Fix Fun-ASR-Nano fallback for GPT-SoVITS ASR (#2801)

Co-authored-by: LauraGPT <LauraGPT@users.noreply.github.com>
This commit is contained in:
zhifu gao 2026-07-10 17:36:10 +08:00 committed by GitHub
parent bf81cdb14a
commit 551918539c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 100 additions and 8 deletions

71
tests/test_funasr_asr.py Normal file
View File

@ -0,0 +1,71 @@
import importlib.util
import sys
import types
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[1]
MODULE_PATH = ROOT / "tools" / "asr" / "funasr_asr.py"
def load_funasr_asr(monkeypatch, auto_model):
funasr = types.ModuleType("funasr")
funasr.AutoModel = auto_model
monkeypatch.setitem(sys.modules, "funasr", funasr)
modelscope = types.ModuleType("modelscope")
modelscope.snapshot_download = lambda *args, **kwargs: None
monkeypatch.setitem(sys.modules, "modelscope", modelscope)
tqdm = types.ModuleType("tqdm")
tqdm.tqdm = lambda iterable: iterable
monkeypatch.setitem(sys.modules, "tqdm", tqdm)
torch = types.ModuleType("torch")
torch.cuda = types.SimpleNamespace(is_available=lambda: False)
monkeypatch.setitem(sys.modules, "torch", torch)
module_name = "funasr_asr_under_test"
sys.modules.pop(module_name, None)
spec = importlib.util.spec_from_file_location(module_name, MODULE_PATH)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def test_fun_asr_nano_falls_back_to_modelscope_when_hf_config_is_not_resolved(monkeypatch):
calls = []
def fake_auto_model(**kwargs):
calls.append(kwargs.copy())
if kwargs["hub"] == "hf":
raise RuntimeError("model 'FunAudioLLM/Fun-ASR-Nano-2512' is not registered.")
if kwargs["hub"] == "ms":
return types.SimpleNamespace(hub=kwargs["hub"], model_name=kwargs["model"])
raise AssertionError(f"unexpected hub {kwargs['hub']}")
module = load_funasr_asr(monkeypatch, fake_auto_model)
model = module.create_model("zh", backend="fun-asr-nano")
assert model.hub == "ms"
assert model.model_name == "FunAudioLLM/Fun-ASR-Nano-2512"
assert [(call["model"], call["hub"], call["trust_remote_code"]) for call in calls] == [
("FunAudioLLM/Fun-ASR-Nano-2512", "hf", True),
("FunAudioLLM/Fun-ASR-Nano-2512", "ms", False),
]
assert all(call["vad_model"] == "fsmn-vad" for call in calls)
assert all(call["device"] == "cpu" for call in calls)
assert all(call["disable_update"] is True for call in calls)
def test_fun_asr_nano_keeps_non_registration_errors_visible(monkeypatch):
def fake_auto_model(**kwargs):
raise RuntimeError("network unavailable")
module = load_funasr_asr(monkeypatch, fake_auto_model)
with pytest.raises(RuntimeError, match="network unavailable"):
module.create_model("zh", backend="fun-asr-nano")

View File

@ -9,6 +9,11 @@ from modelscope import snapshot_download
from tqdm import tqdm
funasr_models = {} # 存储模型避免重复加载
FUN_ASR_NANO_MODEL_ID = "FunAudioLLM/Fun-ASR-Nano-2512"
FUN_ASR_NANO_MODEL_SOURCES = (
{"model": FUN_ASR_NANO_MODEL_ID, "hub": "hf", "trust_remote_code": True},
{"model": FUN_ASR_NANO_MODEL_ID, "hub": "ms", "trust_remote_code": False},
)
def only_asr(input_file, language, backend="fun-asr-nano"):
@ -21,6 +26,29 @@ def only_asr(input_file, language, backend="fun-asr-nano"):
return text
def is_unregistered_model_error(exc):
message = str(exc).lower()
return "model" in message and "not registered" in message
def create_fun_asr_nano_model(device):
common_kwargs = dict(
vad_model="fsmn-vad",
device=device,
disable_update=True,
)
last_error = None
for model_source in FUN_ASR_NANO_MODEL_SOURCES:
try:
return AutoModel(**model_source, **common_kwargs)
except (KeyError, RuntimeError, ValueError) as exc:
if not is_unregistered_model_error(exc):
raise
last_error = exc
raise last_error
def create_model(language="zh", **kwargs):
backend = kwargs.get("backend", "fun-asr-nano")
@ -33,14 +61,7 @@ def create_model(language="zh", **kwargs):
return funasr_models[cache_key]
if backend == "fun-asr-nano":
model = AutoModel(
model="FunAudioLLM/Fun-ASR-Nano-2512",
trust_remote_code=True,
hub="hf",
vad_model="fsmn-vad",
device=device,
disable_update=True,
)
model = create_fun_asr_nano_model(device)
print(f"FunASR Fun-ASR-Nano 模型加载完成: {language.upper()}")
else:
model = AutoModel(