Вот сидите вы и пишете голосового ассистента для врачей. Всё работает, пока пациент не ляпнет «Ацетилсалициловая кислота». И тут модель выдаёт что-то вроде «ацетил силиконовая кислота». Знакомо? Стандартные ASR-модели тренированы на общих данных — они тупят на редких терминах, именах и названиях компаний.
Можно дообучить модель. Но это дорого, нужно собирать размеченный корпус, гонять fine-tuning неделями. А если завтра сменился список препаратов или появился новый сленг — опять переобучать. Есть способ проще: ASR bias (смещение декодера). Смысл в том, чтобы подкрутить вероятности нужных слов прямо во время распознавания, без пересборки весов. О том, как это сделать своими руками на open-source стеке, и поговорим.
Если вы ещё не выбрали базовую модель — гляньте наше сравнение актуальных ASR-моделей для английского. Спойлер: Whisper по-прежнему хорош, но и Parakeet от NVIDIA дышит в спину.
Что такое bias в ASR и зачем он вам (спойлер: вы сэкономите недели)
Базовый принцип: на этапе декодирования мы вводим дополнительную информацию — список слов или фраз с весами. Чем выше вес, тем охотнее модель выбирает этот токен, даже если акустический сигнал неидеален. Это не магия, а обычное логарифмическое смещение логарифмов вероятностей.
Представьте, что у вас есть список названий лекарств, которые модель постоянно коверкает. Вы задаёте bias-файл вида:
[
{"word": "ацетилсалициловая", "weight": 10},
{"word": "метформина гидрохлорид", "weight": 8}
]Декодер прибавляет логарифм веса к скорам соответствующих токенов. Если слово распадается на несколько токенов — веса суммируются по правилу среднегеометрического. Всё честно, без подтасовок.
Важный нюанс: bias не убирает все ошибки. Если акустика совсем плохая (шум, дикция с кашей во рту), bias может лишь слегка подтолкнуть. Но для чистых диктофонных записей или звонков — это спасение.
Открытая реализация: как это работает на практике
Мы взяли за основу Whisper large-v3 (последняя стабильная версия на июнь 2026) и встроили bias через модификацию лог-пробы декодера. Код полностью открытый, лежит на GitHub. Поддерживаются все модели семейства Whisper, а также любые модели на базе CTC (wav2vec 2.0, Branchformer) — нужно лишь адаптировать интерфейс логарифмов.
Основная идея: после получения финальных лог-пробы для каждого токена мы прибавляем bias-вектор, сгенерированный из вашего списка. Если слово из bias-листа состоит из нескольких токенов (BPE), мы маппим его на соответствующие позиции и добавляем вес к каждому входящему в слово токену.
Вот упрощённый сниппет той части, где происходит добавление bias:
def apply_bias(logits, bias_dict, tokenizer):
# bias_dict: {token_id: log_bias_weight}
for token_id, weight in bias_dict.items():
logits[:, :, token_id] += weight
return logitsНо на деле bias-слова нужно предварительно токенизировать и разобрать по токенам. Полный рабочий пример смотрите в коде ниже.
1Подготовка bias-словаря
Сначала собираем список слов, которые модель должна узнавать точнее. Для медицинского случая это:
bias_phrases = ["ацетилсалициловая кислота", "метформина гидрохлорид", "клопидогрел"]
weights = [10.0, 8.0, 9.0]Токенизируем каждую фразу, получаем последовательности ID токенов. Если фраза разбивается на части, мы делим вес на количество токенов (лог-сложение), чтобы итоговый вес был равномерный. Собираем словарь token_id → weight.
2Интеграция bias в пайплайн транскрипции
import whisper
import numpy as np
def transcribe_with_bias(audio_path, bias_dict):
model = whisper.load_model("large-v3")
audio = whisper.load_audio(audio_path)
audio = whisper.pad_or_trim(audio)
mel = whisper.log_mel_spectrogram(audio).to(model.device)
# Декодируем с помощью модифицированного семплирования
options = whisper.DecodingOptions(language="ru", without_timestamps=True, fp16=False)
result = model.decode(mel, options, bias_dict=bias_dict)
return result.textМы расширили DecodingOptions, добавив параметр bias_dict. Внутри decode() перед выбором следующего токена вызывается apply_bias(). Всё делается за один проход, без пересборки графа.
Честное предупреждение: в официальном репозитории Whisper нет такой опции. Мы форкнули и добавили сами. Код доступен на GitHub (ссылка будет в конце). Но вы можете легко повторить — правка в файле decoding.py занимает 15 строк.
Сравнение с альтернативами: почему bias, а не дообучение
| Метод | Время настройки | Гибкость | Риск деградации |
|---|---|---|---|
| Fine-tuning | от 48 часов | Требует датасет | Может забыть общую лексику |
| N-gram LM rescoring (Kaldi, Flashlight) | 2–4 часа | Нужна внешняя LM | Не меняет акустику |
| Bias (наш метод) | 10 минут | Список слов — и готово | Минимальный при разумных весах |
Fine-tuning — это тяжёлая артиллерия. Его стоит применять, если нужно сменить язык или домен полностью (например, адаптировать модель для русской речи с архитектурой SALM). Но когда задача — просто добавить десяток терминов, bias выигрывает по скорости в 300 раз.
N-gram rescoring, как в подходах с глубиной LM, тоже работает. Но он добавляет второй проход, усложняет конвейер. Bias же встраивается прямо в декодер, не требуется никаких внешних библиотек.
Из коммерческих решений: Cohere Transcribe и AssemblyAI поддерживают Hotwords через API. Но это закрытый код, вы платите за каждый час и привязаны к облаку. Наш подход — локальный, бесплатный, подходит для конфиденциальных данных (про сборку локального ASR мы писали вот здесь).
Пример из жизни: как bias спас транскрипцию IT-конференции
Недавно мы настраивали распознавание для записи русскоязычного митапа по MLOps. Спикеры то и дело сыпали терминами: «DVC» (Data Version Control), «CML» (Continuous Machine Learning), «Airflow». Стандартный Whisper large-v3 превращал «DVC» в «ди-ви-си» или «диВиСи». Добавили bias с весом 12 для каждого из этих сокращений — и результат стал близок к идеалу. Единичные пропуски остались только при явном шуме.
Ранее мы описывали фиксы для гибридного русского и английского — bias хорошо ложится поверх тех решений. Комбинация кастомного постпроцессинга и смещения даёт синергию.
Кому это реально упростит жизнь
- Разработчикам медицинских систем — чтобы диктовать лекарства без искажений.
- Создателям голосовых ассистентов для юристов — там каждое слово в договоре на вес золота.
- Интеграторам call-центров — чтобы «передайте трубочку» не превращалось в «передайте трубку».
- Любому, кто мучается с распознаванием на узком домене (геймдев, финансы, мода).
Инструмент лёгкий, встраивается за вечер. Единственное, о чём стоит помнить: не используйте слишком высокие веса (больше 20), иначе модель начнёт галлюцинировать bias-слова там, где их нет. А так — берите и делайте.
PS: Полный код пакета с примерами и тестами выложен в репозиторий. Инструкция по установке и API описаны в README. Если уткнётесь в баги — пишите issue, контрибьюторы welcome.