chat-agent · состояние после C4 · 06.10.2026
chat-agent: от запроса к ответу
Чат принимает текст или голос, показывает ответ по частям и сохраняет историю. Исполнение ограничено очередями и общим сроком. Распознавание, модель, TURN и OAuth остаются у прежних внешних владельцев.
Код: src_core/main.py · stack/webrtc.drs
chat-agent · состояние после C4 · 06.10.2026
Два стэка связаны общим NATS
Диалогом и аудиоподключениями владеет chat-agent. Voice принимает прежний PCM-контракт и возвращает partial/final. Разделение позволяет менять чат без поставки voice; общий NATS и его доступность остаются общей зависимостью.
Код: stack/webrtc.drs · src_shared/audio.py · src_core/audio_admission.py
Схемы и контракты · сверка 06.10.2026
Модель вызываем через Ruby, части ответа идут в Agent
Core передаёт текст или ASR final в Agent. Ruby вызывает LLM и получает проверенный ответ; части текста параллельно идут прямо в Agent через NATS. Обычный разговор требует одной генерации, tools могут потребовать следующих. История хранится в PostgreSQL, текущая попытка - в памяти Agent.
Код: Agent + stream · Ruby RPC · LLM reply / delta · состояние попытки
chat-agent · состояние после C4 · 06.10.2026
Инструменты выбирает модель, проверяет сервер
Ruby получает каталог через nats.tools.discover, проверяет имена и JSON-аргументы до исполнения всего набора вызовов. Затем последовательно вызывает nats.tools.{name}. Пять tools пока возвращают демонстрационные fixtures. Активные и pending-графы сохранены; общий срок 120 s, бюджет до 10 действий.
Код: src_langgraph_rb_node/lib/src_langgraph_rb_node/runtime/dialog.rb · src_api_gateway/main.py · src_shared/contracts/tools.py
Схемы и контракты · сверка 06.10.2026
Два аудиотранспорта сходятся в один PCM-контракт
WebRTC передаёт защищённый RTP; codec согласуется в SDP. WSS передаёт mono PCM16LE с частотой браузера. Каждый ingress отдельно переводит звук в 16 kHz и пакует его для NATS. Общий PCM-модуль - код внутри ingress; Core выдаёт допуск, но не принимает медиапакеты.
Код: WebRTC · WSS · PCM envelope · admission
Схемы и контракты · сверка 06.10.2026
Четыре адреса - четыре разных потока данных
| Адрес на chat-agent.gis-master.ru | Кто принимает | Что передаётся |
HTTPS POST /core/offer | WebRTC ingress | JSON с SDP offer → SDP answer |
WSS /core/ice/{connection_id} | WebRTC ingress | JSON auth / candidate / end |
WSS /audio/ws | WSS ingress | start JSON → binary PCM16LE → end JSON |
WSS /ws | Общий NATS | Протокол NATS; payload событий - JSON |
База HTTPS: https://chat-agent.gis-master.ru; для сокетов - wss://chat-agent.gis-master.ru. Все четыре маршрута проходят OAuth. ICE дополнительно проверяет token подключения. /ws возвращает статусы и ответ, /audio/ws передаёт звук. Текст, история и отмена идут в остальные /core/*, которые обслуживает Core.
Код: routes / OAuth · ICE JSON · PCM start/end · NATS over WSS
Схемы и контракты · сверка 06.10.2026
Voice возвращает текст, Core запускает диалог
Ingress публикует звук в webrtc.komaroff.asr.stream.{session_id}. Voice выделяет фразы и отправляет PCM к GPU по NATS; ответ возвращает в Core как JSON. Partial показываем в UI, непустой final запускает Agent один раз. Файловый API voice и диаризация в live-путь не входят.
Код: voice bridge · GPU contract · final → Agent · NATS remap
Схемы и контракты · сверка 06.10.2026
Части ответа и окончательный результат идут отдельно
Agent публикует response_fragment, request_state, итог message и команды client. Core публикует asr_result и audio_status в тот же nats.events.user123. Frontend проверяет session/request/attempt/generation/sequence до показа текста и команд карты. После reconnect берёт snapshot или историю; replay UI-событий здесь нет.
Код: fragments / snapshot · итог / команды · ASR / audio status · фильтр UI
Было → исправлено
Основные ошибки были в управлении работой
| Проблема | Изменение |
| Router генерировал отдельно от ответа | dialog_step: текст либо tools за одну генерацию |
| Agent последовательно ждал независимые чаты | Три исполнителя, очередь по сессиям, общий срок |
| UI принимал ответы и статусы соседей | Проверка session/request/generation до отображения |
| Каждый PCM-пакет вызывал flush | FIFO, publish сразу, flush раз в 250 мс |
Исправления убрали лишнее ожидание и сделали границы работы явными. Один долгий запрос больше не занимает единственный Agent callback. Общий NATS account сохранён: фильтр UI решает смешивание сообщений, но отдельные права каждого пользователя ещё нужны.
Код: dialog.rb · execution.py · requestState.ts · audio.py
Замеры C3 · 06.10.2026
Диалог ускорился, распознавание сохранило свою задержку
| C0 → C3, секунды | p50 | p95 |
| Обычный текст, n=12 | 14,97 → 3,11 | 20,95 → 3,98 |
| ASR final → ответ | 46,01 → 14,10 | 89,40 → 23,23 |
| RTC connected, n=12 | 1,39 → 1,63 | 1,56 → 1,88 |
| Начало WAV → ASR final | 3,80 → 3,82 | 3,99 → 4,02 |
В той же контрольной серии C3 завершил 33/33 хода с 36 генерациями. Обычный ответ ускорился благодаря одной генерации и новым очередям. Trickle был поставлен раньше; подключение здесь немного медленнее C0, но ниже цели 3 с. ASR p95 после конца WAV вырос на 2,8%. Короткая синтетическая речь иногда искажается; WER/DER не измерены.
Evidence: приёмка C3 · browser measurements · cases.json
Исправление C4 · Core и два аудио-ingress
Healthcheck больше не запускает Python
Каждые 10 секунд Docker проверяет Core и оба ingress. Для одного локального HTTP-запроса раньше запускался Python; теперь работает curl. Полный HTTP 200 и готовность NATS остались обязательными. В 90 пробах реальных образов CPU одной проверки был ниже 29 мс; это снизило фоновую нагрузку всего стэка.
Код: Core Dockerfile · ingress Dockerfile · проверки отказов · результаты C4
Итог после C4 · весь стэк · 06.10.2026
После healthcheck CPU в простое снизился на 75%
| Показатель и база сравнения | До → после |
| CPU в простое, перед → после C4 | 0,197 → 0,049 ядра, -75,0% |
| Память в простое, перед → после C4 | 547,57 → 553,41 МБ, +1,1% |
| Сумма rootfs образов, C0 → C4 | 3 685,21 → 3 256,25 МБ, -11,6% |
| Активный production-код, C0 → C4 | 14 762 → 15 890 строк, +7,6% |
CPU и память сравнили в одинаковых окнах простоя по 180 с: 13 сервисов, без активных запросов. RAM не сократилась. Сама пересборка healthcheck добавила 4,27 МБ rootfs относительно C3. Rootfs повторно учитывает общие слои, без томов и внешних моделей; свежий compressed-размер C4 не подтверждён. Полная серия диалога относится к C3, после C4 прошли короткие проверки текста, RTC и WSS.
Замеры: метод и результат C4 · CPU / RAM / runtime · подсчёт production-кода
Управление
←/→, Page Up/Page Down и Space переключают слайды. Home и End переходят к краям. F включает полный экран. Escape закрывает это окно.