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

Monitor / Chat Agent 1.7.0: результаты

Поставка завершена 25.10.2026: Gateway a0bbc0f7 / 1.0.0.978, Frontend 7db26914 / 1.0.0.981. Оба revision/digest подтверждены через Insight; адресные jobs завершены успешно. Исходная база сравнения — f8351d812e909a41adbcae9c670effffd873197f, окончательный source SHA — 7db269144e1d166e65d9d8cdffbb0b5d4afb69b5. Все пять обязательных checks окончательного SHA и 400 frontend-тестов PASS.

Production-миграция, сохранность WAV, новые границы и короткий replay Whisper Turbo, Whisper Russian и GigaAM проверены. В контрольной серии на одной записи 20/20 прогонов Turbo PASS: по 10 полных и коротких. Медиана полного/короткого режима — 17,69 → 9,43 с (−46,7%); p95 — 19,23 → 9,57 с. Выявленное при приёмке опустошение буфера исправлено полной предзагрузкой участков до 2 MiB. Более ранние прерванные проверки сохранены отдельно.

Полная приёмка LinTO заблокирована отказом существующего NATS-прокси: CONNECT HTTP 503, state=failed, getaddrinfo: Name or service not known. Инфраструктура не менялась.

Пакет расширения 1.7.0 размещён по прежнему пути; пользователь выполнил голосовой сценарий и прислал ID 6496d10f-7902-5c3f-91a7-3c5656455a39. Ответ, исполнение input_list, полнота записи и короткая диагностика новой записи подтверждены в Monitor. Компиляция CI-пакета прошла, но загрузка ZIP в GitLab снова не прошла из-за DNS runner. Локальный ZIP точного SHA проверен. Ниже — измерения и результаты; исторические блокеры 23.10 сохранены отдельно и не описывают текущий rollout.

Скорость чтения на одинаковых данных

Локальная PostgreSQL 16: две копии одной БД, 170 с синтетического PCM, 500 фраз, 4000 окон, 10000 событий. 30 прогретых запросов на сценарий. Пользовательское аудио не попало в fixtures. Время содержит ограниченный пул и запросы приложения; это не сетевой SLA production.

Сценарий Медиана, мс; изменение p95, мс; изменение SQL; изменение
25 сообщений 9.541 → 2.421; -7.120 (-74.6%) 10.835 → 3.290; -7.545 (-69.6%) 6 → 5; -1 (-16.7%)
Данные сообщения 2.631 → 1.681; -0.950 (-36.1%) 4.162 → 2.057; -2.105 (-50.6%) 10 → 9; -1 (-10.0%)
Список потоков / 10000 событий 31.596 → 20.488; -11.108 (-35.2%) 34.129 → 21.723; -12.406 (-36.4%) 5 → 5; +0 (+0.0%)
100 событий, одна страница 15.703 → 15.738; +0.035 (+0.2%) 17.314 → 17.461; +0.147 (+0.8%) 5 → 5; +0 (+0.0%)
Чтение PCM-блока 1.282 → 1.180; -0.102 (-8.0%) 1.557 → 1.487; -0.070 (-4.5%) 7 → 6; -1 (-14.3%)

Чтение измерено на 9b0f928b; следующий a0bbc0f7 меняет только очистку ожидающего манифеста при записи. Измерение записи ниже повторено после этой корректировки.

Одна страница событий не ускорена. Изменён момент загрузки: для списка из 10000 событий первое открытие получает 100 строк вместо 10000 (−99% строк первого отображения); остальные страницы читаются только по кнопке. Этот процент — объём загрузки, не ускорение SQL в 100 раз. Границы 25 фраз теперь требуют 0 дополнительных строк окон вместо 200 в этом наборе; данные одного сообщения — 0 вместо 8.

Ресурсы чтения

