fix(llm): 增强API错误处理以包含原始响应信息
改进所有LLM适配器的错误处理逻辑,现在会捕获并传递API原始响应信息 添加对账户余额不足等特定错误类型的识别和处理 统一各适配器的错误响应格式,包含错误代码和消息
This commit is contained in:
parent
333be11edf
commit
9fe15f0d0b
|
|
@ -75,7 +75,8 @@ class BaiduAdapter(BaseLLMAdapter):
|
||||||
await self.validate_config()
|
await self.validate_config()
|
||||||
return await self.retry(lambda: self._send_request(request))
|
return await self.retry(lambda: self._send_request(request))
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
self.handle_error(error, "百度文心一言 API调用失败")
|
api_response = getattr(error, 'api_response', None)
|
||||||
|
self.handle_error(error, "百度文心一言 API调用失败", api_response=api_response)
|
||||||
|
|
||||||
async def _send_request(self, request: LLMRequest) -> LLMResponse:
|
async def _send_request(self, request: LLMRequest) -> LLMResponse:
|
||||||
"""发送请求"""
|
"""发送请求"""
|
||||||
|
|
@ -107,12 +108,19 @@ class BaiduAdapter(BaseLLMAdapter):
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
error_data = response.json() if response.text else {}
|
error_data = response.json() if response.text else {}
|
||||||
error_msg = error_data.get("error_msg", f"HTTP {response.status_code}")
|
error_msg = error_data.get("error_msg", f"HTTP {response.status_code}")
|
||||||
raise Exception(f"{error_msg}")
|
error_code = error_data.get("error_code", "")
|
||||||
|
api_response = f"[{error_code}] {error_msg}" if error_code else error_msg
|
||||||
|
err = LLMError(error_msg, self.config.provider, response.status_code, api_response=api_response)
|
||||||
|
raise err
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
|
|
||||||
if "error_code" in data:
|
if "error_code" in data:
|
||||||
raise Exception(f"百度API错误: {data.get('error_msg', '未知错误')}")
|
error_msg = data.get('error_msg', '未知错误')
|
||||||
|
error_code = data.get('error_code', '')
|
||||||
|
api_response = f"[{error_code}] {error_msg}"
|
||||||
|
err = LLMError(f"百度API错误: {error_msg}", self.config.provider, api_response=api_response)
|
||||||
|
raise err
|
||||||
|
|
||||||
usage = None
|
usage = None
|
||||||
if "usage" in data:
|
if "usage" in data:
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ class DoubaoAdapter(BaseLLMAdapter):
|
||||||
await self.validate_config()
|
await self.validate_config()
|
||||||
return await self.retry(lambda: self._send_request(request))
|
return await self.retry(lambda: self._send_request(request))
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
self.handle_error(error, "豆包 API调用失败")
|
api_response = getattr(error, 'api_response', None)
|
||||||
|
self.handle_error(error, "豆包 API调用失败", api_response=api_response)
|
||||||
|
|
||||||
async def _send_request(self, request: LLMRequest) -> LLMResponse:
|
async def _send_request(self, request: LLMRequest) -> LLMResponse:
|
||||||
"""发送请求"""
|
"""发送请求"""
|
||||||
|
|
@ -50,8 +51,12 @@ class DoubaoAdapter(BaseLLMAdapter):
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
error_data = response.json() if response.text else {}
|
error_data = response.json() if response.text else {}
|
||||||
error_msg = error_data.get("error", {}).get("message", f"HTTP {response.status_code}")
|
error_obj = error_data.get("error", {})
|
||||||
raise Exception(f"{error_msg}")
|
error_msg = error_obj.get("message", f"HTTP {response.status_code}")
|
||||||
|
error_code = error_obj.get("code", "")
|
||||||
|
api_response = f"[{error_code}] {error_msg}" if error_code else error_msg
|
||||||
|
err = LLMError(error_msg, self.config.provider, response.status_code, api_response=api_response)
|
||||||
|
raise err
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
choice = data.get("choices", [{}])[0]
|
choice = data.get("choices", [{}])[0]
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ class MinimaxAdapter(BaseLLMAdapter):
|
||||||
await self.validate_config()
|
await self.validate_config()
|
||||||
return await self.retry(lambda: self._send_request(request))
|
return await self.retry(lambda: self._send_request(request))
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
self.handle_error(error, "MiniMax API调用失败")
|
api_response = getattr(error, 'api_response', None)
|
||||||
|
self.handle_error(error, "MiniMax API调用失败", api_response=api_response)
|
||||||
|
|
||||||
async def _send_request(self, request: LLMRequest) -> LLMResponse:
|
async def _send_request(self, request: LLMRequest) -> LLMResponse:
|
||||||
"""发送请求"""
|
"""发送请求"""
|
||||||
|
|
@ -47,15 +48,23 @@ class MinimaxAdapter(BaseLLMAdapter):
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
error_data = response.json() if response.text else {}
|
error_data = response.json() if response.text else {}
|
||||||
error_msg = error_data.get("base_resp", {}).get("status_msg", f"HTTP {response.status_code}")
|
base_resp = error_data.get("base_resp", {})
|
||||||
raise Exception(f"{error_msg}")
|
error_msg = base_resp.get("status_msg", f"HTTP {response.status_code}")
|
||||||
|
error_code = base_resp.get("status_code", "")
|
||||||
|
api_response = f"[{error_code}] {error_msg}" if error_code else error_msg
|
||||||
|
err = LLMError(error_msg, self.config.provider, response.status_code, api_response=api_response)
|
||||||
|
raise err
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
|
|
||||||
# MiniMax 特殊的错误处理
|
# MiniMax 特殊的错误处理
|
||||||
if data.get("base_resp", {}).get("status_code") != 0:
|
base_resp = data.get("base_resp", {})
|
||||||
error_msg = data.get("base_resp", {}).get("status_msg", "未知错误")
|
if base_resp.get("status_code") != 0:
|
||||||
raise Exception(f"MiniMax API错误: {error_msg}")
|
error_msg = base_resp.get("status_msg", "未知错误")
|
||||||
|
error_code = base_resp.get("status_code", "")
|
||||||
|
api_response = f"[{error_code}] {error_msg}"
|
||||||
|
err = LLMError(f"MiniMax API错误: {error_msg}", self.config.provider, api_response=api_response)
|
||||||
|
raise err
|
||||||
|
|
||||||
choice = data.get("choices", [{}])[0]
|
choice = data.get("choices", [{}])[0]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,17 +57,30 @@ class BaseLLMAdapter(ABC):
|
||||||
self.config.provider
|
self.config.provider
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle_error(self, error: Any, context: str = "") -> None:
|
def handle_error(self, error: Any, context: str = "", api_response: str = None) -> None:
|
||||||
"""处理API错误"""
|
"""处理API错误
|
||||||
|
|
||||||
|
Args:
|
||||||
|
error: 原始异常
|
||||||
|
context: 错误上下文描述
|
||||||
|
api_response: API 服务器返回的原始响应信息
|
||||||
|
"""
|
||||||
message = str(error)
|
message = str(error)
|
||||||
status_code = getattr(error, 'status_code', None)
|
status_code = getattr(error, 'status_code', None)
|
||||||
|
|
||||||
|
# 如果错误本身已经有 api_response,优先使用
|
||||||
|
if api_response is None:
|
||||||
|
api_response = getattr(error, 'api_response', None)
|
||||||
|
|
||||||
# 针对不同错误类型提供更详细的信息
|
# 针对不同错误类型提供更详细的信息
|
||||||
if "超时" in message or "timeout" in message.lower():
|
if "超时" in message or "timeout" in message.lower():
|
||||||
message = f"请求超时 ({self.config.timeout}s)。建议:\n" \
|
message = f"请求超时 ({self.config.timeout}s)。建议:\n" \
|
||||||
f"1. 检查网络连接是否正常\n" \
|
f"1. 检查网络连接是否正常\n" \
|
||||||
f"2. 尝试增加超时时间\n" \
|
f"2. 尝试增加超时时间\n" \
|
||||||
f"3. 验证API端点是否正确"
|
f"3. 验证API端点是否正确"
|
||||||
|
elif any(keyword in message for keyword in ["余额不足", "资源包", "充值", "quota", "insufficient", "balance"]):
|
||||||
|
message = f"账户余额不足或配额已用尽,请充值后重试"
|
||||||
|
status_code = status_code or 402
|
||||||
elif status_code == 401 or status_code == 403:
|
elif status_code == 401 or status_code == 403:
|
||||||
message = f"API认证失败。建议:\n" \
|
message = f"API认证失败。建议:\n" \
|
||||||
f"1. 检查API Key是否正确配置\n" \
|
f"1. 检查API Key是否正确配置\n" \
|
||||||
|
|
@ -90,7 +103,8 @@ class BaseLLMAdapter(ABC):
|
||||||
full_message,
|
full_message,
|
||||||
self.config.provider,
|
self.config.provider,
|
||||||
status_code,
|
status_code,
|
||||||
error
|
error,
|
||||||
|
api_response=api_response
|
||||||
)
|
)
|
||||||
|
|
||||||
async def retry(self, fn, max_attempts: int = 3, delay: float = 1.0) -> Any:
|
async def retry(self, fn, max_attempts: int = 3, delay: float = 1.0) -> Any:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue