diff --git a/docs/backlog.md b/docs/backlog.md index 2fbaf1c..c9209b9 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -26,6 +26,10 @@ ограничение `onnx-asr<0.12.0`, проверить VAD и квантованные модели; OpenVINO и OpenVINO GenAI обновлять согласованно. Не фиксировать ONNX Runtime 1.28 для Python 3.10. + Шаг 1 в части onnx-пути вынесен в отдельную работу — + [спека «Onnx-каталог, Python 3.13 и границы версий»](specs/2026-08-11-onnx-model-catalog.md): движок + обновляется, три модели становятся поддерживаемыми, дефолт и OpenVINO не + трогаются намеренно, чтобы сохранить точку отсчёта для будущего сравнения. 2. После интеграционных тестов провести сравнительный бенчмарк моделей. Не менять CPU-дефолт только по model card или результату на одном файле. 3. Решение зафиксировать в ADR-007, обновить рекомендации README и только затем @@ -226,6 +230,23 @@ SQL`), словарь пользовательский в `.transcriber.toml`. ## Авто-детект и UX +### Профили намерения вместо выбора модели + +**Что:** Вместо `--model gigaam-v3-e2e-rnnt` пользователь выбирает намерение — +условные `ru-fast`, `ru-readable`, `mixed`, — а проект разворачивает его в пару +модель + квантизация с учётом устройства. + +**Почему:** Имена onnx-моделей ничего не говорят о том, что получит +пользователь, и различие «поддерживаемая модель ≠ рекомендуемая» через них не +выражается. + +**Почему откладывается:** профиль осмыслен, когда известно, какой профиль чем +закрывается — то есть после сравнительной оценки. Введение понятия раньше +данных закрепит догадку в интерфейсе. Источник: +[спека «Onnx-каталог, Python 3.13 и границы версий»](specs/2026-08-11-onnx-model-catalog.md). + +--- + ### Включение `onnx` в `--device auto` **Что:** После периода стабилизации `--device onnx` (несколько недель production-использования без жалоб) — рассмотреть включение в auto-detect chain. diff --git a/docs/specs/2026-08-11-onnx-model-catalog.md b/docs/specs/2026-08-11-onnx-model-catalog.md new file mode 100644 index 0000000..3a41144 --- /dev/null +++ b/docs/specs/2026-08-11-onnx-model-catalog.md @@ -0,0 +1,160 @@ +# 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-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` при реализации. + +## Чего не делаем + +- Не меняем модель по умолчанию и auto-detect: `gigaam-v3` остаётся дефолтом + `--device onnx`. Решение о CPU-дефолте требует замеров на целевом Intel Core + i5, которого сейчас нет в доступе. +- Не обновляем 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-дефолте этого недостаточно; +- **качество моделей друг относительно друга не измерялось.** Ручная проверка + отвечает на вопрос «работает ли», а не «лучше ли»; сравнение — отдельная + работа, см. [backlog](../backlog.md). + +Пошаговый чеклист и практика прогона нужны только на время работ и живут в +задаче трекера +([#1](https://git.dementev.space/ddmitry/local-transcriber/issues/1)), а не в +этом документе. + +## Документация + +README: три модели в таблицу ONNX-моделей. Рекомендация остаётся прежней — +`gigaam-v3` для русского — пока нет данных, чтобы её менять; у новых моделей +стоит оговорка, что скорость на слабых CPU не измерялась. Требование Python +правится в [`docs/PRD.md`](../PRD.md) — раздел «Требования» и таблица +технологий; в README версии Python не упоминаются.