Сценарий Пик Python, байт; изменение CPU на 30 запросов, мс; изменение Ответ, байт; изменение
25 сообщений 524689 → 385599; -139090 (-26.5%) 201.862 → 64.277; -137.585 (-68.2%) 25298 → 26273; +975 (+3.9%)
Данные сообщения 294607 → 292703; -1904 (-0.6%) 55.969 → 47.895; -8.074 (-14.4%) 1658 → 1697; +39 (+2.4%)
Список потоков / 10000 событий 278546 → 314869; +36323 (+13.0%) 40.993 → 41.059; +0.066 (+0.2%) 200 → 229; +29 (+14.5%)
100 событий, одна страница 802096 → 827068; +24972 (+3.1%) 277.918 → 278.281; +0.363 (+0.1%) 70913 → 70913; +0 (+0.0%)
Чтение PCM-блока 393934 → 397052; +3118 (+0.8%) 37.056 → 33.179; -3.877 (-10.5%) 32569 → 32569; +0 (+0.0%)

Список потоков стал возвращать дополнительные агрегаты, поэтому размер ответа и пик Python немного выросли. CPU этих запросов не сократился. Heap браузера/GPU и production CPU здесь не измерены. Хранимый PCM не изменяется и не сжимается.

Три записи одновременно

Три потока × 10 с, 120 блоков, манифест после PCM. Измерен вызов append+manifest под конкуренцией; это архивный путь, не замер качества ASR.

Метрика Было Стало Разница
Медиана, мс 23.610 23.498 -0.112 (-0.47%)
p95, мс 25.651 25.886 +0.234 (+0.91%)
SQL-команд 1980.000 1980.000 +0.000 (+0.00%)
INSERT/UPDATE/DELETE-команд 378.000 378.000 +0.000 (+0.00%)
CPU, мс 480.122 484.889 +4.768 (+0.99%)
Пик Python, байт 572434.000 571226.000 -1208.000 (-0.21%)
Сохранённый PCM, байт 2880000.000 2880000.000 +0.000 (+0.00%)

Все три записи полные. Скорость записи практически прежняя. Временные finish-строки: 3 → 0 (−3, −100%; 384 → 0 логических байт). Независимые манифесты сохранены в chunks. При манифесте раньше PCM временная строка хранится до применения, затем удаляется. Это уменьшение будущего накопления; DELETE не обещает немедленного возврата диска ОС.

Хранение и миграция

Удалены дублирующие audio_recordings.stream_id и его unique-index; stream_id во внешнем ответе остаётся проекцией id. Добавлены start_16k/end_16k и индекс поиска PCM по смещению. 15 таблиц приложения сохранены. Индексы и два новых поля имеют цену:

Отношение с индексами Было, байт Стало, байт Разница
audio_chunks 704512 753664 +49152 (+7.0%)
audio_phrases 212992 319488 +106496 (+50.0%)
audio_recording_events 6037504 6045696 +8192 (+0.1%)
audio_recordings 65536 49152 -16384 (-25.0%)

Размеры после миграции включают MVCC-версии обновлённых фраз; VACUUM FULL не выполнялся. Для реальных накопленных данных число удалённых временных строк пока не измерено. Миграция старой схемы на тестовой копии: PASS, 21 мс для малого теста, повторный запуск PASS, PCM SHA сохранён, неизвестные границы остались NULL. Это не прогноз длительности production-миграции.

Код и сущности

Категория Добавлено строк Удалено строк Чистое изменение
Документация 98 2 +96
Рабочий код 467 257 +210
Тесты 328 121 +207
Всего 893 380 +513

Подсчёт Git diff от baseline до source SHA 7db269144e1d166e65d9d8cdffbb0b5d4afb69b5 (включая корректировку предзагрузки и вывода ошибки). Evidence: code-counts-final-20261025.json. Vendor/generated/build artifacts не включены; правка сгенерированного package-lock.json (+3/−3) учтена отдельно от рабочего кода. Удалённых файлов: 0. Удалены 3 команды/ветки Monitor (exchanges, exchange_events, session_events), 1 совместимый разбор старого comparison, 1 вычисление batch_bounds на чтении, 1 повторная инициализация чужой схемы, 1 DB-поле и 1 unique-index. Новых сервисов, таблиц, зависимостей и постоянных журналов: 0. Добавлен один локальный таймер границы проигрывания. Новые возможности потребовали больше рабочего кода: чистое изменение положительное; это не объявляется сокращением всей кодовой базы.

