diff --git a/data/chroma/kb_3/8aa4b792-80c2-4a03-a4d0-c024eeb961c9/data_level0.bin b/data/chroma/kb_3/8aa4b792-80c2-4a03-a4d0-c024eeb961c9/data_level0.bin index 0ff0149..7654f2d 100644 Binary files a/data/chroma/kb_3/8aa4b792-80c2-4a03-a4d0-c024eeb961c9/data_level0.bin and b/data/chroma/kb_3/8aa4b792-80c2-4a03-a4d0-c024eeb961c9/data_level0.bin differ diff --git a/data/chroma/kb_3/chroma.sqlite3 b/data/chroma/kb_3/chroma.sqlite3 index af6e5fa..1a0a231 100644 Binary files a/data/chroma/kb_3/chroma.sqlite3 and b/data/chroma/kb_3/chroma.sqlite3 differ diff --git a/th_agenter/services/llm_service.py b/th_agenter/services/llm_service.py index 466d9c5..1dc560e 100644 --- a/th_agenter/services/llm_service.py +++ b/th_agenter/services/llm_service.py @@ -22,12 +22,34 @@ class LLMService: max_tokens: Optional[int] = None ) -> str: """调用大模型进行对话完成""" + # 处理 base_url:如果包含 /chat/completions,需要移除 + base_url = model_config.base_url + if base_url and '/chat/completions' in base_url: + # 移除 /chat/completions 后缀,ChatOpenAI 会自动添加 + base_url = base_url.replace('/chat/completions', '').rstrip('/') + logger.debug(f"调整 base_url: {model_config.base_url} -> {base_url}") + + # 处理 SiliconFlow 的模型名称格式 + model_name = model_config.model_name + if 'siliconflow' in (base_url or '').lower() and '/' not in model_name: + # SiliconFlow 需要 org/model 格式,尝试自动转换 + model_name_lower = model_name.lower() + if 'deepseek' in model_name_lower or 'r1' in model_name_lower: + # 尝试常见的 DeepSeek 模型格式 + if 'r1' in model_name_lower: + model_name = 'deepseek-ai/DeepSeek-R1' + elif 'v3' in model_name_lower: + model_name = 'deepseek-ai/DeepSeek-V3' + else: + model_name = f'deepseek-ai/{model_name}' + logger.debug(f"调整 SiliconFlow 模型名称: {model_config.model_name} -> {model_name}") + try: # 创建LangChain ChatOpenAI实例 llm = ChatOpenAI( - model=model_config.model_name, + model=model_name, api_key=model_config.api_key, - base_url=model_config.base_url, + base_url=base_url, temperature=temperature or model_config.temperature, max_tokens=max_tokens or model_config.max_tokens, streaming=False @@ -53,8 +75,41 @@ class LLMService: return response.content except Exception as e: - logger.error(f"LLM调用失败: {str(e)}") - raise Exception(f"LLM调用失败: {str(e)}") + # 提取详细的错误信息 + error_detail = str(e) + + # 尝试从异常对象中提取更多信息 + if hasattr(e, 'response'): + # HTTP 响应错误 + if hasattr(e.response, 'status_code'): + error_detail = f"HTTP {e.response.status_code}: {error_detail}" + if hasattr(e.response, 'text'): + try: + import json + error_body = json.loads(e.response.text) + if isinstance(error_body, dict): + if 'message' in error_body: + error_detail = f"{error_detail} - {error_body['message']}" + if 'error' in error_body: + error_info = error_body['error'] + if isinstance(error_info, dict) and 'message' in error_info: + error_detail = f"{error_detail} - {error_info['message']}" + except: + pass + + # 添加模型配置信息到错误消息中(使用处理后的配置) + model_info = f"模型: {model_name}, base_url: {base_url}" + if 'Not Found' in error_detail or '404' in error_detail: + error_detail = f"{error_detail} ({model_info})。可能的原因:1) 模型名称格式不正确(SiliconFlow需要org/model格式,如deepseek-ai/DeepSeek-R1);2) base_url配置错误;3) API端点不存在" + elif '403' in error_detail or 'account balance' in error_detail.lower() or 'insufficient' in error_detail.lower(): + error_detail = f"{error_detail} ({model_info})。可能的原因:账户余额不足或API密钥权限不足" + elif '401' in error_detail or 'authentication' in error_detail.lower(): + error_detail = f"{error_detail} ({model_info})。可能的原因:API密钥无效或已过期" + else: + error_detail = f"{error_detail} ({model_info})" + + logger.error(f"LLM调用失败: {error_detail}") + raise Exception(f"LLM调用失败: {error_detail}") async def chat_completion_stream( self, diff --git a/th_agenter/services/workflow_engine.py b/th_agenter/services/workflow_engine.py index f786961..81ba93d 100644 --- a/th_agenter/services/workflow_engine.py +++ b/th_agenter/services/workflow_engine.py @@ -831,7 +831,23 @@ class WorkflowEngine: except Exception as e: error_msg = str(e) - logger.error(f"LLM调用失败: {error_msg}") + # LLMService 已经添加了详细的错误信息(包括处理后的模型名称和base_url),直接使用 + # 如果错误信息中已经包含了模型信息,就不再重复添加 + detailed_error = error_msg + + # 如果错误信息中还没有包含模型配置信息,则添加(使用原始配置作为补充) + if "使用的模型:" not in error_msg and "模型:" not in error_msg: + model_info = f"使用的模型: {llm_config.model_name} (ID: {llm_config.id}), base_url: {llm_config.base_url}" + if "Not Found" in error_msg or "404" in error_msg: + detailed_error = f"{detailed_error}。{model_info}。可能的原因:1) 模型名称格式不正确(SiliconFlow需要org/model格式);2) base_url配置错误;3) API端点不存在" + elif "403" in error_msg or "account balance" in error_msg.lower() or "insufficient" in error_msg.lower(): + detailed_error = f"{detailed_error}。{model_info}。可能的原因:账户余额不足或API密钥权限不足" + elif "401" in error_msg or "authentication" in error_msg.lower(): + detailed_error = f"{detailed_error}。{model_info}。可能的原因:API密钥无效或已过期" + else: + detailed_error = f"{detailed_error}。{model_info}" + + logger.error(f"LLM调用失败: {detailed_error}") # 如果当前使用的不是默认模型,并且错误包含 Not Found / 404,则尝试回退到默认模型再调用一次 if (not used_default_model) and ("Not Found" in error_msg or "404" in error_msg): @@ -863,7 +879,7 @@ class WorkflowEngine: logger.error(f"使用默认模型重试LLM调用失败: {str(fallback_error)}") # 继续向下抛出原始错误 - raise ValueError(f"LLM调用失败: {error_msg}") + raise ValueError(f"LLM调用失败: {detailed_error}") def _substitute_variables(self, template: str, input_data: Dict[str, Any]) -> str: """变量替换函数"""