Голосовые системы

Правки для согласования · версия 2 · 30.10.2026

Это уточнённый план и локальные макеты. Исходники проектов, GPU, runtime, образы и расширение не менялись. Рекомендации по Nemotron и исходному PCM из предыдущего REPORT.md заменены решениями пользователя ниже.

Принятые решения

Направление Решение
Nemotron Исключить из этой работы. Не загружать и не интегрировать.
GigaAM Large Подготовить отдельное сравнение large_ctc 600M с текущими моделями. В этой итерации — проверка исходников и план эксперимента.
Silero Оставить нынешний Silero/ONNX Runtime Web/WASM.
Opus Проектировать передачу и хранение одного Opus-потока. Архив содержит именно принятые пакеты, из которых сервер получил вход ASR. Исходный PCM Chrome постоянно не дублируем.
Monitor На верхнем уровне — транскрипции и команды; внутри — сводка, журнал и хорошо видимая схема вызовов.
Реализация Пока только согласование и макеты. Загрузка новой модели в production GPU и внедрение отложены.

1. Monitor: два уровня вместо общей простыни

Верхний уровень — процессы сессии

Один блок — одна транскрипция либо одна команда:

[Транскрипция] Найди форму и поставь ей фон с котом.
Готовая фраза → текст: …    Запросы / ответы: …    События / ошибки: …
                                     [Открыть журнал] [Схема вызовов]

[Команда] Найди форму и поставь ей фон с котом.
Команда → ответ: …          Запросы / ответы: …    События / ошибки: …
                                     [Открыть журнал] [Схема вызовов]

Транскрипция связана с созданной из неё командой через сохранённые идентификаторы. В каждой странице есть переход к соседнему процессу. Для текста существует только команда; для ошибки ASR — только транскрипция с причиной и состоянием «Команда не отправлена». Отдельные аудиофразы не объединяются в один большой блок потока.

Верхние фильтры:

  • Все процессы / Обработка звука / Обработка команд.
  • Состояние: в работе, готово, ошибка; при внедрении также реальные отменённые/прерванные состояния.
  • Источник: голос или текст.
  • Поиск: текст, request_id, phrase_id.
  • Сортировка: ранние, поздние, дольше обрабатывались, ошибки в начале. Время относится к подписанному процессу, а не ко всему захвату.
  • Существующий контекст сессии, потока, интервала и live/pause сохраняется. Макет показывает фиксированный демонстрационный снимок.

Chat UI, NATS events и отдельные subjects перемещаются в технический уровень. Они не смешиваются с фильтрами пользовательских процессов. Служебные события без доказанной связи с фразой/командой остаются доступными в существующем служебном представлении; их нельзя молча выбросить или приклеить к ближайшей фразе по времени.

Отдельная страница выбранного процесса

  1. Заголовок [Транскрипция] — текст или [Команда] — текст, статус, модель и копируемые существующие ID.
  2. Краткий итог: счётчики, основные интервалы, отдельное число вызовов модели/инструментов.
  3. Объяснение вложенных интервалов и, для аудио, запись/диагностика.
  4. Журнал / Схема вызовов — постоянно видимый переключатель.
  5. Локальные фильтры: участник, тип сообщения, направление наблюдения, отсутствие отметки, поиск subject/адреса/ID, ранние/поздние.
  6. Быстрые технические срезы: Все каналы / Chat UI / NATS events / HTTP-модель.

Переход — отдельный URL состояния страницы. Назад возвращает фильтры и место в списке. Переключение журнала и схемы сохраняет фильтр. В макете это разные hash-страницы одного автономного HTML; в проекте используем существующую маршрутизацию Monitor.

Что видно в каждой передаче

Отправлено из                           Получено в
Gateway                          →     Audio Ingress
chat-agent_src_api_gateway              chat-agent_audio_ws_ingress
10:18:02.003                            10:18:02.005

NATS · chat.browser.audio

На схеме направление задаёт стрелка, на концах — участники. Subject/URL и протокол находятся на стрелке; полный адрес доступен при выборе. Для отсутствующей отметки явно показывается «Отправка/получение не зафиксировано». Известный адресат не считается доказательством доставки. Разность часов двух сервисов не выдаётся за сетевую задержку.

Подтверждённые отправку и получение можно показать рядом в одной передаче. Уже существующий transitions() делает это только при совпадающем parent_event_id, маршруте, subject, протоколе и типе. Оба исходных наблюдения остаются доступны в деталях. Новое эвристическое сопоставление не нужно.

Источник: exchangeModel.ts.

Счётчики без удвоения

  • «Запросы / ответы» — количество уникальных передач соответствующего типа внутри процесса. Подтверждённая отправка и её получение считаются один раз.
  • Один запрос пользователя проходит несколько сервисов, поэтому число передач не равно числу вызовов модели. Для ASR, LLM и инструментов нужны отдельные подписанные счётчики.
  • Подтверждение приёма и итоговый результат могут быть разными сообщениями. Не требовать искусственного равенства запросов и ответов.
  • Отдельно показывать служебные события, ошибки и при инспекции — число наблюдений.
  • Если связи или страницы журнала неполны, указывать неполноту. Не выдавать число загруженных строк за итог всего процесса.
  • Фильтры журнала меняют надпись «показано N из M», но не пересчитывают общую сводку блока в незаметно другой смысл. Верхние фильтры выбирают целые процессы.

