From baf0e8ec1f462a3dc6f801e6ceb3f026a1e65ad3 Mon Sep 17 00:00:00 2001 From: Tanishq Date: Fri, 13 Nov 2026 02:44:38 +0530 Subject: [PATCH] fix(websocket): build the offline model from --asr_model funasr_wss_server.py parses --asr_model and --asr_model_revision, and the README lists --asr_model, but since #2791 the server built its offline model from a fixed "paraformer-zh" v2.0.4. Both options had no effect, so a server started with another model, such as an English or a fine-tuned one, still ran paraformer-zh. Build the offline model from the two options, as the streaming, VAD and punctuation models are built from theirs. The default of --asr_model becomes "paraformer-zh" (it named the Contextual Paraformer, which the server did not load), so a server started without these options loads the same model as before. Add tests/test_websocket_server_asr_model.py: it runs the server module with AutoModel replaced and checks the model and revision of the offline model, with and without the options. --- runtime/python/websocket/funasr_wss_server.py | 6 +- tests/test_websocket_server_asr_model.py | 64 +++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/test_websocket_server_asr_model.py diff --git a/runtime/python/websocket/funasr_wss_server.py b/runtime/python/websocket/funasr_wss_server.py index 2a449e6423..394052baec 100644 --- a/runtime/python/websocket/funasr_wss_server.py +++ b/runtime/python/websocket/funasr_wss_server.py @@ -45,7 +45,7 @@ def to_python(obj): parser.add_argument( "--asr_model", type=str, - default="iic/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404", + default="paraformer-zh", help="model from modelscope", ) parser.add_argument("--asr_model_revision", type=str, default="v2.0.4", help="") @@ -235,8 +235,8 @@ def save_offline_wav_segment_sync(websocket, audio_bytes: bytes, reason: str = " # ====== 离线 ASR ====== model_asr = AutoModel( - model="paraformer-zh", - model_revision="v2.0.4", + model=args.asr_model, + model_revision=args.asr_model_revision, ngpu=args.ngpu, ncpu=args.ncpu, device=args.device, diff --git a/tests/test_websocket_server_asr_model.py b/tests/test_websocket_server_asr_model.py new file mode 100644 index 0000000000..b1bab606fb --- /dev/null +++ b/tests/test_websocket_server_asr_model.py @@ -0,0 +1,64 @@ +"""Offline model options of runtime/python/websocket/funasr_wss_server.py. + +The README documents ``--asr_model`` for this server. The server parsed ``--asr_model`` and +``--asr_model_revision`` but built its offline model from a fixed "paraformer-zh" v2.0.4, +so both options had no effect. +""" + +import importlib.util +import sys +import types +from pathlib import Path + +import pytest + +ROOT = Path(__file__).resolve().parents[1] +SERVER_PATH = ROOT / "runtime/python/websocket/funasr_wss_server.py" + + +def load_server(monkeypatch, *options): + """Run the server module with these command-line options; it builds its models on import.""" + pytest.importorskip("numpy") + # Each AutoModel call returns its keyword arguments. + funasr = types.ModuleType("funasr") + funasr.AutoModel = types.SimpleNamespace + monkeypatch.setitem(sys.modules, "funasr", funasr) + # Stand-ins for the modules the server uses to serve requests, not to build its models. + stand_ins = { + name: types.ModuleType(name) + for name in ("websockets", "torch", "scipy", "scipy.spatial", "scipy.spatial.distance") + } + stand_ins["scipy.spatial.distance"].cosine = None + for name, module in stand_ins.items(): + monkeypatch.setitem(sys.modules, name, module) + monkeypatch.setattr(sys, "argv", [str(SERVER_PATH), *options]) + spec = importlib.util.spec_from_file_location("funasr_wss_server_asr_model", SERVER_PATH) + server = importlib.util.module_from_spec(spec) + spec.loader.exec_module(server) + server.EXECUTOR.shutdown(wait=True) + return server + + +def test_default_offline_model_is_unchanged(monkeypatch): + server = load_server(monkeypatch) + assert server.model_asr.model == "paraformer-zh" + assert server.model_asr.model_revision == "v2.0.4" + + +@pytest.mark.parametrize( + "options, model, revision", + [ + (["--asr_model", "paraformer-en"], "paraformer-en", "v2.0.4"), + ( + ["--asr_model", "/models/my-paraformer", "--asr_model_revision", "master"], + "/models/my-paraformer", + "master", + ), + ], +) +def test_asr_model_options_select_the_offline_model(monkeypatch, options, model, revision): + server = load_server(monkeypatch, *options) + assert server.model_asr.model == model + assert server.model_asr.model_revision == revision + # The streaming model keeps its own options. + assert server.model_asr_streaming.model == server.args.asr_model_online