Поведение и проверка

  • P0/P1: аудит и независимые before/after-измерения PASS; applied manifest/receipt cleanup, конфликты/ACK, SQL-пагинация, count 107 = 100+7 PASS.
  • P2: четыре backend на уровне контрактов, read/hash/offset/отмена/lease/приоритет live PASS. Реальный короткий режим: Turbo, Russian, GigaAM PASS; LinTO BLOCKED из-за HTTP 503 существующего NATS-прокси. Отмена, освобождение слота и повторный запуск PASS.
  • P3: 400 frontend-тестов, typecheck/build; waveform seek, selection stop, порционное чтение, клавиатура, 390 px PASS.
  • Python: 324 tests + 14 subtests; адресная корректировка хранения: 35 tests. Ruby release checks PASS.
  • Chrome ID, permissions и host_permissions равны установленному расширению. Физический микрофон и обновление Chrome остаются ручной приёмкой.

Краткая инструкция

Скриншоты виджета и waveform ниже — локальная проверка реальных UI-компонентов на синтетических данных. Production-скриншот и результаты поставки приведены в следующем разделе.

  1. В шестерёнке: микрофон, диагностика аудио и «Собрать поля». Одна кнопка голоса включает соединение и микрофон; повторное нажатие полностью выключает их.
  2. Под сообщением снова виден полезный ход инструментов; значок копирует ID для поиска в Monitor.
  3. В Audio → Диагностика выберите модель и нажмите запуск. По умолчанию передаётся фраза +2/1 секунды; весь поток выбирается отдельно.
  4. В Audio → Данные клик по waveform задаёт позицию; перетаскивание или поля времени выделяют участок прослушивания. Границы ASR от этого не меняются.

Поставка и production-проверки 25.10.2026

CI и runtime

Первичная поставка относится к a0bbc0f78a93e2f0f45c53bc214e958ac4f61ce4, pipeline 5381.

Контур Job Результат
Пять обязательных checks 22145–22149 SUCCESS
Сборки Gateway / Frontend 22162 / 22167 SUCCESS
Свежий deployment preflight 22216 SUCCESS; штатный SSH/Docker доступ восстановлен внешне
Адресный Gateway 22193 SUCCESS, 72,07 с
Адресный Frontend 22206 SUCCESS, 82,93 с
Chrome extension 22217 Компиляция PASS, artifact upload FAIL: DNS gitlab через 172.17.0.1

Job расширения провела около 17 минут в npm ci и завершилась самостоятельно; отмена не выполнялась. Инфраструктура, DNS, SSH agent, CI и зависимости этой итерацией не менялись. Поставка выполнена существующими jobs с drain/resume; полный stack deploy не применялся.

Сервис Фактический revision Digest запущенного image Runtime
Gateway a0bbc0f78a93e2f0f45c53bc214e958ac4f61ce4 sha256:c3d786beed06def0debe71120e0ecba67f14145541504594cdda71c4c4cef6ed 1.0.0.978, 1/1 running, update completed 19:27:08 UTC
Frontend 7db269144e1d166e65d9d8cdffbb0b5d4afb69b5 sha256:7662d48e1b3ebf3590839899356e343e02fc0e1372241f729e751818cf8a74e4 1.0.0.981, 1/1 running, update completed 20:17:51 UTC

Корректировка Frontend поставлена после пяти checks нового pipeline 5385: Python 22343, browser NATS 22344, Frontend 22345, Ruby 22346, dialog integration 22347 — SUCCESS. Сборка 22365 — 60,21 с; preflight 22370 — 83,55 с; адресная поставка 22404 — 89,57 с, все SUCCESS. Gateway повторно не обновлялся.

Revision/digest подтверждены отдельно через Insight Docker inspect, а не только текстом CI. Docker healthcheck у этих контейнеров не настроен; работоспособность подтверждена загрузкой нового Monitor, PostgreSQL-чтением и реальными NATS replay. Admission восстановлен штатной job. Остальные контейнеры chat-agent имеют прежнее время запуска около двух суток; Core 1.0.0.963, ingress 1.0.0.973, Agent/LLM 1.0.0.916. Их поставка не запускалась. PostgreSQL не перезапускался.