Время: что в что входит

Транскрипция:

Значение Граница измерения
После конца речи → текст Последний речевой отсчёт → показ текста; это пользовательская задержка
Окончание фразы Последний речевой отсчёт → отправка конечной границы; включает фактическое ожидание, а не только настроенные 450 мс
Готовая фраза → текст Отправка конечной границы → показ текста; часть предыдущего общего интервала
Обмен с ASR Вложенный серверный обмен; уже включает модель
Чистое распознавание Полное выполнение вызова модели, включая генератор результата; без очереди и транспорта
Кодирование, декодирование, PCM, очередь, показ Только самостоятельные подтверждённые измерения с пояснением области

В примере макета 704 = 450 + 254 мс, а 163 мс модели уже входят в 254 мс. Это учебные числа, не новый benchmark. В реальности между последним речевым отсчётом и отправкой границы могут быть обработка VAD и выпуск последнего кадра кодека: нельзя подставлять настройку паузы вместо измеренного интервала.

Длительность произнесения и внутренних пауз — длительность аудио, не время вычислений. VAD/кодирование выполняются во время захвата и могут перекрываться с передачей; их нельзя автоматически прибавлять к задержке после конца речи.

Команда: от отправки команды до показа итогового ответа, отдельно — очередь, работа LLM, инструменты и отображение. Транскрипция сюда не включается. Суммы CPU/GPU-работы при параллельном исполнении не равны длительности на часах.

Подготовка соединения и закрытие диагностики показываются отдельно, как в ASR Compare. Для постоянно подключённого плагина они не добавляются к каждой фразе. Где нет конечных отметок, показывается «Нет измерения»/«Ожидается», а не ноль или разность несвязанных событий.

Источник действующей семантики: asrCompare/timeline.ts.

Как сделать без новой архитектуры

Расширить существующий SessionSequence, его operations()/transitions() и текущую проекцию запросов/аудиофраз. Сохранять session_id, stream_id, phrase_id, request_id, operation_id; не создавать новую систему trace ID, таблицы или дублирующий журнал.

В нынешнем коде страницы запросов имеют переключатель, а поток создаёт компонент с фиксированным 'events'. Предлагаемое исправление: видимые кнопки «Журнал / Схема вызовов» и прямой вход в схему из блока; раскрывать техническую секцию для доступа к ним больше не потребуется. До внедрения production-страница остаётся прежней.

2. Opus: пересмотренный архивный контракт

Согласованное изменение: «Исходная запись» теперь означает принятый Opus-поток, послуживший входом распознавания, а не несжатые отсчёты Chrome. Название в UI — «Запись для распознавания». Формат и преобразования видны рядом с проигрывателем.

Предлагаемый первый профиль: mono, 48 кГц, Opus 32 кбит/с, кадр 20 мс. Это начальные параметры для эксперимента, не утверждение о достаточном качестве. 24 кбит/с проверять только после сравнения 32 кбит/с с PCM.

Микрофон Chrome
  ├─ аналитическая копия → прежний Silero WASM → координаты фразы
  └─ Opus encoder → существующий бинарный NATS/WebSocket-транспорт
                    ↓ Audio Ingress
                    ├─ те же закодированные пакеты → существующий архив
                    └─ один постоянный decoder захвата → диапазон фразы
                                                       → прежняя подготовка 16 кГц
                                                       → прежнее batch-задание ASR
  • Один Opus encoder на захват. Проверить WebCodecs до включения микрофона; незаметного переключения формата нет. Silero получает свою аналитическую копию и не изменяет звук ASR.
  • Сначала использовать имеющийся Worker и существующий транспорт. Дополнительное NATS-соединение или менеджер кодеков не нужны. Окончательное размещение encoder проверить на задержках VAD/захвата, не считать отсутствие нового Worker самоцелью.
  • В Audio Ingress уже есть PyAV 14.2.0; сначала проверить наличие Opus decoder в текущей сборке. Использовать его, если поддерживается, без нового сервиса и универсальной codec-обвязки.
  • Архив получает именно входные Opus-байты, без повторного кодирования. PCM используется в ограниченных рабочих буферах и отдельно постоянно не сохраняется.
  • Версию и формат обозначить в существующем аудиоконтракте. Нельзя молча отправлять Opus под контрактом pcm16le. Точные изменения бинарного заголовка/subject утвердить после адресной проверки producer/consumer; имена на макетах описывают нынешние управляющие связи, а не уже выпущенный Opus-протокол.
  • Сохранить последовательность, размеры, хеши, частоту, число каналов, codec config, timestamp/duration, priming/pre-skip и конечное обрезание. Координаты фразы остаются в аудиоотсчётах и учитывают задержку кодека.
  • Подтверждать границу после получения всех относящихся к ней закодированных пакетов. Не ждать сохранения БД для начала ASR.
  • При выключении корректно выпустить хвост encoder. Повреждение/пропуск пакета — явная ошибка, без подстановки искусственного звука в команду.
  • Исторические PCM-записи остаются читаемыми по сохранённому формату. Новую историю в PCM не перекодировать; архивы Opus упаковывать для скачивания без re-encode.

