AAYMA
RU
Войти

Stone — Saqta Insurance Voice Router

Голосовой агент вымышленной страховой компании.

Доведённый продукт
Команда «Stone» 24💬 0 комментариевс 22 сентября 2026 г.

О проекте

Команда: Stone
Кейс HackAlem.ai: Коммуникации — Halyk Bank · кейс 2
Стадия: Доведённый продукт

Задача кейса: «Voice Router»: голосовой AI, маршрутизирующий звонки в контакт-центре страховой компании

Суть

Голосовой агент вымышленной страховой компании. Распознаёт русскую, казахскую и смешанную речь, LLM маршрутизирует запрос в один из 40 сценариев или 3 системных намерений и извлекает слоты. Затем выполняются мок-действия с подтверждением, ответ озвучивается.

Как устроено

Streamlit пишет звук с микрофона → gpt-4o-transcribe (язык не фиксируется, чтобы не терять смешанную речь) → предварительное определение языка и нормализация телефона → роутер gpt-4o-mini возвращает JSON со сценариями, уверенностью и слотами. Каталог сценариев и RU/KK-примеры передаются в промпт. decision_policy применяет пороги 0,75/0,45. executor проверяет идентификацию и слоты и требует подтверждения перед необратимыми действиями. actions_mock работает с синтетическим бэкендом. Ответ озвучивает gpt-4o-mini-tts, trace-панель показывает тайминги STT/router/TTS.

Ключевые решения

  • LLM intent routing
  • slot filling
  • пороги уверенности
  • multi-intent
  • few-shot примеры в промпте
  • confirmation flow
  • определение языка RU/KK/mixed

Метрики

Dev-набор (104 реплики, официальный evaluate.py): точность основного сценария 99,0% (103/104), полное совпадение списка 97,1%, полнота интентов в многоцелевых запросах 92,3%

Особенности

Оценка сделана официальным evaluate.py, а ручные правила, переписывавшие выбор модели, удалены. Язык ответа выбирается по преобладающему языку клиента. Необратимые действия (create_policy) ждут подтверждения в статусе pending.

Стек

Python · Streamlit · OpenAI API · python-dotenv · unittest

Модели

gpt-4o-transcribe · gpt-4o-mini · gpt-4o-mini-tts


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-8c2ebcfc-stone.

README

README.md

Stone — Saqta Insurance Voice Router

Описание решения и назначение

Веб-демо голосового агента вымышленной страховой компании Saqta Insurance. LLM выбирает сценарии из 40 бизнес-сценариев и трёх системных намерений, извлекает слоты, а приложение выполняет мок-действия над синтетическим датасетом. Основной ввод — микрофон, ответ озвучивается; текст доступен как дополнение. Данные и цены не относятся к реальной страховой компании.

Архитектура

app.py записывает микрофон → backend.speech распознаёт RU/KK/mixed через gpt-4o-transcribe → backend.language предварительно определяет язык, backend.triage нормализует телефон → backend.router через OpenAI API возвращает JSON с выбранными сценариями, уверенностью и слотами → backend.decision_policy применяет пороги 0,75/0,45 → backend.executor проверяет идентификацию и слоты, показывает предварительный результат и запрашивает подтверждение перед необратимыми действиями → backend.actions_mock обращается к синтетическим данным. Язык из LLM-ответа определяет язык реплики бота; для смешанной речи выбирается преобладающий язык клиента. Каталожные вопросы уже двуязычные, динамические данные переводит отдельный слой представления, не выбирающий сценарии. gpt-4o-mini-tts озвучивает ответ. Справа показаны транскрипт, язык входа и ответа, сценарии и времена STT/router/dialog/reply/TTS/total.

Маршрутизация сценариев выполняется LLM. После ответа модели код только проверяет допустимость ID и уверенности, убирает дубли и ставит срочные сценарии первыми согласно ТЗ. Лексические правила не подменяют выбранный моделью сценарий. Обученный encoder-классификатор намерений в проекте не используется.

