# 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 не упоминаются.