Повтор фразы: у Opus есть состояние. Для первого доказуемого варианта сервер потоково декодирует сохранённую последовательность от начала записи до нужного диапазона, сохраняя ограниченную память. Это может замедлить переход к поздней фразе длинной записи — ограничение нельзя скрывать. Random access с pre-roll проверить отдельно до внедрения в Monitor; произвольный пакет не является точной заменой состояния decoder.

В диагностике проигрывание входа ASR выбранной фразы формируется сервером из того же декодированного/подготовленного диапазона. WAV для проигрывателя — производное представление, не второй постоянный архив. Для повторов сверять хеш входного PCM после одинаковой версии decoder/resampler. Разные браузерные декодеры не объявлять побайтово идентичными серверному.

Используем существующие метаданные и блоки архива. До реализации проверить ограничения текущей схемы, которые предполагают постоянные байты на отсчёт; их нельзя оставить как для PCM. Новых таблиц или служб по умолчанию не требуется.

Источники: WebCodecs Opus — пакеты и priming, Ogg Opus — pre-skip, end trimming и seeking, зависимости ingress, подготовка текущего batch.

Проверка перед внедрением: один PCM-образец и одни границы → baseline PCM и Opus32 → одна модель/настройки. Измерить полезные и wire-байты, encode/decode CPU, задержку последнего пакета, очередь, ASR, последний речевой отсчёт → текст, WER/CER. Проверить 90 мс/1 с, начало/конец слова, длинную запись и seek. Не обещать ускорение модели от сетевого сжатия.

3. GigaAM Large: адресная проверка

Кандидат — ai-sage/GigaAM-Multilingual, ветка large_ctc, ревизия 3905cd51c3ed4e88c8edf33f3302969ba480a327. Веса 2,34 ГБ. Исходный снимок GPU от 10:50 MSK показывал 11,66 ГиБ свободно в ASR-разделе; перед экспериментом память проверить заново.

Дополнительная проверка исходника модели подтвердила: используются GigaAMModel/GigaAMASR, CTCGreedyDecoding, а класс ASR предоставляет head и decoding, как и текущий адаптер RNNT. Это основание попробовать небольшой явный профиль загрузки/параметров вместо нового inference-фреймворка. Совместимость установленных torch/transformers ещё требует import/load проверки; автоматически обновлять общие зависимости по примеру из README не следует.

Порядок будущего эксперимента:

  1. Закрепить файлы и хеши модели, проверить импорты в изолированном окружении. Не подменять действующий GigaAM.
  2. Один контролируемый load в разрешённом бюджете GPU: память до/после/пик, холодный запуск. OOM не должен затронуть текущие модели.
  3. Одни PCM16 16 кГц, одни границы и тексты-эталоны: текущий RNNT, новый CTC, Turbo. Сначала PCM, отдельно от Opus, чтобы не смешать причины различий.
  4. Короткие команды, тихая речь, имена, числа, шум, паузы; длительности 1/5/15/30 секунд. Отдельно cold/warm, медиана/p95 чистого ASR и памяти. Пунктуация и нормализация оцениваются отдельно от WER.
  5. Вход напрямую массивом через decoder, без повторного VAD, WAV/base64-круга и фильтрации текста по score.
  6. По результату решить: добавить альтернативную модель, заменить нынешнюю или отказаться. Решение о замене заранее не принято.

Поддержка общего класса проверена по исходнику закреплённой модели и нашему адаптеру. Модель в GPU в этой итерации не загружалась.

4. Материалы и проверки

  • Интерактивный макет: верхние фильтры, отдельные страницы, переход транскрипция ↔ команда, журнал/схема, локальные фильтры и темы.
  • Общий список, транскрипция, схема команды, мобильный эскиз 390 px.
  • Изображения — отдельные векторные эскизы, отрисованные из того же набора условных данных. Это не скриншоты работающего сайта. Они просмотрены визуально.
  • Проверки HTML: 13 адресных функциональных проверок JSDOM, включая прямой вход в схему, сохранение фильтров, отсутствие выдуманных отметок доставки и разделение таймингов.
  • Браузерная политика ранее запретила file://. Повторной попытки или обхода не было; реальная браузерная вёрстка HTML, clipboard и responsive остаются непроверенными. Превью позволяют согласовать компоновку без этого доступа.
  • Изменены только файлы в локальном каталоге asr-monitor-research/v2. Репозитории и production UI остаются прежними.

Исходник

Скачать Markdown · К материалам исследования