diff --git a/nodes/llm_loader.py b/nodes/llm_loader.py index f9b831f..5aa9ce4 100644 --- a/nodes/llm_loader.py +++ b/nodes/llm_loader.py @@ -12,6 +12,7 @@ _BASE_URL_MAPPING = { "MiniMax/MiniMax": "https://api.minimax.chat/v1", "StepFun/阶跃星辰": "https://api.stepfun.com/v1", "SenseChat/日日新": "https://api.sensenova.cn/compatible-mode/v1", + "iFlow/心流": "https://apis.iflow.cn/v1", } @@ -35,6 +36,7 @@ class LLM_Loader: "MiniMax/MiniMax", "StepFun/阶跃星辰", "SenseChat/日日新", + "iFlow/心流", "Custom/自定义" ], { "default": "Qwen/通义千问" diff --git a/nodes/llm_translator.py b/nodes/llm_translator.py index a61dd2b..e177882 100644 --- a/nodes/llm_translator.py +++ b/nodes/llm_translator.py @@ -63,6 +63,8 @@ class LLMTranslator: temperature: float = 0.3 ) -> str: """调用LLM API - 核心通信逻辑""" + import ssl + base_url = llm_config.get("base_url", "").rstrip("/") model = llm_config.get("model", "") api_key = llm_config.get("api_key", "") @@ -80,27 +82,39 @@ class LLMTranslator: "max_tokens": 4096 } - try: - req = urllib.request.Request( - url, - data=json.dumps(payload).encode("utf-8"), - headers=headers, - method="POST" - ) - - with urllib.request.urlopen(req, timeout=60) as response: - data = json.loads(response.read().decode("utf-8")) - - if "choices" not in data or not data["choices"]: - raise ValueError("Empty response from API") - - return data["choices"][0]["message"]["content"].strip() + ctx = ssl.create_default_context() + last_error = None - except urllib.error.HTTPError as e: - error_body = e.read().decode("utf-8", errors="ignore") - raise Exception(f"HTTP Error {e.code}: {error_body}") - except Exception as e: - raise Exception(f"Translation failed: {str(e)}") + for attempt in range(3): + try: + req = urllib.request.Request( + url, + data=json.dumps(payload).encode("utf-8"), + headers=headers, + method="POST" + ) + + with urllib.request.urlopen(req, timeout=60, context=ctx) as response: + data = json.loads(response.read().decode("utf-8")) + + if "choices" not in data or not data["choices"]: + raise ValueError("Empty response from API") + + return data["choices"][0]["message"]["content"].strip() + + except urllib.error.HTTPError as e: + error_body = e.read().decode("utf-8", errors="ignore") + raise Exception(f"HTTP Error {e.code}: {error_body}") + except (ssl.SSLError, urllib.error.URLError, ConnectionError, TimeoutError) as e: + last_error = e + print(f"[LLMs_Toolkit] Translator attempt {attempt + 1}/3 failed: {e}") + import time + time.sleep(1) + continue + except Exception as e: + raise Exception(f"Translation failed: {str(e)}") + + raise Exception(f"Translation failed after 3 attempts: {last_error}") def translate( self,