Используемые технологии

Python 3.11+, Streamlit, OpenAI API, python-dotenv; JSON-файлы из data/case_2/voice_router_dataset служат каталогом сценариев, мок-бэкендом и базой знаний. Данные читаются локально, внешняя база данных не нужна.

Установка

Из корня репозитория:

python -m venv .venv
# Windows PowerShell: .venv\Scripts\Activate.ps1
# macOS/Linux: source .venv/bin/activate
python -m pip install -r requirements.txt

Запуск

Создайте .env в корне репозитория, задайте OPENAI_API_KEY, затем:

python -m streamlit run app.py

Откройте локальный адрес, который выведет Streamlit. Для демо нужен доступ к OpenAI API; личный аккаунт эксперта в приложении не требуется. Разрешите браузеру доступ к микрофону, нажмите запись, произнесите фразу и остановите запись. Ответ появляется текстом и в аудиоплеере; если браузер блокирует автозапуск, нажмите Play. Для телефона нужен HTTPS-адрес приложения (или локальный localhost на том же устройстве), а не HTTP-адрес ноутбука. Поле чата служит запасным вводом.

Зависимости

Зависимости перечислены в requirements.txt. Датасет уже включён в репозиторий. При запуске роутер отправляет реплику и каталог сценариев в OpenAI API; без доступного ключа маршрутизация не работает.

Переменные окружения

ПеременнаяОбязательнаНазначение
OPENAI_API_KEYДаКлюч OpenAI API для роутера, STT, TTS и локализации
ROUTER_MODELНетМодель роутера; по умолчанию gpt-4o-mini
STT_MODELНетРаспознавание; gpt-4o-transcribe
TTS_MODELНетОзвучка с инструкциями языка; gpt-4o-mini-tts
TTS_VOICEНетГолос; alloy
REPLY_MODELНетПеревод динамических данных; gpt-4o-mini

.env исключён из Git. Не помещайте ключ в коммиты и скриншоты.

Развёрнутая версия

Публичное демо (без установки): https://examined-sandwich-rocky-screensavers.trycloudflare.com — временный туннель на локально запущенный app.py, доступен, пока запущен процесс на машине команды. Для гарантированной проверки используйте локальный запуск по инструкции выше.

Порядок проверки основного сценария

  1. Запустите приложение и введите: «Сколько стоит ОГПО для легковой машины в Алматы?». Панель трассировки должна показать SC01; бот запросит недостающие слоты.
  2. Введите ИИН водителя из data/case_2/voice_router_dataset/mock_backend.json и остальные запрошенные данные. Проверьте расчёт стоимости и действия в панели трассировки.
  3. Для проверки подтверждения запросите покупку ОГПО (SC02), предоставьте запрошенные номер автомобиля, ИИН и телефон синтетического клиента. До ответа «да» действие create_policy должно оставаться в режиме pending.
  4. Для проверки системного намерения введите запрос о кредите: ожидается SYS_OUT_OF_SCOPE.

Датасет и полное описание кейса: data/case_2/voice_router_dataset/README.ru.md. Оценка на размеченных репликах:

python predictions.py
python data/case_2/voice_router_dataset/evaluate.py predictions.json data/case_2/voice_router_dataset/dev_utterances.json

Проверка текущего роутера после удаления трёх функций, вручную переписывавших выбор сценария, и добавления каталоговых RU/KK примеров в промпт: 104 реплики dev_utterances.json через OpenAI API и официальный evaluate.py (23.09.2026). Точность основного сценария — 99,0% (103/104); полное совпадение списка — 97,1% (101/104); полнота интентов в многоцелевых запросах — 92,3%. Остались три несовпадения: U034 (SC30 вместо SC17), U086 (пропущен SC31), U093 (пропущен SC33). Это открытая выборка разработки, не независимая итоговая оценка; повторный вызов API может дать другой результат. Веса LLM не дообучались: дополнительные примеры из scenarios.json передаются в контексте запроса.