Миграция и изоляция

  • PASS: в production audio_phrases появились start_16k/end_16k; для контрольной фразы сохранены 91520–125952 отсчётов, то есть 5,720–7,872 с. Недоказуемые границы остаются NULL.
  • PASS: в audio_recordings отсутствует дублирующая колонка stream_id; строк осталось 13 до новой ручной записи.
  • PASS: WAV контрольной фразы до и после миграции — 206636 байт, одинаковый SHA256 770c48d54d48ba5699ed90e4d4d43922ba94553109fd6a945ca6b694ad1f69f4.
  • PASS: в окне 18:38–19:38 UTC четыре таблицы аудио, widget_cache, browser_command_receipts и chat_notes не имеют новых/изменённых строк. NATS-журнал содержит 24 служебные операции preflight/drain/resume/state/lifecycle, все без request_id; записей replay, Agent/LLM/инструментов нет. Изменились только browser_access и эти служебные записи nats_log.

Это наблюдаемая проверка конкретных прогонов; гарантии других отказных сценариев подтверждены адресными тестами, а не этим коротким окном наблюдения.

Реальная короткая диагностика

Сравнение на одном сохранённом PCM: request_id 9eba3789-b7be-5e8f-8d65-759eafdcc8d1, recording c4016f13-d470-4e9b-be0b-f903718cce72. Контекст 2 с до / 1 с после даёт диапазон 3,720–8,872 с. Подача сократилась 11,936 → 5,152 с, на 6,784 с / 56,8%. Исходные WAV не изменены.

Backend Полный режим до, с Новый короткий режим, с Разница Результат
Whisper Turbo 15,57 9,14 −6,43 / −41,3% PASS: «да и список всех полей»
Whisper Russian 15,58 9,52 −6,06 / −38,9% PASS: «Да и список всех полей.»
GigaAM v3 RNNT 15,62 9,52 −6,10 / −39,1% PASS: «Да, список всех полей.»
LinTO 15,61, текст не подтверждён 9,66, ошибка Не сравнивается как ускорение ASR BLOCKED: linto_stream_error, HTTP CONNECT 503

До — по одному прогону 23.10; после — первые контрольные прогоны 25.10. Это не медиана/p95, нагрузка между днями не зафиксирована. Статистические сравнения на одинаковой конфигурации приведены выше для PostgreSQL. Повторный короткий Turbo после отмены занял 8,55 с; эта вариативность не скрыта выбором лучшего результата.

Стадия нового короткого режима, с Turbo Russian GigaAM
Подготовка 0,87 0,89 0,85
Предзагрузка / подключение 1,47 1,99 2,03
Подача PCM 1× 5,14 5,14 5,14
Завершение ASR 1,48 1,32 1,31
Весь запуск, включая освобождение 9,14 9,52 9,52

Partial и final показаны до завершения прогона. Final Turbo пришёл на 7,64 с, Russian на 7,56 с, GigaAM на 7,55 с. Очередь и Decoder показаны отдельно; их нельзя отождествлять со стадией завершения ASR. Качество первого слова не изменялось этой задачей: модели/VAD/декодирование остались прежними.

  • PASS: полный режим сохранён; новый Turbo передал все 11,936 с и завершился за 14,91 с.
  • PASS: активный полный replay отменён после подачи 2,496 с; UI подтвердил освобождение слота на 4,41 с. Следующий короткий запуск завершился успешно.
  • PASS: новые вкладки и подробный журнал работают в production. В журнале нет отдельной строки на каждый PCM-пакет.
  • PASS: на production-WAV клавиатура сдвигает курсор на 0,1 с; выделение 6,000–6,500 с запускает проигрыватель с нужного смещения и автоматически останавливает его точно на 6,500 с. Подтверждены paused=true и media currentTime=0,780 с относительно исходного фрагмента 5,720 с. Evidence: production-waveform-20261025.json/png.

Новая речь после обновления Chrome

