Saqta Voice Router
Голосовой AI-робот для контакт-центра страховой компании Saqta Insurance: принимает речь на RU/KK/смешанном языке, выбирает один или несколько из 40…
О проекте
Команда: CyberAgents AI
Кейс HackAlem.ai: Коммуникации — Halyk Bank · кейс 2
Стадия: Рабочий MVP
Задача кейса: «Voice Router»: голосовой AI, маршрутизирующий звонки в контакт-центре страховой компании
Суть
Голосовой AI-робот для контакт-центра страховой компании Saqta Insurance: принимает речь на RU/KK/смешанном языке, выбирает один или несколько из 40 сценариев через LLM и отвечает голосом, с передачей оператору и панелью трассировки.
Как устроено
Браузер записывает звук через MediaRecorder, OpenAI Audio API переводит его в текст, после чего LLM-роутер со Structured Output выбирает сценарии из scenarios.json. Роутер учитывает description, правила-границы not_this_if, историю диалога, активный сценарий и уже собранные слоты. Decision Policy и детерминированный Scenario Executor обрабатывают quote/read-only сценарии (ОГПО, travel, статус заявки, поиск офиса), необратимые действия требуют подтверждения. Ответ озвучивается через TTS, Supervisor Trace показывает confidence, альтернативы и задержку на каждом этапе.
Ключевые решения
- LLM semantic routing
- Structured Outputs
- multi-intent detection
- slot extraction
- dialog state
- not_this_if boundary rules
- confirmation guard
- simulated operator handoff
- evaluation на 104 dev utterances
Метрики
Primary accuracy 96.154%, Full match 94.231%, Multi-intent recall 92.308%, median router latency 1481 ms (104 dev utterances)
Особенности
Вместо intent-классификатора используется LLM-роутинг с явными правилами-границами not_this_if для каждого сценария. Есть воспроизводимый бенчмарк на dev-выборке и офлайн smoke-check детерминированного исполнителя. Задержка меряется по этапам: STT, роутер, TTS до первого звука и полный голосовой ход.
Стек
Python · FastAPI · Uvicorn · HTML/CSS/JavaScript · Docker · Docker Compose
Модели
OpenAI API · OpenAI Speech-to-Text · OpenAI Text-to-Speech
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-4808fff1-cyberagents-ai.
README
README.mdSaqta Voice Router — HackAlem AI
Гибридный голосовой AI-ассистент для страхового контакт-центра Saqta Insurance.
Система принимает голосовые и текстовые обращения на русском, казахском и в mixed RU/KK речи, преобразует голос в текст, использует LLM для выбора бизнес-сценария и возвращает голосовой ответ.
Главная идея решения: вместо классического intent-классификатора используется LLM routing layer, который учитывает смысл реплики, границы сценариев, multi-intent и состояние диалога.
Возможности
- 40 бизнес-сценариев Saqta Insurance
- RU / KK / mixed-language routing
- Voice input через STT
- Voice output через TTS
- LLM-based semantic routing
- Multi-intent detection
- Structured Output
- Dialog state
- Slot extraction
- Out-of-scope / unclear / goodbye system intents
- Scenario boundary handling через
not_this_if - Deterministic scenario executor для ключевых quote/read-only flows
- Simulated operator handoff с сохранением контекста
- Confirmation guard для необратимых действий
- Supervisor Trace для объяснимости решения
- Confidence score и alternatives
- Измерение router latency
- Cross-browser microphone MIME negotiation
- Web UI с микрофоном и текстовым fallback
- Evaluation pipeline на 104 dev utterances
- Docker / Docker Compose
.env-based secret management
Последний измеренный routing benchmark
Полный прогон data/dev_utterances.json — 104 тестовых высказывания. Ниже — последний сохранённый benchmark маршрутизации до финального hardening. Live UI отдельно измеряет STT, router/response, TTS-to-first-audio и полный voice turn:
| Metric | Result |
|---|---|
| Primary accuracy | 96.154% |
| Full match | 94.231% |
| Multi-intent recall | 92.308% |
| Router median latency | 1481 ms |
Маршрутизатор тестируется на русских, казахских и mixed-language запросах, включая multi-intent и системные сценарии.
Архитектура
┌──────────────────────┐
│ Browser UI │
│ Voice + Text input │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ STT │
│ OpenAI Audio API │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ LLM Router │
│ │
│ RU / KK / mixed │
│ Multi-intent │
│ Structured Output │
└──────────┬───────────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
scenarios.json Dialog State Boundary Rules
+ Slots + not_this_if
│ │ │
└────────────────┼────────────────┘
▼
┌──────────────────────┐
│ Decision Policy │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Scenario Executor │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ TTS │
│ OpenAI Audio API │
└──────────────────────┘
└────► Supervisor Trace
LLM Router
Router не работает как простой keyword classifier.
При выборе сценария учитываются:
- semantic meaning текущей реплики;
descriptionсценария;not_this_if/ boundary rules;- история диалога;
- активный сценарий;
- уже известные slots;
- RU / KK / mixed speech;
- multi-intent обращения.
LLM возвращает structured decision, включающий:
{
"language": "ru",
"scenarios": [
{
"scenario_id": "SC06",
"confidence": 0.9,
"reason": "Travel insurance purchase"
}
],
"alternatives": [],
"slots": {}
}
Supervisor Trace
Web UI показывает технический trace каждого решения:
- transcript;
- detected language;
- scenario ID;
- confidence;
- alternatives;
- routing reason;
- extracted slots;
- STT latency;
- router latency;
- response latency;
- TTS-to-first-audio latency;
- end-of-user-turn → first-audio latency для voice turns.
Это позволяет оператору или жюри видеть, почему AI выбрал конкретный сценарий.
Соответствие must-have HackAlem
| Требование | Реализация |
|---|---|
| Голосовое взаимодействие в вебе | Browser MediaRecorder → STT → LLM Router → TTS |
| LLM-слой выбора сценария | Structured LLM routing по каталогу 40 сценариев, без encoder intent classifier |
| Корректность выбора | scripts/evaluate_dev.py, raw и accepted predictions |
| Панель трассировки | transcript, proposed/accepted scenarios, reason, alternatives, slots, handoff, latency |
| Русский / казахский / mixed | Router принимает ru, kk, mixed; reply language передаётся в TTS |
| Безопасность | необратимые действия не выполняются без явного подтверждения |
| Передача оператору | simulated handoff с queue + reason в Supervisor Trace |
| Запуск | run.bat, bash run.sh, Docker Compose |
Быстрый запуск
Windows
Создать виртуальное окружение:
python -m venv .venv
Активировать:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\.venv\Scripts\Activate.ps1
Установить зависимости:
python -m pip install --upgrade pip
pip install -r requirements.txt
Создать .env:
Copy-Item .env.example .env
Добавить API key:
OPENAI_API_KEY=your_key_here
Запустить:
.\run.bat
Открыть в браузере:
http://localhost:8000
macOS / Linux
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
bash run.sh
Docker Compose
docker compose up --build
Evaluation
Быстрая проверка первых 10 примеров:
python scripts/evaluate_dev.py --limit 10
Полный benchmark:
python scripts/evaluate_dev.py
Evaluation сохраняет raw + accepted predictions и рассчитывает:
- Primary accuracy
- Full match
- Multi-intent recall
- Median router latency
Offline smoke-check
Без внешних API можно проверить детерминированный executor:
python scripts/smoke_check.py
Проверяются OGPO quote, travel quote, claim status и office lookup на синтетических данных.
Demo scenarios
1. Автострахование
Сколько стоит обязательная страховка на машину?
Expected route:
SC01
2. Travel insurance
Мне нужна страховка для поездки за границу.
Expected route:
SC06
3. Kazakh
Шетелде аяғымды сындырып алдым, сақтандыруым бар.
Expected route:
SC15
4. Out of scope
Можно у вас взять кредит на машину?
Expected route:
SYS_OUT_OF_SCOPE
5. Multi-intent
Router поддерживает несколько независимо actionable intents в одной реплике и возвращает массив сценариев.
Структура проекта
voice-router-saqta/
├── app/
│ ├── main.py
│ ├── router.py
│ ├── assistant.py
│ ├── executor.py
│ ├── audio.py
│ ├── session.py
│ ├── schemas.py
│ ├── data_store.py
│ ├── config.py
│ └── static/
│ └── index.html
├── data/
│ ├── scenarios.json
│ ├── slots.json
│ ├── actions.json
│ ├── knowledge_base.json
│ ├── mock_backend.json
│ └── dev_utterances.json
├── scripts/
│ ├── evaluate_dev.py
│ └── smoke_check.py
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── run.bat
├── run.sh
└── .env.example
Security
Секреты не хранятся в репозитории.
.env исключён через .gitignore.
Для запуска используется .env.example, в который не включаются реальные API keys.
Tech stack
- Python
- FastAPI
- Uvicorn
- OpenAI API
- Structured Outputs
- OpenAI Speech-to-Text
- OpenAI Text-to-Speech
- HTML / CSS / JavaScript
- Docker
HackAlem AI
Проект разработан для кейса Voice Router — гибридный голосовой AI-робот с LLM-слоем выбора сценария.
Основной фокус решения — высокая точность semantic routing при живой RU / KK / mixed речи и минимальной задержке.
Safety and current scope
- Все данные в
data/синтетические. - Необратимые действия не выполняются молча: требуется явное подтверждение клиента.
- Handoff в веб-демо моделируется очередью оператора и отображается в Supervisor Trace.
- Реализованы детерминированные расчёты/поиски для ключевых quote/read-only сценариев; остальные сценарии продолжают безопасный grounded flow.
.envисключён из Git и Docker build context через.dockerignore.
Авторы коммитов
История коммитов
- 2026-09-23 17:45fix: repair schemas syntax and trace fieldsdosssymzhan
- 2026-09-23 17:40docs: map implementation to hackathon must-have criteriadosssymzhan
- 2026-09-23 17:39feat: measure STT router TTS and end-to-end voice latencydosssymzhan
- 2026-09-23 17:38chore: remove nonessential CI workflow from hackathon submissiondosssymzhan
- 2026-09-23 17:35ci: add reproducible syntax and offline smoke checksdosssymzhan
- 2026-09-23 17:35docs: include executor and smoke check in project structuredosssymzhan
- 2026-09-23 17:35fix: stabilize repeated voice recording and include STT tracedosssymzhan
- 2026-09-23 17:33docs: align README with implemented executor and safetydosssymzhan
Все коммиты (35)
- 2026-09-23 17:33fix: align supervisor trace with accepted routedosssymzhan
- 2026-09-23 17:32Delete DELETEdosssymzhan
- 2026-09-23 17:32chore: make unix launch deterministicdosssymzhan
- 2026-09-23 17:32chore: make windows launch deterministicdosssymzhan
- 2026-09-23 17:32chore: protect secrets from docker build contextdosssymzhan
- 2026-09-23 17:32test: add offline executor smoke checksdosssymzhan
- 2026-09-23 17:32fix: evaluate accepted routes and correct mediandosssymzhan
- 2026-09-23 17:31fix: harden chat trace and async audio processingdosssymzhan
- 2026-09-23 17:31fix: complete dialog slot handling and scenario executiondosssymzhan
- 2026-09-23 17:31fix: improve continuation context and invalid-route fallbackdosssymzhan
- 2026-09-23 17:31fix: expose canonical slot schema to LLM routerdosssymzhan
- 2026-09-23 17:30fix: expose canonical slot schema to LLM routerdosssymzhan
- 2026-09-23 17:30fix: strengthen dialog state and trace schemadosssymzhan
- 2026-09-23 17:29fix: add grounded scenario executordosssymzhan
- 2026-09-23 17:14Create DELETEdosssymzhan
- 2026-09-23 16:51Delete voice-router-saqta directorydosssymzhan
- 2026-09-23 16:42fix: improve cross-browser microphone recordingDossymzhan
- 2026-09-23 15:57feat: integrate Saqta Voice Router into hackathon mainDossymzhan
- 2026-09-23 15:53docs: finalize hackathon README and benchmark resultsDossymzhan
- 2026-09-23 15:44Update README.mdDoskhan Dosmaganbet
- 2026-09-23 15:28Revert "fix: improve dialog continuation and slot handling"Dossymzhan
- 2026-09-23 15:26fix: improve dialog continuation and slot handlingDossymzhan
- 2026-09-23 15:24Delete voiceDoskhan Dosmaganbet
- 2026-09-23 15:09Create voicedosssymzhan
- 2026-09-23 14:53chore: setup environment ignoreDoskhan
- 2026-09-23 14:52feat: initial Voice Router with LLM routingDossymzhan
- 2026-09-23 13:58Add files via uploaddosssymzhan
Структура репозитория (30 файлов)
.dockerignore .env.example .gitignore Dockerfile README.md app/__init__.py app/assistant.py app/audio.py app/config.py app/data_store.py app/executor.py app/main.py app/router.py app/schemas.py app/session.py app/static/index.html data/ORIGINAL_README.ru.md data/actions.json data/dev_utterances.json data/dialogs_sample.json data/knowledge_base.json data/mock_backend.json data/scenarios.json data/slots.json docker-compose.yml requirements.txt run.bat run.sh scripts/evaluate_dev.py scripts/smoke_check.py
Ветки (2)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.