Правки для согласования · версия 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 перемещаются в технический уровень. Они не смешиваются с фильтрами пользовательских процессов. Служебные события без доказанной связи с фразой/командой остаются доступными в существующем служебном представлении; их нельзя молча выбросить или приклеить к ближайшей фразе по времени.
Отдельная страница выбранного процесса
- Заголовок
[Транскрипция] — текстили[Команда] — текст, статус, модель и копируемые существующие ID. - Краткий итог: счётчики, основные интервалы, отдельное число вызовов модели/инструментов.
- Объяснение вложенных интервалов и, для аудио, запись/диагностика.
- Журнал / Схема вызовов — постоянно видимый переключатель.
- Локальные фильтры: участник, тип сообщения, направление наблюдения, отсутствие отметки, поиск subject/адреса/ID, ранние/поздние.
- Быстрые технические срезы: Все каналы / 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 не следует.
Порядок будущего эксперимента:
- Закрепить файлы и хеши модели, проверить импорты в изолированном окружении. Не подменять действующий GigaAM.
- Один контролируемый load в разрешённом бюджете GPU: память до/после/пик, холодный запуск. OOM не должен затронуть текущие модели.
- Одни PCM16 16 кГц, одни границы и тексты-эталоны: текущий RNNT, новый CTC, Turbo. Сначала PCM, отдельно от Opus, чтобы не смешать причины различий.
- Короткие команды, тихая речь, имена, числа, шум, паузы; длительности 1/5/15/30 секунд. Отдельно cold/warm, медиана/p95 чистого ASR и памяти. Пунктуация и нормализация оцениваются отдельно от WER.
- Вход напрямую массивом через decoder, без повторного VAD, WAV/base64-круга и фильтрации текста по score.
- По результату решить: добавить альтернативную модель, заменить нынешнюю или отказаться. Решение о замене заранее не принято.
Поддержка общего класса проверена по исходнику закреплённой модели и нашему адаптеру. Модель в GPU в этой итерации не загружалась.
4. Материалы и проверки
- Интерактивный макет: верхние фильтры, отдельные страницы, переход транскрипция ↔ команда, журнал/схема, локальные фильтры и темы.
- Общий список, транскрипция, схема команды, мобильный эскиз 390 px.
- Изображения — отдельные векторные эскизы, отрисованные из того же набора условных данных. Это не скриншоты работающего сайта. Они просмотрены визуально.
- Проверки HTML: 13 адресных функциональных проверок JSDOM, включая прямой вход в схему, сохранение фильтров, отсутствие выдуманных отметок доставки и разделение таймингов.
- Браузерная политика ранее запретила
file://. Повторной попытки или обхода не было; реальная браузерная вёрстка HTML, clipboard и responsive остаются непроверенными. Превью позволяют согласовать компоновку без этого доступа. - Изменены только файлы в локальном каталоге
asr-monitor-research/v2. Репозитории и production UI остаются прежними.