Переиспользованные компоненты

backend.triage.detect_language() первоначально переиспользован из предыдущего проекта команды AI Firewall; теперь заменён на RU/KK/mixed fallback в backend.language, основной язык полной реплики возвращает LLM. Это вспомогательное определение языка, не классификатор намерений и не основная часть решения. Обученная модель DistilBERT для классификации намерений из того проекта здесь не используется.

Проверка голосового демо

Произнесите последовательно русскую, казахскую и смешанную фразы о страховании. В Trace panel проверьте transcript, language (ru, kk, mixed) и response_language (ru или kk), затем прослушайте ответ. Для KK и смешанной речи с преобладанием казахского вопросы и голос должны быть казахскими; при преобладании русского — русскими. Номер телефона или ИИН сам по себе не меняет язык диалога. Новая русская реплика переключает ответ обратно на русский.

Ошибки распознавания и озвучки видны в интерфейсе; кнопки повтора не выполняют страховую операцию заново. При неточной транскрипции введите исправленную фразу в чат. Автоматическое тестирование без API:

python -m unittest discover -s tests -v

STT API: язык в запросе не фиксируется, чтобы сохранить смешанную речь. Для gpt-4o-transcribe используется JSON; verbose_json/языковые сегменты этой моделью не поддерживаются. TTS API принимает текст ответа и инструкции произношения. Текущая реализация ждёт полный MP3: поле tts означает полное время синтеза, а total включает STT; это не замер времени до первого аудиофрагмента и не подтверждение секундного бюджета ТЗ.

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
48
Авторы
4
Файлы
45
Ветки
11

Авторы коммитов

dariyaska 21befru 18dariyaska 6Dariya 3

История коммитов

  • 2026-09-23 17:59Merge pull request #9 from BAITC-Hacks/codex/remove-hardcode-evaldariyaska
  • 2026-09-23 17:56Resolve main integration preserving LLM-only routingbefru
  • 2026-09-23 17:56Merge remote-tracking branch 'origin/main' into codex/fix-reply-languagedariyaska
  • 2026-09-23 17:55hour 5: larger bannerdariyaska
  • 2026-09-23 17:55Merge pull request #8 from BAITC-Hacks/codex/fix-reply-languagedariyaska
  • 2026-09-23 17:53Fix reply language for clearly Russian and Kazakh requestsdariyaska
  • 2026-09-23 17:51hour 5: localize top-level UI labels to demo language toggledariyaska
  • 2026-09-23 17:49merge: resolve PR #6 conflicts — remove hardcode, adopt multi-slot promptsdariyaska
