BorisovAI
Все потоки
Исправлениеspeech-to-text7 заметок

Разработка: speech-to-text

Поток разработки проекта speech-to-text. 7 заметок: баг-фиксы (1), фичи (5), обучение (1). Последние темы: Whisper упирается в стену: что происходит, когда оптимизация бессильна; Когда пороги T5 упираются в потолок качества; Микротюнинг алгоритма: как сэкономить гигабайты памяти.

#git#commit#api#security
Начало
Завершён
1
Новая функция

Как мы защитили артефакты приватного проекта, но случайно выставили их в интернет

Проект speech-to-text — это голосовой ввод для веб-приложения. Задача казалась стандартной: настроить автоматизированный релиз артефактов через CI/CD. Но когда я начал копать, обнаружилась забавная особенность GitLab Pages, которая чуть не стала залогом безопасности нашего проекта.

Когда публичное скрывается за приватным

Первым делом я исследовал варианты хранения и раздачи собранных ZIP-файлов. В репозитории всё приватное — исходники защищены, доступ ограничен. Проверил GitLab Releases — отличное решение, вот только возникла проблема: как скачивать артефакты с публичного фронтенда, если сам проект закрыт?

Тогда я посмотрел на GitLab Package Registry — тоже приватный по умолчанию. Но потом наткнулся на странное: GitLab Pages генерирует статические сайты, которые всегда публичны независимо от приватности самого проекта. То есть даже если репо закрыт для всех, Pages будут доступны по ссылке для любого, кто её узнает.

Неожиданно выяснилось: это не баг, а фича. Pages часто используют именно для этого — расшарить артефакты или документацию публично, не давая при этом доступ в репо.

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

Архитектура получилась такой: скрипт на Python собирает проект, упаковывает в ZIP и загружает в GitLab Package Registry. Затем я создал CI pipeline, который срабатывает на тег вида v* (семантическое версионирование). Pipeline скачивает ZIP из Package Registry, деплоит его на GitLab Pages (делает доступным по публичной ссылке), обновляет версию в Strapi и создаёт Release в GitLab.

Для работы потребилась переменная CI_GITLAB_TOKEN с соответствующим доступом — её я забил в CI Variables с флагами protected и masked, чтобы она не оказалась в логах сборки.

Версионирование жёсткое: версия указывается в src/__init__.py, оттуда её подхватывает скрипт при сборке. Архивы называются в стиле VoiceInput-v1.0.0.zip.

Идея, которая в голову не пришла

Интересный момент: изначально я беспокоился, что приватный проект станет помехой. На деле оказалось, что Pages — это идеальное решение для раздачи артефактов, которые не нужно прятать, но и не нужно давать доступ к исходникам. Классический сценарий для скачиваемых утилит, библиотек или сборок.

Теперь релиз — это одна команда: .\venv\Scripts\python.exe scripts/release.py. Скрипт собирает, архивирует, загружает, пушит тег. А CI сам позаботится о Pages, Strapi и Release.

😄 Почему GitLab Pages пошёл в терапию? Потому что у него была сложная личная жизнь — он был публичным, но никто об этом не знал!

#claude#ai#python#git#api#security
Читать далее
2
Новая функция

Когда Gitaly молчит: охота на недоступный GitLab среди ночи

Вечер пятницы, deadline на релиз v1.0.0 проекта speech-to-text буквально под носом. Нужно было запушить финальный коммит с автоматизацией сборки в master, создать тег и загрузить артефакт в Package Registry. Казалось бы, стандартная процедура — клик, клик, и всё готово.

Но началось всё с того, что я попытался перезапустить Gitaly на GitLab-сервере через SSH. Ничего не вышло. Сервер просто не отвечает. Ладно, попробую обойтись без SSH — может быть, сам GitLab доступен по HTTP? Нет, он тоже молчит как партизан. Вообще ничего не откликается.

Паника? Нет, просто логика. Если сервер не отвечает ни на SSH, ни на HTTP, значит либо он упал, либо сетевая проблема. Проверяю VPN. И вот оно! IP-адрес в диапазоне 10.8.0.x не найден. OpenVPN отключился. Сервер GitLab (gitlab.dev.borisovai.tech) размещён на машине 144.91.108.139, которая доступна только через защищённый туннель.

Вот это поворот! Оказывается, всё время я просто был за стеной недоступности — VPN выполнял свою работу, но потом тихо сдался. Компания добавила слой безопасности, а я про это забыл. Типичная история: инфраструктура дышит на тебе в спину, а ты смотришь на монитор и недоумеваешь.

Интересный факт: Gitaly — это компонент GitLab, отвечающий за хранение репозиториев и работу с гитом на серверной стороне. Создан он специально для того, чтобы отделить операции с файловой системой от основного приложения. Если Gitaly недоступен, GitLab просто не может выполнять операции с гитом — это как отключить ноги при попытке ходить.

Решение было простым, но требовало действий. Нужно было:

  1. Подключить OpenVPN к серверу 144.91.108.139
  2. После восстановления туннеля выполнить git push origin master из ветки master
  3. Запустить скрипт релиза: .\venv\Scripts\python.exe scripts/release.py

Этот скрипт собирает EXE из Python-кода, упаковывает его в ZIP, загружает артефакт в GitLab Package Registry и создаёт тег версии.

Когда VPN встал на место и лампочки начали загораться в правильном порядке — Gitaly вновь ожил, сервер откликнулся, а мой коммит с облегчением пошёл в master. Релиз ушёл в прод ровно в срок.

Урок на вечер: прежде чем искать проблему на сервере, проверьте, что вы вообще до него дотягиваетесь. Инфраструктура любит прятаться за слоями безопасности, и иногда самая сложная проблема решается одной переподключением.

😄 Почему MongoDB считает себя лучше всех? Потому что Stack Overflow так сказал.

#claude#ai#python#git#api
Читать далее
3
Новая функция

Охота на баги в системном трее: как логи спасили день

Проект speech-to-text — это приложение для распознавания речи с поддержкой выбора аудиоустройства прямо из системного трея. Казалось бы, простая задача: пользователь кликает по иконке микрофона, видит список устройств, выбирает нужное. Но реальность оказалась хитрее.

Когда старая сборка не хочет уходить

Всё началось со стандартной проблемы: после изменения кода сборка падала, потому что старый EXE-файл приложения всё ещё работал в памяти. Казалось бы, что здесь сложного — убить процесс, запустить новый. Но разработчик пошёл дальше и решил запустить приложение в режиме разработки прямо из Git Bash, чтобы видеть логи в реальном времени. Это сыграло ключевую роль в том, что произошло дальше.

Задача была конкретной: разобраться, почему меню выбора аудиоустройства в системном трее работает странно. Пользователь кликает на “Audio Device”, но что происходит дальше — неизвестно. Здесь-то и нужны были логи.

Логирование как инструмент детектива

Первое, что сделал разработчик — добавил логирование на каждый шаг создания меню устройств. Это классический подход отладки: когда ты не видишь, что происходит внутри системного трея Windows, логи становятся твоим лучшим другом.

Приложение запущено в фоновом режиме. Инструкция для тестирования была простая: наведи курсор на “Audio Device” в трее, и система начнёт логировать каждый шаг процесса. Процесс загрузки моделей искусственного интеллекта занимает 10–15 секунд — это время, когда нейросетевые модели инициализируются в памяти.

Кстати, это напоминает, как работают трансформеры в современных AI-системах. По сути, когда речь преобразуется в текст, система использует архитектуру на основе multi-head attention: звук кодируется в токены, каждый токен переходит в векторное представление, а затем контекстуализируется в рамках контекстного окна с другими токенами параллельно. Это позволяет системе “понять”, какие части речи важны, а какие можно проигнорировать.

Жизненный цикл одного багфикса

Разработчик делал это методично: добавил логирование, перезапустил приложение с новым кодом, ждал инициализации, затем попросил выполнить действие (клик по “Audio Device”). После этого — проверка логов.

Это не просто отладка. Это итеративный цикл обратной связи: код → перезапуск → действие → анализ логов → новое понимание. Каждая итерация приносила всё больше информации о том, как именно система ведёт себя на уровне системного трея.

Главный вывод: когда ты работаешь с компонентами операционной системы (вроде системного трея Windows), логирование становится не просто удобством, а необходимостью. Без логов ты работаешь вслепую.

Что дальше

На этот момент приложение работало, логирование было активно, и любое действие пользователя оставляло след в логах. Это была база для настоящей отладки — уже известно, как и где начать искать проблему.

Разработчик научился важному уроку: никогда не недооценивай силу логирования при работе с системными компонентами. Это, конечно, не панацея, но когда ты охотишься на баги в чёрном ящике операционной системы, логи — это твой фонарик.

Если NumPy работает — не трогай. Если не работает — тоже не трогай, станет хуже. 😄

#claude#ai#git#api
Читать далее
4
Обучение

Когда микротюнинг алгоритма экономит гигабайты памяти

Работаю над проектом speech-to-text, и вот типичная история: всё кажется работающим, но стоишь перед выбором — либо система пожирает память и отзывается медленно, либо производит мусор вместо текста. На этот раз пришлось разбираться с двумя главными вредителями: слишком агрессивной фильтрацией T5 и совершенно бесполезным адаптивным fallback’ом.

Начну с того, что случилось. Тестировали систему на аудиокниге, и T5 (модель для коррекции текста) вела себя как чрезмерно ревностный редактор — просто удаляла слова направо и налево. Результат? Потеря 30% текста при попытке поднять качество. Это был провал: WER (Word Error Rate) показывал 28,4%, а сохранялось всего 70% исходного текста. Представьте, вы слушаете аудиокнигу, а система вам отдаёт её в сокращённом виде.

Первым делом залез в text_corrector_t5.py и посмотрел на пороги схожести слов. Там стояли скромные значения: 0,6 для одиночных слов и 0,7 для фраз. Я поднял их до 0,80 и 0,85 соответственно. Звучит как небольшое изменение? На самом деле это означало: «T5, удаляй слово только если ты ОЧЕНЬ уверена, а не если просто подозреваешь». И вот что получилось — WER упал до 3,9%, а сохранение текста прыгнуло на 96,8%. Это был уже другой уровень.

Но это был только первый фронт войны. Вторым врагом оказался adaptive_model_fallback — механизм, который должен был срабатывать, когда основная модель барахлит, и переключаться на резервную. Звучит логично, но на практике? Тестировали на синтетических деградированных аудио — отлично, WER 0,0%. На реальных данных (TTS аудиокниги в чистом виде) — хуже базовой линии: 34,6% вместо 31,9%. На шумных записях — 43,6%, никакого улучшения.

Получилось, что адаптивный fallback был как дорогой зонтик, который вообще не спасает от дождя, но при этом весит килограмм и занимает место в рюкзаке. Я отключил его по умолчанию в config.py, выставив adaptive_model_fallback: bool = False. Код оставил — вдруг когда-нибудь появятся реальные микрофонные записи, где это сработает, но пока это просто груз.

Интересный факт: задача выбора порога схожести в NLP похожа на тюнинг гитары — сдвигаешь колок на миллиметр, и звук либо поёт, либо звенит. Только вместо уха здесь работаешь с метриками и надеешься, что улучшение на тестовом наборе не рухнет на боевых данных.

В итоге система стала на 86% точнее на аудиокнигах, освободилась от 460 МБ ненужной памяти и ускорилась на 0,3 секунды. Всё это из-за двух небольших изменений пороговых значений и одного отключённого флага. Результаты зафиксировал в BENCHMARK_RESULTS.md — полная таблица тестов, чтобы потом никто не начинал возвращать fallback обратно.

Урок такой: иногда микротюнинг работает лучше, чем архитектурные перестройки. Иногда лучшее решение — просто выключить то, что не работает, вместо того чтобы его развивать.

😄 Что общего у T5 и подросткового возраста? Оба требуют очень точных параметров, иначе начинают удалять всё подряд.

#git#commit#python#security
Читать далее
5
Новая функция

Когда оптимизация упирается в стену: история о порогах T5

Работаю над speech-to-text проектом уже несколько спринтов. Задача простая на словах: снизить процент ошибок распознавания (WER) с 34% до 6–8%. Звучит как небольшое улучшение, но на практике — это огромный скачок качества. Когда система неправильно расслышит каждое третье слово, пользователи просто перестанут ей доверять.

Инструмент в руках — модель Whisper base от OpenAI с надстройкой на базе T5 для исправления текста. T5 работает как корректор: смотрит на распознанный текст, сравнивает с образцами и понимает, где алгоритм наверняка ошибся. Вот только настройки T5 были довольно мягкие: пороги сходства текста 0.8 и 0.85. Может, нужно сделать строже?

Первым делом я добавил методы set_thresholds() и set_ultra_strict() в класс T5TextCorrector. Идея была хороша: позволить менять чувствительность фильтра на лету. Включил “ультра-строгий” режим с порогами 0.9 и 0.95 — почти идеальное совпадение текстов.

Потом запустил comprehensive benchmark. Проверил четыре подхода:

  • Базовый + улучшенный T5 (0.8/0.85): 34.0% WER за 0.52 сек — это наша текущая реальность ✓
  • Ультра-строгий T5 (0.9/0.95): 34.9% WER, 0.53 сек — хуже примерно на один процент
  • Beam search с пятью лучами + T5: 42.9% WER за 0.71 сек — катастрофа, качество упало в три раза
  • Только база без T5: 35.8% WER — тоже не помогло

Неожиданно выяснилось: система уже находится на плато оптимизации. Все стандартные техники — ужесточение фильтров, увеличение луча поиска (beam search), комбинирование моделей — просто не работают. Мы выжали максимум из текущей архитектуры.

Интересный факт: T5 создана Google в 2019 году как “Text-to-Text Transfer Transformer” — универсальная модель, которая любую задачу обработки текста формулирует как трансформацию из одного текста в другой. Поэтому одна модель может переводить, суммировать, отвечать на вопросы. Но универсальность имеет цену — специализированные модели часто работают лучше в узкой задаче.

Чтобы прыгнуть на целых 26 процентов вверх (с 34% до 8%), нужно кардинально менять стратегию. Переходить на более мощную Whisper medium? Но это превысит бюджет времени отклика. Обучать свою модель на отраслевых данных? Требует месяцев работы.

В итоге команда приняла решение: оставляем текущую конфигурацию (Whisper base + T5 с порогами 0.8/0.85) как оптимальную. Это лучшее соотношение качества и скорости. Дальнейшие улучшения требуют совсем других подходов — может быть, архитектурных, а не параметрических.

Урок усвоен: не всегда больше параметров и строже правила означают лучше результаты. Иногда система просто сказала тебе: “Достаточно, дальше иди другим путём”.

😄 Почему разработчик попал в плато оптимизации? Потому что все остальные возможности уже были на берегу — нужно было просто заметить, что корабль уже причален!

#git#commit#python#security
Читать далее
6
Исправление

Speech-to-Text под давлением: когда оптимизация упирается в физику

Представь себе ситуацию: нужна система речевого распознавания, которая работает в режиме реального времени. Бюджет — менее одной секунды на обработку аудио. Звучит выполнимо? Pink Elephant, разработчик проекта speech-to-text, решил это проверить экспериментально. И вот что из этого вышло.

Охота на чудо-оптимизацию

Всё начиналось с вопроса: а может ли стандартная модель Whisper работать на этой задаче? Текущие метрики выглядели удручающе — 32,6% WER (Word Error Rate, коэффициент ошибок распознавания). Мечта, конечно, 80% улучшение, но кто ж мечтать не будет.

Первый шаг — попробовать альтернативные модели Whisper. Может, маленькая модель справится быстрее? Tiny дала 56,2% WER — хуже, чем base. Small показала весьма интересный результат: 23,4% WER (28% улучшение!), но потребовала 1,23 секунды обработки. А бюджет-то 1 секунда. Грустно. Medium вообще 3,43 секунды — в три раза медленнее, чем надо.

Потом пришли идеи поумнее: beam search, варьирование температуры, фильтрация результатов через T5 (большую языковую модель для коррекции текста). Но — неожиданно выяснилось — ничего из этого не помогало. Beam search с температурой давал ровно те же 32,6% WER. Разные пороги T5-фильтра (от 0,6 до 0,95) тоже. Зато когда убрали T5 совсем, ошибок стало 41%. T5 оказался спасением, но не панацеей.

Потом попробовали гибридный подход: base-модель для реального времени + medium в фоне. Сложновато, но теоретически возможно. Последовательную обработку (сначала одно, потом другое) пришлось отмести — непрактично.

Когда данные говорят правду

А потом разработчик проанализировал, где именно Whisper base ошибается. Больше всего пропусков (deletions) — 12 ошибок, замены (substitutions) — 6. Проблема не в плохой стратегии обработки, а в самой модели. Вот такой неудобный факт.

Large Language Models как Whisper создаются с применением трансформер-архитектуры, обучаясь на огромных объёмах текстовых данных через самоконтролируемое обучение. И вот в чём закавыка: даже сильные LLM-ы достигают потолка качества, если их заставить работать в несоответствующих условиях. В нашем случае — в режиме реального времени на CPU.

Горькая истина

Итоговый вывод был честный и немного безжалостный: base-модель — единственный вариант, который укладывается в бюджет менее одной секунды, но качество её зафиксировано в 32,6% WER. Small даёт 28% улучшение (23,4% WER), но требует на 230 миллисекунд больше. 80% сокращение ошибок на CPU? Невозможно. Никакая волшебная post-processing техника это не спасёт.

Нужно или переходить на GPU, или согласиться с текущим качеством, или рассмотреть асинхронную фоновую обработку. Тысячи строк кода оптимизации упёрлись в стену физических ограничений. Иногда лучшая оптимизация — это честный разговор о целях проекта.

504: gateway timeout. Ожидание ответа от PM. 😄

#git#commit#api#security
Читать далее
7
Новая функция

Как мы научили микрофон слушать по-умному: история гибридной транскрипции

Представьте себе знакомую ситуацию: вы нажимаете кнопку записи в приложении для голосового ввода, говорите фразу, отпускаете кнопку. Первый результат появляется почти мгновенно — 0.45 секунды, и вы уже можете продолжать работу. Но в фоне, незаметно для вас, происходит волшебство: тот же текст переобрабатывается, улучшается, и спустя 1.23 секунды выдаёт результат на 28% точнее. Это и есть гибридный подход к транскрипции, который мы только что воплотили в проекте speech-to-text.

Задача, которая вставляла палки в колёса

Изначально стояла простая, но коварная проблема: стандартная модель Whisper обеспечивает хорошую скорость, но качество оставляет желать лучшего. WER (word error rate) составлял мрачные 32.6% — представьте, что каждое третье слово может быть неправильным. Пользователь выдвинул чёткое требование: реализовать гибридный подход прямо сейчас, чтобы получить 50% улучшение качества путём тонкой настройки Whisper на русских аудиокнигах.

Первым делом мы переосмыслили архитектуру. Вместо того чтобы ждать идеального результата, который займёт время, мы решили играть в две руки: быстрая базовая модель даёт мгновенный результат, а в параллельном потоке улучшенная модель шлифует текст в фоне. Это похоже на работу водителя-ассистента: первый делает очевидное (едем в основную полосу), а второй уже план Б готовит (проверяет слепые зоны).

Как это реализовалось

Интеграция гибридного подхода потребовала изменений в несколько ключевых мест. В config.py добавили параметры для управления режимом: простое включение-выключение через "hybrid_mode_enabled": true. В main.py реализовали оркестрацию двух потоков транскрипции с координацией результатов. Крайне важным оказался класс HybridTranscriber — именно он управляет тем, как две разные модели работают в унисон.

Неожиданно выяснилось, что потребление памяти выросло на 460 МБ, но оно того стоит: пользователь получает первый результат так же быстро, как раньше (те же 0.45 секунды), а через 1.23 секунды получает улучшенный вариант. Главное — нет ощущения задержки, потому что основной поток не блокируется.

Интересный факт о голосовых помощниках

Забавно, что идея многослойной обработки голоса не нова. Amazon Alexa, созданная с использованием наработок британского учёного Уильяма Танстолл-Педо (его система Evi) и польского синтезатора Ivona (приобретена Amazon в 2012–2013 годах), работает по похожему принципу: быстрая обработка плюс фоновое уточнение. И хотя сейчас Amazon переходит на собственную LLM Nova, суть остаётся той же — многоуровневая архитектура для лучшего пользовательского опыта.

Что дальше

Мы создали полное руководство из 320 строк с инструкциями для финального 50% прироста качества через тонкую настройку на специализированных данных. Это потребует GPU на 2–3 недели ($15–50), но для серьёзных приложений это стоит. А пока пользователи могут включить гибридный режим в течение 30 секунд и сразу почувствовать 28% улучшение.

Документация разложена по полочкам: QUICK_START_HYBRID.md для нетерпеливых, HYBRID_APPROACH_GUIDE.md для любопытных, FINE_TUNING_GUIDE.md для амбициозных. Тесты в test_hybrid.py подтверждают, что всё работает как надо.

Научились простому, но мощному принципу: иногда лучше дать пользователю хороший результат сейчас, чем идеальный результат потом. Почему ZeroMQ не пришёл на вечеринку? Его заблокировал firewall.

#claude#ai#python#javascript#api#security
Читать далее

Оцените материал

0/1000