Пользователь прислал request_id 6496d10f-7902-5c3f-91a7-3c5656455a39, session db96a164-fcbf-41d2-bf83-673c283b159d.

  • Запрос выполнен: две генерации, один input_list (0,25 с), сервер 11,82 с; показ ответа подтверждён через 12,09 с.
  • Текст ASR: «на расписок всех полей.». Это ошибка исходного распознавания; изменение качества ASR, VAD и декодирования не входило в эту поставку.
  • В списке потоков 18,685 с и 76 событий; сохранённый PCM 17,472 с указан в tooltip. Раздел «События потока» подтвердил ровно 76 загруженных событий. Переход по прямой ссылке и клавиатурой прошёл.
  • Recording de3ad0ed-cf17-44f1-8601-7f700af2844f закрыт, полон: 17,472 с. Микрофонные NS/EC/AGC зафиксированы включёнными после пакета 2.
  • Границы новой фразы доступны сразу: 2,040–3,904 с. Диагностика использует 0,040–4,904 с — 4,864 с вместо 17,472 с (−12,608 с / −72,2% PCM).
  • Короткий Turbo завершился за 9,51 с, final пришёл на 7,57 с. Текст replay «на распишек всех полей.» отличается от live: сохранено предупреждение об изменении VAD-контекста; точное повторение текста не обещается.
  • Дополнительно production partial 0,520 с успешно загружен и воспроизведён до конца; исходные данные окна помечены как PCM браузера, не как точный массив Decoder.

Evidence: user-request-overview-20261025.txt, user-audio-data-20261025.txt, user-replay-20261025.txt, production-partial-played-20261025.json.

Корректировка, выявленная серией прогонов

В серии на первом поставленном a0bbc0f7: 3 полных запуска PASS (15,38 / 15,24 / 15,79 с), первые 2 коротких PASS (9,70 / 9,02 с), третий короткий остановился после 2,147 с PCM из 5,152 с. Причина — запаздывающие порционные чтения после стартовой предзагрузки двух секунд; UI сохранил ошибку и освободил слот. Этот отказ сохранён в paired-replay-20261025.json и replay-underrun-20261025.txt, исключать его из отчёта об успешности нельзя. По этой незавершённой серии медиана/p95 успешности не объявляется.

В 4ad16814 выбранный PCM, помещающийся в существующие 2 MiB, полностью читается и проверяется до открытия ingress. Для больших записей сохранены прежние два параллельных чтения, минимум две секунды предзагрузки и остановка при недостатке данных; память и темп 1× не увеличены. Отдельный тест воспроизвёл отказ старого кода, затем прошёл после исправления. Проверен также участок ровно 2 MiB.

В 1ffcd7e3 пустой text backend больше не скрывает code ошибки/отклонения в результате и журнале. Это исправление UI; оно не восстанавливает неисправный LinTO-прокси. Полная локальная проверка: 400 tests / 57 files PASS, typecheck, Vite и runtime settings PASS. В CI 5384 все 400 тестов и сборка прошли, но npm audit обнаружил уязвимость dev-зависимости undici 7.30.0. В 7db26914 только её lock-запись обновлена до 7.30.1 (3 строки); после обновления все 400 тестов и npm audit (0 уязвимостей) прошли локально. Целевой pipeline 5385. Исправленная версия подтверждена публикацией разработчиков. Gateway и расширение не требовали повторной поставки от этих Frontend-изменений. Новый runtime Frontend подтверждён через Insight; отдельно сохранён frontend-runtime-final-20261025.json.

Контрольная серия на окончательной поставке

Frontend 7db26914, Gateway a0bbc0f7, один и тот же сохранённый PCM и прогретый Whisper Turbo. 10 чередующихся пар «весь поток / фраза + контекст» в 20:25–20:34 UTC. 20/20 PASS, все завершили передачу и подтвердили освобождение слота. Текст всех результатов одинаков: «да и список всех полей».

Этап Медиана: полный → короткий, с Разница p95: полный → короткий, с Разница
Подготовка 0,945 → 0,870 −0,075 (−7,9%) 1,01 → 0,94 −0,07 (−6,9%)
Предзагрузка / подключение 3,310 → 1,895 −1,415 (−42,7%) 4,78 → 2,08 −2,70 (−56,5%)
Подача PCM 1× 11,94 → 5,14 −6,80 (−57,0%) 11,94 → 5,14 −6,80 (−57,0%)
Завершение ASR 1,31 → 1,32 +0,01 (+0,8%) 1,39 → 1,41 +0,02 (+1,4%)
Всего с освобождением 17,69 → 9,43 −8,26 (−46,7%) 19,23 → 9,57 −9,66 (−50,2%)