Все коммиты (48)
  • 2026-09-23 17:47hour 5: add public demo link to READMEdariyaska
  • 2026-09-23 17:43Improve LLM prompt examples and record final dev scorebefru
  • 2026-09-23 17:42Merge pull request #7 from BAITC-Hacks/codex/voice-ru-kk-mixeddariyaska
  • 2026-09-23 17:41hour 4: russian reason field, demo language toggledariyaska
  • 2026-09-23 17:40Fix Russian and Kazakh voice interactiondariyaska
  • 2026-09-23 17:26Remove hardcoded scenario overrides and record fresh evalbefru
  • 2026-09-23 17:22hour 4: remove duplicate junk filesdariyaska
  • 2026-09-23 17:20hour 4: polish UI — branded header, readable trace panel with confidence badgesdariyaska
  • 2026-09-23 17:01Merge PR #3: fix Saqta Voice Router review findingsbefru1
  • 2026-09-23 17:00Merge latest main and preserve router validation retrybefru
  • 2026-09-23 16:55Merge pull request #5 from BAITC-Hacks/codex/router-final-boundariesdariyaska
  • 2026-09-23 16:53Improve router boundary handlingdariyaska
  • 2026-09-23 16:52Allow topic changes during identification and localize promptsbefru
  • 2026-09-23 16:36Retain bilingual catalog examples after main mergebefru
  • 2026-09-23 16:35Merge latest main and retain slot type guidancebefru
  • 2026-09-23 16:32Merge remote-tracking branch 'origin/codex/integration-readme-audit'dariyaska
  • 2026-09-23 16:31Handle malformed live router replies and localize system flowbefru
  • 2026-09-23 16:28Merge current main and resolve router prompt conflictbefru
  • 2026-09-23 16:27Normalize live router slots and preserve queued intentsbefru
  • 2026-09-23 16:17Merge pull request #4 from BAITC-Hacks/codex/router-boundary-fixesdariyaska
  • 2026-09-23 16:15Fix PR review findings across dialog flow and mock actionsbefru
  • 2026-09-23 16:12improve router boundary handlingDariya
  • 2026-09-23 15:40defer SMS until confirmationbefru
  • 2026-09-23 15:37treat empty required slots as missingbefru
  • 2026-09-23 15:32fix router prompt for numeric enum slotsbefru
  • 2026-09-23 15:27hour 3: document setup and harden scenario integrationbefru
  • 2026-09-23 15:13Merge pull request #1 from BAITC-Hacks/codex/router-intent-qualitydariyaska
  • 2026-09-23 15:07hour 2: guard route() call against router validation errorsdariyaska
  • 2026-09-23 14:44Improve bilingual router context and multi-intent handlingDariya
  • 2026-09-23 14:28TEAM_GUIDE WITH CONTEXTdariyaska
  • 2026-09-23 14:24hour 1: router working — 92% full match, 94% primary accuracy on dev setdariyaska
  • 2026-09-23 13:58strturedariyaska
  • 2026-09-23 13:52Add backend scaffoldDariya
  • 2026-09-23 15:07hour 2: actions_mock (31/31 actions), executor confirmation flow, app.py identification/confirmation/slot-mergebefru1
  • 2026-09-23 14:46merge: resolve .gitignore conflict after pullbefru1
  • 2026-09-23 00:42hour 0: env template + finance-track depsdariyaska
  • 2026-09-23 00:41hour 0: db + vectordb skeletonsdariyaska
  • 2026-09-23 00:32hour 0: pin base dependenciesdariyaska
  • 2026-09-23 00:14hour 0: add gitignoredariyaska
  • 2026-09-23 00:13hour 0: project skeleton + READMEdariyaska
Структура репозитория (45 файлов)
.env.example
.gitignore
.streamlit/config.toml
README.md
TEAM_GUIDE.md
app.py
backend/__init__.py
backend/actions_mock.py
backend/confirmation.py
backend/data_loader.py
backend/decision_policy.py
backend/executor.py
backend/language.py
backend/reply_language.py
backend/router.py
backend/slot_normalization.py
backend/speech.py
backend/state.py
backend/triage.py
data/case_2/voice_router_dataset/README.kz.md
data/case_2/voice_router_dataset/README.md
data/case_2/voice_router_dataset/README.ru.md
data/case_2/voice_router_dataset/actions.json
data/case_2/voice_router_dataset/dev_utterances.json
data/case_2/voice_router_dataset/dialogs_sample.json
data/case_2/voice_router_dataset/evaluate.py
data/case_2/voice_router_dataset/knowledge_base.json
data/case_2/voice_router_dataset/mock_backend.json
data/case_2/voice_router_dataset/scenarios.json
data/case_2/voice_router_dataset/slots.json
docs/customer-materials.md
docs/router-quality.md
docs/router-validation.md
docs/voice-validation.md
predictions.py
requirements.txt
tests/router_boundaries.json
tests/test_app_review.py
tests/test_decision_policy.py
tests/test_language.py
tests/test_reply_language.py
tests/test_review_fixes.py
tests/test_router.py
tests/test_voice.py
tests/test_voice_app.py
Ветки (11)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.