Files
local-transcriber/docs/specs/2026-08-11-onnx-model-catalog.md
T
Dmitriy Dementiev 7f58a56913 feat(onnx): изменена модель по умолчанию на GigaAM RNN-T
- Зачем:
  - пользователям нужен читаемый транскрипт без обязательной LLM-обработки.
- Что:
  - моделью ONNX по умолчанию выбрана `gigaam-v3-e2e-rnnt`.
  - сохранён явный профиль `gigaam-v3` для более точного сырого текста.
  - обновлены тест, README, спецификация, ADR и benchmark.
- Проверка:
  - `uv run pytest -q` — 226 passed, 1 skipped.
  - `git diff --check`.
2026-08-11 16:47:09 +03:00

173 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Onnx-каталог, Python 3.13 и границы версий
## Проблема
Смешанная русско-английская речь и отсутствие пунктуации у `gigaam-v3-ctc`
известные ограничения onnx-пути ([ADR-006](../adr/006-onnx-asr-backend.md)). В
`onnx-asr` 0.12 появились модели, которые их адресуют, но обновление
заблокировано ограничением `onnx-asr[cpu,hub]>=0.11.0,<0.12.0` в
`pyproject.toml`.
Состояние движков и первичные источники —
[исследование обновлений](../research/2026-08-10-engine-model-updates.md).
## Что делаем
Снимаем ограничение версии, поднимаем `onnx-asr` до 0.12 и делаем
поддерживаемыми четыре модели:
- `gigaam-multilingual-ctc` и `gigaam-multilingual-large-ctc` — смешанная речь
с англоязычными терминами; large добавлена после сравнительного benchmark по
явному решению пользователя;
- `gigaam-v3-e2e-ctc` и `gigaam-v3-e2e-rnnt` — пунктуация и нормализация текста.
Каталог моделей в бэкенде хранит, помимо имени, опубликованные для модели
квантизации — сейчас такого места нет, потому что алиасы отображают имя в имя.
Расширять существующую таблицу или заводить рядом отдельную структуру —
решается при реализации. Passthrough сырых имён onnx-asr сохраняется: он не
мешает и оставляет дверь для экспериментов.
Заодно поднимаем минимальную версию Python до 3.13 и ONNX Runtime до последней
доступной (1.28 на момент написания). Python 3.10 в режиме security-only и
снимается с поддержки в октябре 2026, а ORT 1.28 требует минимум 3.11 — так что
подъём floor и обновление рантайма идут вместе. Следствие: зависимость `tomli` и
условный импорт в `config.py` становятся мёртвым кодом и убираются — начиная с
3.11 есть `tomllib`.
Floor берётся сразу 3.13, а не минимально достаточный 3.11: любой подъём версии
всё равно требует прогона на всех трёх платформах, и дорого именно тестирование,
а не строка в `pyproject.toml`. Один переезд вместо двух. Проект ставится там,
где доступны uv и PyPI, поэтому uv сам поднимет нужный интерпретатор; закрытых
контуров и оффлайн-зеркал среди пользователей нет.
Рабочая версия фиксируется файлом `.python-version` (сейчас его в репозитории
нет). Floor разрешает любой интерпретатор от 3.13 и выше, а пин делает окружение
одинаковым на разных машинах — иначе расхождение вылезает именно тогда, когда
что-то отлаживаешь.
Колёса cp313 проверены для всех нативных зависимостей и всех трёх целевых
платформ — Windows, Linux, macOS: `openvino-genai` 2026.0.0.0, `ctranslate2`
4.7.1, `onnxruntime` 1.28.0. На macOS `openvino-genai` не ставится по
существующему маркеру `sys_platform != 'darwin'`, так что там остаются
faster-whisper на CPU и onnx-путь — это не меняется этой работой, но стоит
помнить, раз появились пользователи на Mac.
GPU-пакеты ORT с их требованием CUDA 13 нас не касаются: CUDA идёт через
CTranslate2, а onnx-путь ставится в CPU-варианте.
## Границы версий
Каждая прямая зависимость получает верхнюю границу по мажорной версии. Причина
не в осторожности вообще, а в канале установки: README предлагает
`uv tool install git+…`, а этот путь резолвит зависимости заново из метаданных
пакета — `uv.lock` в колесо не попадает и не участвует. Диапазоны в
`[project.dependencies]` — единственное, что ограничивает версии на машине
пользователя. Установки в разные месяцы иначе дают разные наборы библиотек при
одном и том же коде, и такие расхождения дороже разбирать, чем поднимать
границы вручную.
Три случая, которые сами собой не решаются:
- **`onnxruntime` объявляется прямой зависимостью с границей**, хотя проект его
не импортирует. `[tool.uv] constraint-dependencies` для этого не годится:
по документации uv он действует только когда uv резолвит сам проект, и
игнорируется, когда пакет ставят как зависимость.
- **`nvidia-cublas-cu12` получает границу по мажорной версии.**
`_cuda_bootstrap.py` преднагружает `libcublas.so.12` по точному soname
([ADR-001](../adr/001-cuda-bootstrap.md)); мажорный апгрейд даёт другой soname
и ломает bootstrap при неизменном коде.
- **`openvino-genai` фиксируется на проверенной линии 2026.0**, а не просто «до
следующего года». Иначе свежая установка подтянет 2026.3 и незаметно поменяет
ту самую точку отсчёта, которую мы договорились не трогать. Границу снимает
отдельная работа по обновлению OpenVINO — осознанно.
Конкретные номера берутся из `uv.lock` при реализации.
## Последующее решение о модели по умолчанию
После сравнительного прогона на трёх реальных записях и обсуждения двух
основных потребителей транскрипта модель `gigaam-v3-e2e-rnnt` выбрана моделью
по умолчанию для явного `--device onnx`. Она всего на 2% медленнее сырого
`gigaam-v3`, но выдаёт пунктуацию для чтения человеком; `gigaam-v3` остаётся
явным профилем с приоритетом дословной точности и последующей обработки LLM.
Это решение не включает ONNX в auto-detect.
## Чего не делаем
- Не меняем auto-detect: ONNX остаётся только явным выбором пользователя.
- Не обновляем OpenVINO, OpenVINO GenAI и CTranslate2. Whisper medium на
OpenVINO — то, с чем сравниваются новые модели; менять его движок
одновременно значит потерять точку отсчёта. Верхние границы версий им при
этом проставляются — см. «Границы версий»; это фиксация текущего состояния, а
не обновление.
- Не добавляем алиасы `large-v3-turbo`, диаризацию, чанкование по паузам и
словарь замен терминов — отдельные пункты [backlog](../backlog.md).
## Ловушки
- **`compute_type` разрешается по устройству, а не по модели.**
`DEVICE_DEFAULTS["onnx"]` даёт `int8` независимо от модели, а `int8`
опубликован не для всех. Для модели без запрошенной квантизации проект должен
взять доступную и сказать об этом; явно заданное пользователем значение
остаётся ошибкой, а не тихой подменой. Явным считается и значение из
`.transcriber.toml`, не только флаг CLI — подстановка допустима лишь там, где
квантизацию выбрал сам проект. Это единственное изменение в каскаде
конфигурации.
- **Язык у multilingual-модели.** Проект по умолчанию форсирует `ru`, а интерес
— как раз смешанная речь. Надо посмотреть, принимает ли модель подсказку языка
или определяет сама, и описать правило в README.
- **E2E меняет форму текста.** Пунктуация и нормализация могут повлиять на
группировку абзацев в `formatter.py` и на предупреждения `quality.py`,
написанные под поведение Whisper.
- **VAD.** В 0.12 исправлены сегменты нулевой длины после VAD — проект
оборачивает модель в `.with_vad()`, так что изменение касается нас напрямую.
## Как проверяем
Работа идёт в отдельной ветке (по конвенции репозитория — `feature/…`), в
`master` вливается только после ручной проверки. Причина не в процессе ради
процесса: переезд на 3.13 пересобирает окружение целиком, и откатывать это на
основной ветке неприятно. Ветка позволяет держать рабочий `master` под рукой,
пока новое окружение не подтвердилось.
Внутри ветки смена окружения и смена библиотеки проверяются раздельно: сначала
Python и зависимости при неизменных моделях — поведение обязано остаться
прежним, — и только потом `onnx-asr` 0.12 с новыми моделями. Иначе при первой же
странности подозреваемых окажется десяток и разделить их будет нечем, CI тут не
поможет.
Проект домашний, CI нет, репрезентативные записи приватны и на разных ноутбуках
разные — автоматическая приёмка невозможна в принципе, уверенность держится на
ручных прогонах. Что она покрывает и чего не покрывает:
- существующие тесты замоканы ([`AGENTS.md`](../../AGENTS.md)) и подтверждают
CLI, конфиг и форматирование, но не работоспособность движка: поломку ORT или
onnx-asr видно только на реальной записи;
- ручные прогоны делаются на Windows и Linux, по всем трём путям — onnx,
openvino, cuda;
- **macOS не проверяется вовсе.** Колёса cp313 там опубликованы, но это
наличие, а не работоспособность; при жалобе с Mac исходить из того, что путь
не валидировался;
- **скорость на Intel Core i5 не измерялась.** Замеры делаются на Ryzen 7
8845H и записываются как наблюдение с указанием CPU — для решения о
CPU-дефолте этого недостаточно;
- **качество моделей измерено предварительно на трёх 14–15-минутных записях.**
Результат фиксирует WER, скорость и ручное чтение, но не заменяет приёмку на
целевом Intel Core i5 и длинных записях; см.
[benchmark](../benchmarks/2026-08-11-gigaam-model-comparison.md).
Пошаговый чеклист и практика прогона нужны только на время работ и живут в
задаче трекера
([#1](https://git.dementev.space/ddmitry/local-transcriber/issues/1)), а не в
этом документе.
## Документация
README: поддерживаемые модели добавляются в таблицу ONNX-моделей. Для готового
читаемого русского текста и как модель по умолчанию используется E2E RNN-T,
для русского без пунктуации и LLM-пайплайнов остаётся явный `gigaam-v3`, для
смешанной речи с приоритетом качества — multilingual large. Скорость на слабых
CPU не измерялась. Требование Python
правится в [`docs/PRD.md`](../PRD.md) — раздел «Требования» и таблица
технологий; в README версии Python не упоминаются.