diff --git a/tests/test_llm_default_model.py b/tests/test_llm_default_model.py index 4e6b85d..da3d6ef 100644 --- a/tests/test_llm_default_model.py +++ b/tests/test_llm_default_model.py @@ -107,6 +107,54 @@ def test_params_model_优先于环境变量(monkeypatch, tmp_path: Path) -> None assert sent[0]["model"] == "工作流/模型" +def test_纠错节点用独立环境变量不受全局模型影响() -> None: + """纠错节点必须能用**独立**环境变量固定模型,不受全局 LLM_MODEL 控制。 + + 回归(本次提交前实测):该节点原先写的是 `os.getenv("LLM_MODEL", "旧模型")` + ——`LLM_MODEL` 存在时(生产环境必有)兜底值永远不会被取到, + 导致"有意保留旧模型"实际失效,真实 LLM 集成测试 + test_generic_correction_generalizes_to_unseen_mishearing 失败。 + + 正确行为:`params.model` > `SUBTITLE_CORRECTION_MODEL` > `LLM_MODEL` > 兜底。 + 这样既保留全局一致(不设置该变量时),又能在该节点需要时单独固定模型。 + """ + import os + from unittest import mock + + from nodes import subtitle_correction as sc + + entries = [{"start": 100.0, "end": 103.0, "text": "もっとマンゴーを舐めてください"}] + sent: list[str] = [] + + class Response: + def __enter__(self): + return self + + def __exit__(self, *args): + return False + + def read(self): + return json.dumps({"choices": [{"message": {"content": "请多舔舔我的小穴"}}]}).encode() + + def fake_open(request, *args, **kwargs): + sent.append(json.loads(request.data)["model"]) + return Response() + + env = {"LLM_MODEL": "全局/模型", "SUBTITLE_CORRECTION_MODEL": "纠错/专用模型"} + with mock.patch.object(urllib.request, "urlopen", fake_open), mock.patch.dict(os.environ, env): + sc.correct_entry(entries[0], entries, 0, {}) + assert sent[-1] == "纠错/专用模型", "独立环境变量应优先于全局 LLM_MODEL" + sc.correct_entry(entries[0], entries, 0, {"model": "参数/模型"}) + assert sent[-1] == "参数/模型", "params.model 优先级最高" + # 未设置独立变量时退回全局 LLM_MODEL(保持单一全局配置能力)。 + with mock.patch.object(urllib.request, "urlopen", fake_open), mock.patch.dict( + os.environ, {"LLM_MODEL": "全局/模型"} + ): + os.environ.pop("SUBTITLE_CORRECTION_MODEL", None) + sc.correct_entry(entries[0], entries, 0, {}) + assert sent[-1] == "全局/模型" + + def test_兜底默认模型按节点职责分离() -> None: """翻译节点跟随 .env 的 LLM_MODEL;纠错节点保留旧默认(实测更优)。