From a65e5039f55958ebfb84236389da9743ffd45507 Mon Sep 17 00:00:00 2001 From: Dmitry Dementiev Date: Wed, 12 Aug 2026 08:00:46 +0300 Subject: [PATCH] =?UTF-8?q?feat(openvino):=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=20large-v3-turbo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Зачем: - нужен быстрый качественный профиль Whisper для локального распознавания. - Что: - добавлены официальные варианты large-v3-turbo INT8 и FP16. - покрыты каталог, выбор квантизации, ошибка и создание модели. - Проверка: - uv run pytest. --- src/local_transcriber/backends/openvino.py | 2 + tests/test_backend_openvino.py | 55 ++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/local_transcriber/backends/openvino.py b/src/local_transcriber/backends/openvino.py index 0855d63..85b80bd 100644 --- a/src/local_transcriber/backends/openvino.py +++ b/src/local_transcriber/backends/openvino.py @@ -23,6 +23,8 @@ MODEL_REPOS: dict[tuple[str, str], str] = { ("medium", "fp16"): "OpenVINO/whisper-medium-fp16-ov", ("large-v3", "int8"): "OpenVINO/whisper-large-v3-int8-ov", ("large-v3", "fp16"): "OpenVINO/whisper-large-v3-fp16-ov", + ("large-v3-turbo", "int8"): "OpenVINO/whisper-large-v3-turbo-int8-ov", + ("large-v3-turbo", "fp16"): "OpenVINO/whisper-large-v3-turbo-fp16-ov", } # Fallback: если точная пара не найдена, пробуем альтернативный compute_type diff --git a/tests/test_backend_openvino.py b/tests/test_backend_openvino.py index df44470..79c0799 100644 --- a/tests/test_backend_openvino.py +++ b/tests/test_backend_openvino.py @@ -17,6 +17,20 @@ from local_transcriber.types import Segment # === _resolve_repo === +def test_model_catalog_contains_supported_profiles(): + assert MODEL_REPOS == { + ("tiny", "int8"): "OpenVINO/whisper-tiny-int8-ov", + ("base", "fp16"): "OpenVINO/whisper-base-fp16-ov", + ("small", "int8"): "OpenVINO/whisper-small-int8-ov", + ("medium", "int8"): "OpenVINO/whisper-medium-int8-ov", + ("medium", "fp16"): "OpenVINO/whisper-medium-fp16-ov", + ("large-v3", "int8"): "OpenVINO/whisper-large-v3-int8-ov", + ("large-v3", "fp16"): "OpenVINO/whisper-large-v3-fp16-ov", + ("large-v3-turbo", "int8"): "OpenVINO/whisper-large-v3-turbo-int8-ov", + ("large-v3-turbo", "fp16"): "OpenVINO/whisper-large-v3-turbo-fp16-ov", + } + + def test_resolve_repo_exact_match(): backend = OpenVINOBackend(compute_type_explicit=True) assert backend._resolve_repo("medium", "int8") == ("OpenVINO/whisper-medium-int8-ov", "int8") @@ -60,6 +74,26 @@ def test_resolve_repo_explicit_large_v3_int8_respected(): assert backend._resolve_repo("large-v3", "int8") == ("OpenVINO/whisper-large-v3-int8-ov", "int8") +@pytest.mark.parametrize("compute_type", ["int8", "fp16"]) +def test_resolve_repo_large_v3_turbo_quantization(compute_type): + backend = OpenVINOBackend(compute_type_explicit=True) + + assert backend._resolve_repo("large-v3-turbo", compute_type) == ( + f"OpenVINO/whisper-large-v3-turbo-{compute_type}-ov", + compute_type, + ) + + +def test_resolve_repo_large_v3_turbo_unsupported_quantization_raises(): + backend = OpenVINOBackend(compute_type_explicit=True) + + with pytest.raises( + ValueError, + match="Доступные варианты: fp16, int8", + ): + backend._resolve_repo("large-v3-turbo", "float32") + + # === ensure_model_available === @@ -101,6 +135,27 @@ def test_ensure_model_available_downloads(mock_download, tmp_path): assert any("Скачиваю" in s for s in statuses) +@patch("local_transcriber.backends.openvino.snapshot_download") +def test_large_v3_turbo_model_is_resolved_and_created(mock_download, tmp_path): + model_dir = tmp_path / "large-v3-turbo" + model_dir.mkdir() + (model_dir / "openvino_encoder_model.xml").write_text("") + (model_dir / "openvino_decoder_model.xml").write_text("") + mock_download.return_value = str(model_dir) + mock_ov = MagicMock() + + backend = OpenVINOBackend(ov_device="openvino-cpu", compute_type_explicit=True) + model_path = backend.ensure_model_available("large-v3-turbo", "int8") + with patch.dict("sys.modules", {"openvino_genai": mock_ov}): + backend.create_model(model_path, "openvino-cpu", "int8") + + mock_download.assert_called_once_with( + "OpenVINO/whisper-large-v3-turbo-int8-ov", + local_files_only=True, + ) + mock_ov.WhisperPipeline.assert_called_once_with(str(model_dir), "CPU") + + # === create_model ===