Разработка AI-IVR (интеллектуальное голосовое меню)
AI-IVR заменяет дерево тонального меню («нажмите 1, нажмите 2...») на свободный диалог. Клиент говорит что хочет, система понимает намерение и направляет звонок — без нажатия кнопок, без многоуровневых меню.
Сравнение DTMF-IVR и AI-IVR
| Параметр | DTMF-IVR | AI-IVR |
|---|---|---|
| Навигация | 4–7 уровней, кнопки | 1–2 вопроса, речь |
| Покрытие сценариев | Ограничено деревом | Неограниченно |
| Обновление | Сложно | Промпт-файл |
| Для немобильных пользователей | Проблемно | Нормально |
| Стоимость разработки | Низкая | Средняя |
Архитектура AI-IVR
class AIIVR:
def __init__(self, routing_config: dict):
self.destinations = routing_config["destinations"]
self.llm = AsyncOpenAI()
async def handle_call(self, call: IncomingCall) -> str:
"""Обрабатываем входящий звонок — возвращаем destination"""
# Приветствие
await call.say(
"Добрый день! Вас приветствует {company}. Как я могу вам помочь?"
)
# Слушаем намерение (до 8 секунд)
user_input = await call.listen(timeout_sec=8, silence_threshold_ms=800)
if not user_input:
return await self.handle_silence(call)
# Распознаём намерение и маршрутизируем
route = await self.recognize_intent(user_input)
if route["confidence"] >= 0.75:
return await self.route_call(call, route["destination"])
else:
return await self.clarify_intent(call, user_input)
async def recognize_intent(self, user_input: str) -> dict:
destinations_description = "\n".join(
f"- {d['id']}: {d['description']}"
for d in self.destinations
)
response = await self.llm.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "system",
"content": f"""Определи куда направить звонок.
Доступные направления:
{destinations_description}
Верни JSON: {{"destination": "id", "confidence": 0.0-1.0}}"""
}, {"role": "user", "content": user_input}],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
async def route_call(self, call: IncomingCall, destination: str) -> str:
dest = next(d for d in self.destinations if d["id"] == destination)
# Подтверждение маршрутизации
await call.say(dest.get("routing_message",
f"Перевожу вас в {dest['name']}..."))
if dest["type"] == "queue":
await call.transfer_to_queue(dest["queue_id"])
elif dest["type"] == "extension":
await call.transfer(dest["extension"])
elif dest["type"] == "bot":
await call.transfer_to_bot(dest["bot_id"])
return destination
Конфигурация направлений (YAML/JSON)
destinations:
- id: technical_support
name: "Техническая поддержка"
description: "Проблемы с сервисом, ошибки, не работает"
type: queue
queue_id: tech_support_q
routing_message: "Соединяю с технической поддержкой. Ожидайте, пожалуйста."
- id: billing
name: "Оплата и счета"
description: "Вопросы оплаты, счета, задолженности, тарифы"
type: bot
bot_id: billing_bot
- id: sales
name: "Продажи и новые подключения"
description: "Подключить услугу, новый договор, тарифы"
type: queue
queue_id: sales_q
Сроки: AI-IVR с 5–7 направлениями — 2–3 недели. Полная замена DTMF-системы — 4–6 недель.







