webrtc-komaroff
От голоса к действию
Вы говорите: «Покажи ближайшие аэропорты». webrtc-komaroff должен распознать реплику, выбрать сценарий и показать результат на карте.
Одна реплика — несколько границ
Этот путь проходит через несколько сервисов. Каждый отвечает за свою часть: соединение, распознавание, состояние разговора или выполнение инструментов.
Core принимает живой звук
Браузер передаёт микрофон по WebRTC. Сервис Core завершает соединение и превращает звук в короткие пакеты для распознавания.
20 миллисекунд в одном кадре
В текущем формате кадр содержит двадцать миллисекунд звука. Пакеты идут через брокер сообщений NATS в соседний проект распознавания.
Whisper bridge выделяет фразу
Там детектор речи отделяет голос от тишины. Когда фраза закончена, сервис отправляет её внешнему распознавателю LinTO и получает текст.
Голос и текст сходятся
Теперь голосовой и текстовый запросы идут одним путём. Core передаёт Агенту текст и идентификаторы сессии и реплики.
Agent хранит разговор
Агент загружает состояние диалога из базы PostgreSQL. Так следующий вопрос может продолжить предыдущий сценарий, а не начинать разговор заново.
Workflow выбирает следующий шаг
Дальше работает сценарный движок. Он решает, какой инструмент нужен, какие данные уже есть и что ещё спросить у пользователя.
Модель разбирает намерение
Для нового запроса об аэропортах текущий сценарий обращается к языковой модели дважды: сначала выбирает намерение, затем извлекает параметры поиска.
Инструмент возвращает данные
Сам поиск выполняет инструмент по каталогу аэропортов. Модель не должна придумывать координаты. Маршрут строится только при явном запросе пользователя.
Результат приходит событием
Агент сохраняет результат и публикует команды интерфейсу. Браузер получает событие и обновляет сообщение или карту. Ответ по HTTP — отдельная часть обмена.
Стенд, а не источник авиационных данных
Здесь есть важная граница. Позиция, погода и рейсы в проверенном коде демонстрационные. Нарисованный маршрут не является дорожным маршрутом или инструкцией для полёта.
Меньше ожидания перед стартом
Первое небольшое улучшение — начальная загрузка карты. Сейчас два запроса идут последовательно. Переиспользование соединения и параллельное выполнение уберут лишнее ожидание.
Очередь должна иметь предел
Более серьёзная проблема — перегрузка. Семафор ограничивает активные вызовы, но ожидающие задачи уже созданы. Нужен предел очереди до приёма новой работы.
Один turn — один сохранённый результат
Ещё важнее запись результата. Состояние и история сохраняются раздельно. При сбое повтор может снова вызвать сценарий. Нужны общая транзакция и защита от повторного исполнения.
Три движка увеличивают цену изменений
В репозитории три реализации сценарного движка. Прежде чем удалять две, надо сравнить поведение и проверить их пользователей. Переименование каталогов эту работу не заменяет.
Упростить границу диалога
Следующий вариант — объединить Агент и выбранный сценарный движок. Исчезнет один сетевой переход, но пользу нужно измерить. Медиасоединения и модели разумно оставить отдельно.
Измерить, затем менять
Начинать стоит с очередей и корректности повторов. Затем считать вызовы модели, задержку ответа и ошибки. Полное переписывание без этих измерений пока не обосновано.
От фразы до понятного результата
Так короткая просьба превращается в цепочку проверяемых действий. Этот разбор основан на снимке кода. Он объясняет устройство проекта, но не подтверждает состояние работающего кластера.