Это сравнение режимов на текущей версии, а не двух версий при идентичной внешней нагрузке. p95 — nearest rank для 10 запусков (в этой выборке максимум), поэтому не обещание production SLA. Передача содержит реальные интервалы исходных пакетов; измеренное время подачи и длительность PCM могут немного отличаться. Реальные размеры PCM: 1 145 856 → 494 592 байт, −651 264 байта (−56,8%). Накопленные WAV в БД не изменились.

Цена полной предзагрузки: полный режим этой записи ждёт чтения всех 1,09 MiB перед запуском; его медиана предзагрузки 3,31 с. В прежних единичных прогонах с двухсекундным стартовым буфером было около 0,6 с, но повторная серия выявила опустошение буфера. Ускорение полного режима не заявляется. Для больших записей свыше 2 MiB сохранено порционное чтение с bounded buffer.

До этой серии сохранены ещё два прерванных прогона новой версии: short 5,32 с и full 15,32 с. Клиент отменил подачу; ошибки хеша/буфера/темпа в журнале отсутствуют. Точный инициатор отмены в UI не записан. По исходникам таким путём завершается скрытие страницы, но исторического visibility-события для этих двух запусков нет, поэтому причина не объявляется доказанной. Отдельный полный прогон с временным наблюдением visibility завершился успешно за 19,70 с; он исключён из статистики как инструментированный. Временные DevTools breakpoints сняты. Прерванные и инструментированный прогоны сохранены, а не удалены из общего evidence.

Проверка backend на окончательной версии: Turbo 9,16 с, Russian 9,72 с, GigaAM 9,08 с — PASS; LinTO 9,35 с — ASR ERROR linto_stream_error, освобождение слота PASS. Код ошибки теперь явно виден под результатом и в журнале.

Дополнительно отменён полный replay после 2,496 с PCM; освобождение подтверждено на 6,97 с от запуска. Следующий короткий replay завершился успешно за 9,42 с. Нельзя приравнивать раннее отображение кнопки запуска к подтверждённому освобождению — здесь проверено и серверное подтверждение.

Evidence: paired-replay-fixed-20261025.json, paired-replay-statistics-20261025.json, replay-fixed-200..209-*.txt, replay-cancel-final-20261025.txt, linto-visible-error-final-20261025.png.

Оставшиеся ограничения

  1. LinTO: в 19:34:17 UTC py_faster_whisper_nats_proxy_linto получил CONNECT к llm-models_linto_stt_whisper:80 и ответил 503: Service runtime failed, state=failed, role=requester, getaddrinfo: Name or service not known, оба bridge=false. Ошибка возникает в существующем прокси до обращения к распознавателю. Сервис не перезапускался, инфраструктура не менялась по прямому ограничению пользователя. Полноценную приёмку LinTO требуется повторить после штатного восстановления этого контура.
  2. CI ZIP: разрешённый пользователем повтор 22218 также завершился ошибкой DNS после 1019,67 с; компиляция проходит, загрузка артефакта в GitLab блокируется DNS runner. Это не препятствовало адресной поставке Gateway/Frontend. Проверенный локальный пакет точного SHA доступен в локальный источник, ZIP SHA2565586a3328679be64f65280d72e6b0cd5a74f5efe9e1e019d6f3045ab9027cdaa`; прежние ID и permissions сохранены.
  3. Ручная приёмка Chrome: пользователь выполнил запрошенный сценарий и прислал ID новой реплики. Через Monitor подтверждены ответ, input_list, прекращение потока и полная запись. Расположение шестерёнки и видимость хода инструментов внутри закрытой панели независимо браузерным инструментом не инспектировались; UI-компоненты проверены локально. Отдельного текстового подтверждения этих двух визуальных пунктов пользователь не прислал.

Evidence: jobs-final-20261025.json, gateway-runtime-20261025.json, frontend-runtime-20261025.json, runtime-after-20261025.json, production-bounds-20261025.json, production-recordings-schema-20261025.json, production-wav-check-20261025.json, replay-short-*-20261025.txt, replay-full-turbo-20261025.txt, replay-cancel-20261025.txt, replay-after-cancel-20261025.txt, replay-isolation-20261025.json, replay-period-nats-rows-20261025.json, linto-proxy-log-20261025.json.

История ранних попыток и исходных проверок: DELIVERY-HISTORY.md.

Исходник

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