
Почему ИИ-транскрипция перевирает технические термины (и как мы это исправили)
Живая сессия услышала «what is the pointer in C++» как «what is the point in life». Вот путь расследования от того транскрипта до GeekBye v2.0.11 — keyterm biasing, гонка, обрывавшая соединение, и день, когда наш собственный фикс сработал против нас.
2 июля мы запустили тестовую сессию и задали GeekBye вслух простой вопрос: «What is the pointer in C++?» (что такое указатель в C++).
Живой транскрипт ответил поэзией:
[23:16:37] You: Tell me, what is the point in life? [23:16:52] You: Handy Plus. [23:17:02] You: What the pointer in Plus Plus? [23:17:09] You: C.
Вместо «pointer in C++» (указатель в C++) модель услышала «point in life» (смысл жизни). Остальное в той же сессии рассказали метрики здоровья: 3 обрыва соединения транскрипции за 163 секунды и 51-секундная дыра в транскрипте. И ещё одна улика, которая оказалась важнее всех: наш механизм восстановления после сессии — он повторно транскрибирует локально сохранённое аудио, чтобы заполнить пробелы, — воспроизвёл фразу почти правильно: «a pointer in plus, plus? What the pointer in plus, plus C++.»
С аудио всё было в порядке. Просто у живой модели не было ни одной причины ожидать C++.
Это история релиза GeekBye v2.0.11, рассказанная по реальным транскриптам и продакшен-логам.
Почему речевые модели перевирают вашу лексику
Распознавание речи — это задача предсказания. Получив неоднозначное аудио, модель выбирает наиболее вероятные слова — а для модели общего назначения фраза «point in life» куда вероятнее, чем «pointer in C++». Каждый инженер, который видел, как транскрипт встречи превращает Kubernetes в «cube and eddies», знаком с этим провалом лично.
Лекарство — не микрофон получше, а keyterm biasing: перед началом сессии сообщить модели, какие маловероятные слова вероятны именно у вас. Наш речевой провайдер поддерживает до 50 подсказок на сессию. А теперь неловкая часть: вся обвязка для этих терминов существовала в нашем стеке от начала до конца — клиент, бэкенд, провайдер — и никто её ни разу не заполнял. Каждая сессия работала без какой-либо доменной помощи.
Фикс 1: ваш профиль становится словарём модели
GeekBye уже знает ваш домен — он записан в вашем активном профиле. v2.0.11 выводит keyterms для смещения из названия и описания профиля: термины с символами (C++, Node.js), акронимы (SQL, AWS), имена в camel case (TypeScript, PostgreSQL) и имена собственные. Профиль, где упомянут ваш стек, теперь делает этот стек ожидаемым, а не экзотическим.
День, когда фикс сделал всё хуже
Наша первая версия считала именем собственным каждое слово с заглавной буквы. На внутренней тестовой сборке (до клиентов это не дошло) профиль, написанный обычной прозой, отправил модели такой список подсказок:
Senior, Writing, Direct, For, Includes, Write, Role, Intent…
Смещать речевую модель в сторону слова «For» хуже, чем не смещать её вовсе. В следующей же тестовой сессии слово «speak» — произнесённое чётко, несколько раз — вернулось как «Clicky», «Hey, Vicky» и «Peter Paderty». Урок обошёлся нам в один вечер: смещайте только характерными терминами. Слова с заглавной буквы теперь учитываются, только если стоят в середине предложения (настоящий признак имени собственного); заголовки markdown, где с заглавной буквы начинается каждое слово, не дают вклада никогда. Тот же профиль теперь выводит ровно LinkedIn, AI, CEO, MCP — а валидационная сессия корректно транскрибировала многоязычное аудио с быстрыми переключениями 199 секунд подряд: 189 сегментов транскрипта, ноль ошибок.
Фикс 2: гонка, обрывавшая соединения
Keyterms объяснили перевранные слова. Три обрыва соединения они не объясняли.
Этот след вёл к чему-то более тонкому. Наш провайдер коммитит (финализирует) транскрипцию по собственному детектору голосовой активности — примерно через секунду тишины. Наш клиент тоже отправляет страховочный commit через 250 миллисекунд тишины, чтобы дослать зависшее незаконченное предложение. Подтверждение провайдера о том, что он уже закоммитил, идёт обратно от одной до трёх секунд. Сложите эти три числа: всякий раз, когда провайдер коммитил первым, наш страховочный commit ударял по почти пустому буферу — и ответом провайдера был не вежливый отказ. Он обрывал соединение. Каждая пауза в речи была подбрасыванием монеты.
v2.0.11 ставит против этого два слоя защиты:
- В приложении: когда приходит закоммиченный транскрипт, клиент теперь знает, что буфер провайдера только что был сброшен, и пропускает лишний страховочный commit.
- На нашем бэкенде, в тот же день: прокси между приложением и провайдером в точности зеркалит учёт аудио у провайдера — он видит каждый аудиофрейм и каждое подтверждение коммита с нулевой задержкой — и просто отказывается пересылать любой commit, который провайдер отклонил бы. Этот слой защищает сразу все версии клиента, включая пользователей, которые ещё не обновились.
Мы увидели, как это работает в продакшене, уже в течение часа. Защита перехватила обречённые коммиты со 178 мс и 256 мс буферизованного аудио — каждый из них до этого дня означал гарантированный обрыв соединения и дыру в чьих-то заметках со встречи. 60-минутная непрерывная сессия в тот же день зафиксировала пять перехватов и ноль обрывов. До фикса, тем же утром, реальный пользователь пять раз за шесть минут перезапускал запись, сражаясь ровно с этим багом.
Два фикса поменьше в том же релизе
ИИ-инсайты теперь ждут содержания. Те искажённые ранние обрывки раньше попадали в живые чипы-подсказки GeekBye, которые из перевранного вопроса про C++ уверенно выдавали темы вроде «Defining Life's Ultimate Purpose». Теперь подсказки ждут, пока в сессии наберётся настоящая разговорная масса.
Восстановленный текст получает правильного говорящего. Механизм восстановления, который корректно транскрибировал наш вопрос про C++, приписал его «Them» (собеседнику). Локально сохраняемая аудио-хронология теперь фиксирует, кто говорил, и восстановленные сегменты корректно относятся к вам или собеседнику.
Табло результатов
| Метрика (измерено, а не оценено) | До | После v2.0.11 + защита на бэкенде |
|---|---|---|
| Обрывы соединения в тестовой сессии | 3 за 163 с | 0 |
| Самая длинная дыра в транскрипте | 51 с | ~6 с — худший пробел на валидации |
| «pointer in C++» | «point in life» | правильно, со смещённым словарём |
| Обречённые коммиты, дошедшие до провайдера | все | 0 (перехвачены на бэкенде) |
Если вы строите на realtime-API распознавания речи
Три переносимых урока из этого релиза:
- Кормите механизм смещения. Если ваш STT-провайдер поддерживает keyterms/подсказки фраз, заполнить их небольшим, характерным словарём — самый дешёвый доступный выигрыш в точности; заполнить их обычными словами — потеря точности.
- Никогда не соревнуйтесь с конечным автоматом провайдера с неправильной стороны сетевого round-trip. Наш клиент не мог выиграть информационную гонку 250 мс против 3 с. Защите место там, где сходятся оба сигнала, — у нас это прокси на бэкенде.
- Проверяйте на живой сборке перед публикацией. Регрессию с keyterms поймали потому, что каждый релиз GeekBye перед выпуском тестируется как подписанная, нотарифицированная сборка на продакшене. Плохая версия прожила несколько часов на одной внутренней машине, а не на вашем Mac.
GeekBye v2.0.11 уже доступен — если вы на v2, он уже прилетел через автообновление. О фундаменте надёжности, на котором построен этот релиз, читайте в статьях почему ваш ИИ-блокнот останавливается на плохом Wi-Fi и что изменилось в GeekBye v2. А о том, как живая транскрипция работает изо дня в день, начните с транскрипции в реальном времени в GeekBye.

