From 937eafe8dbb6e6c553a106b59a063cdbed8f3736 Mon Sep 17 00:00:00 2001 From: Dmitry Dementiev Date: Mon, 21 Sep 2026 22:20:27 +0300 Subject: [PATCH] =?UTF-8?q?fix(device):=20=D0=B7=D0=B0=D0=BA=D1=80=D0=B5?= =?UTF-8?q?=D0=BF=D0=BB=D1=91=D0=BD=20ONNX=20CPU=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=B3=D0=BE=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/local_transcriber/backends/onnx_asr.py | 5 ++-- src/local_transcriber/utils.py | 7 ++---- tests/test_onnx_asr.py | 28 +++++++++++++++++++--- tests/test_utils.py | 10 ++++---- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/local_transcriber/backends/onnx_asr.py b/src/local_transcriber/backends/onnx_asr.py index 498bfb4..5f4a668 100644 --- a/src/local_transcriber/backends/onnx_asr.py +++ b/src/local_transcriber/backends/onnx_asr.py @@ -200,8 +200,9 @@ class OnnxAsrBackend: model = onnx_asr.load_model( model=model_path, quantization=quantization, + providers=["CPUExecutionProvider"], ) - vad = onnx_asr.load_vad("silero") + vad = onnx_asr.load_vad("silero", providers=["CPUExecutionProvider"]) self._vad = vad return model.with_vad(vad).with_timestamps() @@ -278,7 +279,7 @@ class OnnxAsrBackend: fallback = _whisper_fallback_model(model_name) raise ValueError( f"Модель '{model_name}' относится к Whisper и не поддерживается " - "ONNX-бэкендом. Без CUDA --device auto выбирает ONNX; " + "ONNX-бэкендом. --device auto всегда выбирает ONNX CPU; " f"укажите --device openvino-cpu --model {model_name} на x86, " f"--device cpu --model {fallback} на любой платформе " f"или --device cuda --model {fallback} при NVIDIA GPU." diff --git a/src/local_transcriber/utils.py b/src/local_transcriber/utils.py index 8cfafe0..84e8a22 100644 --- a/src/local_transcriber/utils.py +++ b/src/local_transcriber/utils.py @@ -2,7 +2,6 @@ import glob import platform -import shutil import subprocess import warnings from pathlib import Path @@ -16,15 +15,13 @@ SUPPORTED_EXTENSIONS = { def detect_device(requested: str = "auto") -> str: """Определяет устройство для вычислений. - При ``requested="auto"`` выбирает CUDA при наличии ``nvidia-smi``, - иначе ONNX на CPU. + При ``requested="auto"`` всегда выбирает ONNX на CPU. + CUDA включается только явным выбором пользователя. ``"openvino"`` — алиас для авто-детекта внутри OpenVINO (GPU если доступен, иначе CPU). Возвращает всегда конкретное значение (не абстрактный ``"openvino"``). """ if requested == "auto": - if shutil.which("nvidia-smi") is not None: - return "cuda" return "onnx" if requested == "openvino": if _is_openvino_gpu_available(): diff --git a/tests/test_onnx_asr.py b/tests/test_onnx_asr.py index e6e2734..118d7b6 100644 --- a/tests/test_onnx_asr.py +++ b/tests/test_onnx_asr.py @@ -1,6 +1,7 @@ """Tests for onnx-asr backend.""" import warnings +from unittest.mock import MagicMock import pytest @@ -64,12 +65,12 @@ class TestEnsureModelAvailable: def with_timestamps(self): return self - def fake_load_model(*, model, quantization): + def fake_load_model(*, model, quantization, providers): quantizations.append(quantization) return FakeAsrAdapter() monkeypatch.setattr("onnx_asr.load_model", fake_load_model) - monkeypatch.setattr("onnx_asr.load_vad", lambda model: None) + monkeypatch.setattr("onnx_asr.load_vad", lambda model, **kwargs: None) backend = OnnxAsrBackend(compute_type_explicit=False) model_id = backend.ensure_model_available( @@ -87,6 +88,26 @@ class TestEnsureModelAvailable: class TestCreateModel: + def test_cpu_provider_is_explicit_for_asr_and_vad(self, monkeypatch): + """Доступность CoreML/CUDA не меняет исполнение ASR и VAD.""" + monkeypatch.setattr( + "onnxruntime.get_available_providers", + lambda: ["CoreMLExecutionProvider", "CUDAExecutionProvider", "CPUExecutionProvider"], + ) + load_asr = MagicMock() + load_vad = MagicMock() + monkeypatch.setattr("onnx_asr.load_model", load_asr) + monkeypatch.setattr("onnx_asr.load_vad", load_vad) + + OnnxAsrBackend().create_model("gigaam-v3-e2e-rnnt", "onnx", "int8") + + load_asr.assert_called_once_with( + model="gigaam-v3-e2e-rnnt", + quantization="int8", + providers=["CPUExecutionProvider"], + ) + load_vad.assert_called_once_with("silero", providers=["CPUExecutionProvider"]) + def test_wraps_vad_model_with_timestamps(self, monkeypatch): timestamped_model = object() @@ -99,7 +120,7 @@ class TestCreateModel: return FakeVadAdapter() monkeypatch.setattr("onnx_asr.load_model", lambda **kwargs: FakeAsrAdapter()) - monkeypatch.setattr("onnx_asr.load_vad", lambda model: object()) + monkeypatch.setattr("onnx_asr.load_vad", lambda model, **kwargs: object()) model = OnnxAsrBackend().create_model("gigaam-v3-e2e-rnnt", "onnx", "int8") @@ -127,6 +148,7 @@ class TestCreateModel: return self monkeypatch.setattr("onnx_asr.load_model", fake_load_model) + monkeypatch.setattr("onnx_asr.load_vad", lambda model, **kwargs: None) backend = OnnxAsrBackend() backend.actual_compute_type = "int8" diff --git a/tests/test_utils.py b/tests/test_utils.py index 0d919ea..223b9a0 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -66,17 +66,17 @@ def test_detect_device_explicit_passthrough(): assert detect_device("openvino-cpu") == "openvino-cpu" -def test_detect_device_auto_cuda_when_nvidia_smi_available(): - """При доступном nvidia-smi auto выбирает CUDA.""" +def test_detect_device_auto_onnx_when_nvidia_smi_available(): + """При доступном nvidia-smi auto остаётся на ONNX CPU.""" with patch( - "local_transcriber.utils.shutil.which", return_value="/usr/bin/nvidia-smi" + "shutil.which", return_value="/usr/bin/nvidia-smi" ): - assert detect_device("auto") == "cuda" + assert detect_device("auto") == "onnx" def test_detect_device_auto_onnx_without_cuda(): """Без CUDA auto выбирает ONNX CPU.""" - with patch("local_transcriber.utils.shutil.which", return_value=None): + with patch("shutil.which", return_value=None): assert detect_device("auto") == "onnx"