From 1c6e01087b381bc60d2e95c1ba8237036a385277 Mon Sep 17 00:00:00 2001 From: cat-shark Date: Thu, 13 Aug 2026 22:01:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20LLM=20=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E8=B6=85=E6=97=B6=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 1 + tests/test_llm_node.py | 48 ++++++++++++++++++++++++++++++++++++++++ wov_node_llm/__main__.py | 3 ++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 52a1507..62c73fa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,3 +16,4 @@ - `LLM_API_BASE`:兼容接口地址,默认 `http://192.168.123.70:8080/v1/chat/completions`。 - `LLM_API_KEY`:可选。 - `LLM_MODEL`:默认模型,默认值 `default`。 +- `LLM_TIMEOUT_SECONDS`:单次请求超时,默认 `600`。 diff --git a/tests/test_llm_node.py b/tests/test_llm_node.py index 738ed02..63b62d4 100644 --- a/tests/test_llm_node.py +++ b/tests/test_llm_node.py @@ -10,6 +10,22 @@ from wov_node_llm.__main__ import invoke, translate_lines from wov_sdk.models import InvokeRequest +class FakeUrlOpenResponse: + def __init__(self, content: str) -> None: + self._payload = json.dumps( + {"choices": [{"message": {"content": content}}]} + ).encode("utf-8") + + def read(self) -> bytes: + return self._payload + + def __enter__(self): + return self + + def __exit__(self, *args) -> bool: + return False + + def _make_srt(tmp_path, count=5) -> Path: lines = [] for index in range(count): @@ -83,6 +99,38 @@ def test_translate_lines_api_error(monkeypatch) -> None: pass +def test_translate_lines_default_timeout(monkeypatch) -> None: + captured = {} + + def fake_open(request, timeout): + captured["timeout"] = timeout + return FakeUrlOpenResponse("译文一") + + monkeypatch.setattr("wov_node_llm.__main__.urllib.request.urlopen", fake_open) + monkeypatch.setenv("LLM_API_BASE", "http://fake/v1/chat/completions") + + result = translate_lines(["一"], {}) + + assert result == ["译文一"] + assert captured["timeout"] == 600 + + +def test_translate_lines_env_timeout(monkeypatch) -> None: + captured = {} + + def fake_open(request, timeout): + captured["timeout"] = timeout + return FakeUrlOpenResponse("译文一") + + monkeypatch.setattr("wov_node_llm.__main__.urllib.request.urlopen", fake_open) + monkeypatch.setenv("LLM_API_BASE", "http://fake/v1/chat/completions") + monkeypatch.setenv("LLM_TIMEOUT_SECONDS", "45") + + translate_lines(["一"], {}) + + assert captured["timeout"] == 45 + + def test_invoke_success(tmp_path, monkeypatch) -> None: source = _make_srt(tmp_path) diff --git a/wov_node_llm/__main__.py b/wov_node_llm/__main__.py index 2d813c8..cccd6d8 100644 --- a/wov_node_llm/__main__.py +++ b/wov_node_llm/__main__.py @@ -18,6 +18,7 @@ def translate_lines(lines: list[str], params: dict) -> list[str]: "http://192.168.123.70:8080/v1/chat/completions", ) api_key = os.getenv("LLM_API_KEY", "") + request_timeout = float(os.getenv("LLM_TIMEOUT_SECONDS", "600")) model = str(params.get("model") or os.getenv("LLM_MODEL", "default")) target_language = str(params.get("target_language", "zh-CN")) system_prompt = ( @@ -43,7 +44,7 @@ def translate_lines(lines: list[str], params: dict) -> list[str]: headers=headers, method="POST", ) - with urllib.request.urlopen(request, timeout=120) as response: + with urllib.request.urlopen(request, timeout=request_timeout) as response: payload = json.loads(response.read().decode("utf-8")) content = payload["choices"][0]["message"]["content"] translated.extend(