docs(specs): дизайн-спек Parakeet backend
- Зачем: - зафиксировать дизайн экспериментального бэкенда до имплементации; гипотеза — Parakeet TDT v3 быстрее/качественнее Whisper на Intel/AMD встройках. - Что: - добавлен docs/superpowers/specs/2026-04-18-parakeet-backend-design.md после 3 раундов adversarial-review. - зафиксированы: onnx-asr+Silero VAD как runtime, CPU EP в MVP, --device parakeet, int8/fp32 compute_type, no-fallback политика, long-audio gate с blocker-thresholds (peak RSS ≤4GB, первый status ≤10с, interval ≤30с, offline после первого запуска). - Проверка: - cat docs/superpowers/specs/2026-04-18-parakeet-backend-design.md.
This commit is contained in:
@@ -0,0 +1,277 @@
|
|||||||
|
# Parakeet backend — design spec
|
||||||
|
|
||||||
|
**Дата:** 2026-04-18
|
||||||
|
**Статус:** Готов к планированию реализации
|
||||||
|
**Ветка реализации:** `feature/parakeet-backend` (в отдельном git worktree)
|
||||||
|
|
||||||
|
## Контекст и гипотеза
|
||||||
|
|
||||||
|
`local-transcriber` — CLI для локальной транскрипции аудио/видео (Whisper). Архитектура pluggable backends (ADR-003): `FasterWhisperBackend` (CTranslate2, CPU/CUDA), `OpenVINOBackend` (Intel CPU/iGPU/NPU). Дефолтный язык — `ru`. Целевая аудитория — ноутбуки с Intel и AMD встройками; NVIDIA — меньшинство.
|
||||||
|
|
||||||
|
**Гипотеза.** NVIDIA Parakeet TDT 0.6B v3 (через ONNX Runtime на CPU) быстрее и/или качественнее Whisper-бэкендов на Intel/AMD встройках. Проверяется прогоном на реальных русских файлах с сравнением wall-clock и качества против OpenVINO-Whisper medium и faster-whisper CPU medium.
|
||||||
|
|
||||||
|
## Выбор технологии (зафиксирован)
|
||||||
|
|
||||||
|
- **Модель:** `nvidia/parakeet-tdt-0.6b-v3` — multilingual, 25 языков включая русский.
|
||||||
|
- **Runtime:** ONNX Runtime через Python-пакет `onnx-asr` ([`istupakov/onnx-asr`](https://github.com/istupakov/onnx-asr)). Отклонены: NeMo toolkit (~1-2GB зависимостей), OpenVINO Parakeet (AMD iGPU не поддерживается, Intel — экспериментальный порт без сообщества).
|
||||||
|
- **Execution Provider в MVP:** CPU. DirectML (Windows AMD/Intel iGPU), ORT-OpenVINO EP, `onnxruntime-gpu` (CUDA) — отдельные фазы после валидации гипотезы.
|
||||||
|
- **VAD:** Silero VAD через `asr.with_vad()` — обязательно (без VAD лимит 20-30 сек на файл; все реальные файлы длиннее).
|
||||||
|
- **Quantization:** `int8` по умолчанию (~670MB диск, ~2GB RAM при inference), `fp32` — опциональное значение `--compute-type float32`.
|
||||||
|
|
||||||
|
## Архитектура
|
||||||
|
|
||||||
|
### Инвариант
|
||||||
|
|
||||||
|
`TranscribeFileResult`, `TranscribeResult`, `Segment`, `format_transcript()` — **не меняем**. Регрессионный риск для существующих Whisper/OpenVINO-путей минимизирован.
|
||||||
|
|
||||||
|
Parakeet интегрируется через две минимальные точки:
|
||||||
|
1. `result.language = "multi"` внутри `ParakeetBackend.transcribe` — соответствует поведению Parakeet v3.
|
||||||
|
2. Атрибут backend-инстанса `effective_model_name` — аналог существующих `actual_compute_type`, `actual_ov_device`.
|
||||||
|
|
||||||
|
CLI после `_transcribe_file` читает `getattr(tfr.backend, "effective_model_name", defaults["model"])` для rich-вывода и `format_transcript(..., model_name=...)`. Rich-строка `Модель: ...` **переносится** после `_transcribe_file` (точка, где уже доступен `tfr.backend`). До транскрипции выводится только `Файл: ...` и сообщения `on_status` от загрузки модели.
|
||||||
|
|
||||||
|
**Шапка транскрипта для Parakeet:** `result.language = "multi"` + `language_mode = "detected"` (CLI форсит `"detected"` при `--device parakeet*`). Формат — `**Язык**: multi (detected)`.
|
||||||
|
|
||||||
|
### Контракт `--language`
|
||||||
|
|
||||||
|
- `result.language = "multi"` всегда.
|
||||||
|
- CLI при `--device parakeet*` форсит `language_mode = "detected"` (независимо от того, задавал ли пользователь `--language`).
|
||||||
|
- **Warning только при явном CLI-флаге `--language`.** Если `language` пришёл из `.transcriber.toml` или `HARDCODED_DEFAULTS` (без явного CLI) — warning подавлен. Источник явности: `cli_values["language"] is not None` (не `"language" in config`).
|
||||||
|
- Текст warning: `Parakeet игнорирует --language; язык определяется автоматически`.
|
||||||
|
|
||||||
|
### Контракт `--compute-type`
|
||||||
|
|
||||||
|
| CLI `--compute-type` | `onnx_asr.load_model(quantization=...)` | Примечание |
|
||||||
|
|----------------------|------------------------------------------|------------|
|
||||||
|
| `int8` | `"int8"` | Дефолт |
|
||||||
|
| `float32` | `None` | Без quantization |
|
||||||
|
| другое | — | `ValueError("Parakeet поддерживает только int8 или float32")` |
|
||||||
|
|
||||||
|
### Контракт VAD — runtime-зависимость, без prefetch
|
||||||
|
|
||||||
|
`ensure_model_available` отвечает только за Parakeet-модель. `create_model` вызывает `onnx_asr.load_vad(model="silero")`, который при первом запуске скачивает Silero VAD (~15MB).
|
||||||
|
|
||||||
|
Одна точка правды — `onnx_asr.load_vad`. Двойной prefetch (наш `snapshot_download` + внутренний `onnx-asr`) без точного знания repo/layout создавал несостыковку: `ensure_model_available` рапортует «готово», но `create_model` всё равно тянет из сети.
|
||||||
|
|
||||||
|
Документировано в ADR-005 и README: **первый запуск `--device parakeet` требует интернет для Silero VAD; повторные — оффлайн** (проверяется в long-audio gate).
|
||||||
|
|
||||||
|
### Контракт fallback — **НЕ fallback'ить Parakeet на Whisper CPU**
|
||||||
|
|
||||||
|
В `load_model` и `_transcribe_file` при `actual_device.startswith("parakeet")` — пропускаем fallback-ветку, исключение пробрасывается наружу.
|
||||||
|
|
||||||
|
Обоснование: Parakeet — другое семейство моделей с другим качеством и семантикой языка (`multi` vs `ru`). Молчаливая подмена на Whisper medium ломает интерпретацию транскрипта. Пользователь видит понятную ошибку (`Ошибка загрузки Silero VAD — проверьте интернет` / `Parakeet inference crashed — см. --verbose`) и делает осознанный выбор.
|
||||||
|
|
||||||
|
### `detect_device` (utils.py)
|
||||||
|
|
||||||
|
`--device auto` **не переключается на Parakeet.** Порядок остаётся: CUDA → OpenVINO GPU → OpenVINO CPU → CPU. Parakeet — только через явный `--device parakeet` / `--device parakeet-cpu`.
|
||||||
|
|
||||||
|
### `config.py`
|
||||||
|
|
||||||
|
```python
|
||||||
|
_VALID_DEVICES = {
|
||||||
|
"auto", "cpu", "cuda",
|
||||||
|
"openvino", "openvino-gpu", "openvino-cpu",
|
||||||
|
"parakeet", "parakeet-cpu",
|
||||||
|
}
|
||||||
|
|
||||||
|
DEVICE_DEFAULTS["parakeet"] = {"model": "parakeet-tdt-0.6b-v3", "compute_type": "int8"}
|
||||||
|
DEVICE_DEFAULTS["parakeet-cpu"] = {"model": "parakeet-tdt-0.6b-v3", "compute_type": "int8"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Config-conflict на `model`.** Если в глобальном `.transcriber.toml` стоит `model = "medium"` и пользователь запускает `--device parakeet` без `--model`, `apply_device_defaults` возьмёт `"medium"` из конфига → `ParakeetBackend.ensure_model_available` кидает **понятный `ValueError`**:
|
||||||
|
|
||||||
|
> `Parakeet поддерживает только 'parakeet-tdt-0.6b-v3' или алиас 'parakeet'. Получено: 'medium'. Передайте --model parakeet или уберите 'model' из .transcriber.toml.`
|
||||||
|
|
||||||
|
Принципиально **не делаем** скрытого override в `apply_device_defaults` — это ломает инвариант «CLI > config > defaults». Пользователь получает ясную ошибку и делает явный фикс.
|
||||||
|
|
||||||
|
Алиас `"parakeet"` → `"parakeet-tdt-0.6b-v3"` допустим в `ensure_model_available` (UX-удобство).
|
||||||
|
|
||||||
|
### Новый бэкенд — `backends/parakeet.py`
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ParakeetBackend:
|
||||||
|
SUPPORTED_MODEL_NAMES = {"parakeet-tdt-0.6b-v3", "parakeet"}
|
||||||
|
SUPPORTED_COMPUTE_TYPES = {"int8", "float32"}
|
||||||
|
|
||||||
|
def __init__(self, compute_type_explicit: bool = True):
|
||||||
|
self._compute_type_explicit = compute_type_explicit
|
||||||
|
self.actual_compute_type: str | None = None
|
||||||
|
self.effective_model_name: str = "parakeet-tdt-0.6b-v3"
|
||||||
|
|
||||||
|
def ensure_model_available(self, model_name, compute_type, on_status) -> str:
|
||||||
|
# 1. model_name ∈ SUPPORTED_MODEL_NAMES иначе ValueError (текст выше)
|
||||||
|
# 2. compute_type ∈ SUPPORTED_COMPUTE_TYPES иначе ValueError
|
||||||
|
# 3. snapshot_download("nvidia/parakeet-tdt-0.6b-v3") → локальный путь
|
||||||
|
# 4. Silero VAD здесь НЕ трогаем (runtime-зависимость)
|
||||||
|
# 5. self.actual_compute_type = compute_type
|
||||||
|
# 6. Возвращаем путь к каталогу
|
||||||
|
|
||||||
|
def create_model(self, model_path, device, compute_type, cpu_threads=0) -> Any:
|
||||||
|
# 1. quantization = "int8" if compute_type == "int8" else None
|
||||||
|
# 2. asr = onnx_asr.load_model("nemo-parakeet-tdt-0.6b-v3", path=model_path, quantization=quantization)
|
||||||
|
# 3. vad = onnx_asr.load_vad(model="silero") # может качать VAD при первом запуске
|
||||||
|
# 4. asr_with_vad = asr.with_vad(vad=vad)
|
||||||
|
# 5. cpu_threads → sess_options через providers_options
|
||||||
|
# 6. Возвращаем asr_with_vad
|
||||||
|
|
||||||
|
def transcribe(self, model, file_path, language, on_segment, on_status) -> TranscribeResult:
|
||||||
|
# 1. Если language задан явно (см. «Контракт --language») — warnings.warn
|
||||||
|
# 2. result = model.recognize(str(file_path))
|
||||||
|
# 3. Поддержка iterator И list (детектим на лету)
|
||||||
|
# 4. Для каждого SegmentResult → Segment(start, end, text); on_segment; on_status c heartbeat
|
||||||
|
# 5. Возвращаем TranscribeResult(segments, language="multi", language_probability=0.0, duration, device_used="")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Регистрация в `backends/__init__.py`
|
||||||
|
|
||||||
|
```python
|
||||||
|
if device in ("parakeet", "parakeet-cpu"):
|
||||||
|
try:
|
||||||
|
from .parakeet import ParakeetBackend
|
||||||
|
except ImportError:
|
||||||
|
raise ValueError(
|
||||||
|
"Parakeet бэкенд недоступен. Установите: pip install onnx-asr[cpu,hub]"
|
||||||
|
) from None
|
||||||
|
return ParakeetBackend(compute_type_explicit=compute_type_explicit)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `transcriber.py` — no-fallback для Parakeet
|
||||||
|
|
||||||
|
```python
|
||||||
|
def _is_parakeet_error(exc: BaseException) -> bool:
|
||||||
|
if isinstance(exc, RuntimeError):
|
||||||
|
return True
|
||||||
|
mod = type(exc).__module__ or ""
|
||||||
|
return "onnxruntime" in mod or "onnx_asr" in mod
|
||||||
|
|
||||||
|
def _is_backend_error(exc, device):
|
||||||
|
if device.startswith("parakeet"):
|
||||||
|
return _is_parakeet_error(exc)
|
||||||
|
# ... existing branches
|
||||||
|
```
|
||||||
|
|
||||||
|
В `load_model` и `_transcribe_file` добавляется ранний выход из fallback-ветки при `actual_device.startswith("parakeet")` — исключение пробрасывается (как будто `strict_device=True`).
|
||||||
|
|
||||||
|
### `cli.py` — точечные изменения
|
||||||
|
|
||||||
|
1. **Rich-строка `Модель: ...` переносится после `_transcribe_file`.** Использует `getattr(tfr.backend, "effective_model_name", defaults["model"])`.
|
||||||
|
2. **`format_transcript(..., model_name=...)`** получает `getattr(tfr.backend, "effective_model_name", defaults["model"])`.
|
||||||
|
3. **`language_mode`** при Parakeet: `if actual_device.startswith("parakeet"): language_mode = "detected"`. Иначе — существующая логика.
|
||||||
|
4. **Warning на явный `--language`** при Parakeet: проверка `cli_values["language"] is not None` (не `"language" in config`). Срабатывает в `_run_single` / `_run_batch` до `_transcribe_file` — пользователь видит сразу.
|
||||||
|
5. **`_format_device_info`**: `if device_used == "parakeet-cpu": return "Parakeet (CPU via ONNX Runtime)"`.
|
||||||
|
|
||||||
|
Для Whisper-бэкендов код не меняется.
|
||||||
|
|
||||||
|
### Progress UX — heartbeat если блокирующий вызов
|
||||||
|
|
||||||
|
Если `asr_with_vad.recognize()` возвращает iterator — итерируем с вызовами `on_status` per segment. Если блокирующий — обёртка в поток с heartbeat-таймером (паттерн `openvino.py::_generate_with_progress`). Тип возврата проверяется в long-audio gate (см. ниже); при блокирующем вызове heartbeat — **обязателен до merge**.
|
||||||
|
|
||||||
|
## Зависимости
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# pyproject.toml
|
||||||
|
dependencies = [
|
||||||
|
# ... existing
|
||||||
|
"onnx-asr[cpu,hub]>=0.7", # минимальная версия уточнить после uv lock
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
`uv lock` обязателен до любой имплементации — проверить, что `onnxruntime` не конфликтует с тем, что тянут `faster-whisper` / `openvino-genai`. Platform markers не нужны: `onnx-asr` — pure Python; `onnxruntime` CPU-wheels покрывают Linux/macOS/Windows × x86_64/arm64.
|
||||||
|
|
||||||
|
## Тесты
|
||||||
|
|
||||||
|
### `tests/test_parakeet_backend.py` — юнит с mock `onnx_asr`
|
||||||
|
|
||||||
|
1. `test_ensure_model_available_accepts_alias` — `model_name="parakeet"` → скачивает `nvidia/parakeet-tdt-0.6b-v3`.
|
||||||
|
2. `test_ensure_model_available_rejects_unknown_model` — `model_name="medium"` → `ValueError` с текстом-подсказкой.
|
||||||
|
3. `test_ensure_model_available_rejects_unknown_compute_type` — `compute_type="float16"` → `ValueError`.
|
||||||
|
4. `test_create_model_maps_compute_type` — `int8` → `quantization="int8"`; `float32` → `quantization=None`.
|
||||||
|
5. `test_transcribe_produces_segments` — mock `recognize` возвращает 3 `SegmentResult` → 3 `Segment`.
|
||||||
|
6. `test_transcribe_warns_on_explicit_cli_language` — явный `--language` → `warnings.warn`.
|
||||||
|
7. `test_transcribe_does_not_warn_on_config_language` — `language` из конфига → warning НЕ срабатывает.
|
||||||
|
8. `test_transcribe_calls_on_segment` — callback на каждый сегмент.
|
||||||
|
9. `test_transcribe_returns_multi_language` — `result.language == "multi"`, `language_probability == 0.0`.
|
||||||
|
10. `test_backend_sets_effective_model_name` — атрибут проставлен.
|
||||||
|
11. `test_transcribe_accepts_list_and_iterator_results` — оба типа возврата обрабатываются.
|
||||||
|
|
||||||
|
### `tests/test_transcriber.py`
|
||||||
|
|
||||||
|
12. `test_load_model_parakeet_no_fallback` — при ошибке Parakeet исключение пробрасывается (без fallback на CPU Whisper).
|
||||||
|
|
||||||
|
### `tests/test_cli.py` — regression + новые
|
||||||
|
|
||||||
|
13. `test_cli_whisper_transcript_header_unchanged` — `--device cpu --language ru` → шапка содержит `**Язык**: ru (forced)` (регрессия отсутствует).
|
||||||
|
14. `test_cli_whisper_auto_language_header_unchanged` — `--device cpu --language auto` → шапка отражает detected-режим.
|
||||||
|
15. `test_cli_parakeet_transcript_header` — `--device parakeet` → шапка `**Язык**: multi (detected)` и `**Модель**: parakeet-tdt-0.6b-v3`.
|
||||||
|
16. `test_cli_parakeet_model_row_shows_effective` — config `model="medium"` + `--device parakeet --model parakeet` → rich-вывод и `format_transcript` получают `parakeet-tdt-0.6b-v3`.
|
||||||
|
17. `test_cli_errors_on_config_model_mismatch_without_override` — config `model="medium"` + `--device parakeet` без `--model` → ясная ошибка (не traceback).
|
||||||
|
18. `test_cli_parakeet_warns_explicit_language` — config без `language`, явный `--language en --device parakeet` → warning.
|
||||||
|
|
||||||
|
Все юнит-тесты — чистые mocks, без реального скачивания.
|
||||||
|
|
||||||
|
## Long-audio verification gate — exit criteria, blocker для merge
|
||||||
|
|
||||||
|
**Метрики и нормы (единственный источник истины):**
|
||||||
|
|
||||||
|
| Метрика | Норма |
|
||||||
|
|---------|-------|
|
||||||
|
| Длина тестового файла | ≥30 минут, русский |
|
||||||
|
| Peak RSS | ≤4 GB |
|
||||||
|
| Первый `on_status` update | ≤10 сек от старта `_transcribe_file` |
|
||||||
|
| Максимальный интервал между `on_status` update'ами | ≤30 сек |
|
||||||
|
| Повторный прогон с `HF_HUB_OFFLINE=1` | без сетевых запросов |
|
||||||
|
|
||||||
|
**Методика измерения:**
|
||||||
|
- Peak RSS: `/usr/bin/time -v ...` (поле "Maximum resident set size") или `psutil.Process().memory_info().rss` из внешнего процесса раз в секунду.
|
||||||
|
- Интервалы `on_status`: специальный тестовый callback в CLI логирует `time.monotonic()` каждого вызова в файл; пост-анализ считает max interval.
|
||||||
|
- Offline: `HF_HUB_OFFLINE=1` через `env`; либо `strace -e trace=connect`, либо проверка отсутствия задержек на сетевых операциях в начале прогона.
|
||||||
|
|
||||||
|
**Blocker-правила (план заморожен до устранения):**
|
||||||
|
- Peak RSS > 4 GB → нужен ручной chunking; MVP не готов.
|
||||||
|
- Первый update > 10 сек ИЛИ любой интервал > 30 сек → нужен heartbeat-thread (паттерн `openvino.py::_generate_with_progress`).
|
||||||
|
- Offline-прогон делает сетевые обращения → VAD-кэш не работает, разбираться до merge.
|
||||||
|
|
||||||
|
Результаты (числа всех метрик) фиксируются в `docs/gpu.md`.
|
||||||
|
|
||||||
|
## Документация
|
||||||
|
|
||||||
|
1. **ADR-005** (`docs/adr/005-parakeet-backend.md`) — контекст, решение (ONNX Runtime + onnx-asr + Silero VAD), отклонённые альтернативы (NeMo toolkit, OpenVINO Parakeet, DirectML в MVP, VAD prefetch, скрытый override в `apply_device_defaults`, cross-backend fallback на Whisper), последствия (язык игнорируется, no fallback, `effective_model_name` через backend-атрибут, VAD runtime-зависимость с требованием интернета на первый запуск).
|
||||||
|
2. **README.md** — секция «Parakeet (экспериментально)»: установка, `--device parakeet`, ограничения (int8/fp32, язык auto, первый запуск — интернет для VAD ~15MB, память ~2GB, конфликт с `model` в конфиге).
|
||||||
|
3. **docs/gpu.md** — секция «Parakeet»: результаты long-audio gate + сравнение с OpenVINO medium / faster-whisper medium CPU на одном и том же RU-файле.
|
||||||
|
|
||||||
|
## Порядок шагов (для writing-plans)
|
||||||
|
|
||||||
|
Вся работа — в git worktree на ветке `feature/parakeet-backend` (через `superpowers:using-git-worktrees`).
|
||||||
|
|
||||||
|
1. **Scaffold + зависимости:** worktree, ветка, `uv add "onnx-asr[cpu,hub]>=0.7"`, `uv lock` → нет конфликтов `onnxruntime` с существующими deps (**блокер**). `uv sync`. Существующие `uv run pytest` зелёные.
|
||||||
|
2. **config.py:** `_VALID_DEVICES` + `DEVICE_DEFAULTS` для parakeet/parakeet-cpu. Тест на валидацию `device = "parakeet"` в конфиге.
|
||||||
|
3. **ParakeetBackend (заглушка):** файл `backends/parakeet.py` со stub'ами (`raise NotImplementedError`). Регистрация в `backends/__init__.py`. Импорт работает без ошибок.
|
||||||
|
4. **`ensure_model_available`:** валидация model_name / compute_type, `snapshot_download`, валидация каталога. Тесты 1-3.
|
||||||
|
5. **`create_model`:** `onnx_asr.load_model + load_vad + with_vad`, маппинг compute_type, cpu_threads. Тест 4.
|
||||||
|
6. **`transcribe`:** итерация `SegmentResult`, warning на язык, `language="multi"`, duration. Тесты 5-11.
|
||||||
|
7. **`transcriber.py` — no-fallback:** `_is_parakeet_error`, ветка в `_is_backend_error`, пропуск fallback при `actual_device.startswith("parakeet")`. Тест 12.
|
||||||
|
8. **cli.py:** перенос строки `Модель:` после `_transcribe_file`, чтение `effective_model_name` через `getattr`, force `language_mode="detected"` для Parakeet, warning на явный CLI `--language`, `_format_device_info` для `parakeet-cpu`. Regression-тесты 13-14, Parakeet-тесты 15-18.
|
||||||
|
9. **Long-audio verification gate:** прогон ≥30-мин RU-файла, замеры всех метрик, оффлайн-повтор. Фиксация в `docs/gpu.md`. **Blocker для merge.**
|
||||||
|
10. **ADR-005 + README** с финальными числами из шага 9.
|
||||||
|
11. **Финал:** `uv run pytest -v` зелёное, `uv run transcribe sample.mp3 --device parakeet` работает end-to-end, PR.
|
||||||
|
|
||||||
|
## Что НЕ делаем в MVP (отложено)
|
||||||
|
|
||||||
|
- DirectML EP для AMD iGPU / Intel iGPU (Windows).
|
||||||
|
- ORT-OpenVINO EP для Intel iGPU/NPU.
|
||||||
|
- Parakeet на CUDA (`onnxruntime-gpu`).
|
||||||
|
- Ручной chunking длинных файлов (доверяем `with_vad` + gate).
|
||||||
|
- `--device auto` включает Parakeet.
|
||||||
|
- Alias `parakeet-tdt-0.6b-v3` для моделей других бэкендов.
|
||||||
|
- Canary (ещё одна NeMo-модель, поддерживается `onnx-asr`).
|
||||||
|
- Prefetch Silero VAD в `ensure_model_available`.
|
||||||
|
- Изменение сигнатур `TranscribeFileResult` / `TranscribeResult` / `format_transcript`.
|
||||||
|
|
||||||
|
## Открытые риски и митигации
|
||||||
|
|
||||||
|
1. **Память на длинных файлах** — gate шага 9; провал → блокер MVP до ручного chunking.
|
||||||
|
2. **Progress UX (блокирующий `recognize`)** — gate шага 9; провал → heartbeat-thread обязателен.
|
||||||
|
3. **Качество на русском** — основная гипотеза; результат фиксируется в `docs/gpu.md`; при ухудшении по сравнению с Whisper — бэкенд остаётся с пометкой «EN лучше, чем RU».
|
||||||
|
4. **Конфликт версий `onnxruntime`** — блокер шага 1; решается через `uv lock` до любой имплементации.
|
||||||
|
5. **VAD offline** — gate шага 9 (`HF_HUB_OFFLINE=1`); провал → разбираться, при необходимости возвращаться к prefetch с реальной проверкой repo/layout.
|
||||||
|
6. **Config-conflict на `model`** — ясная ошибка, не скрытый override.
|
||||||
Reference in New Issue
Block a user