fix(llm): sanitize model endpoint errors (#6021)

This commit is contained in:
InfinityPacer
2026-06-29 11:19:38 +08:00
committed by GitHub
parent 9eb71c744b
commit 0cb0bac0e1
2 changed files with 64 additions and 7 deletions

View File

@@ -48,7 +48,7 @@ class LlmProviderAuthStartRequest(BaseModel):
method: str
def _sanitize_llm_test_error(message: str, api_key: Optional[str] = None) -> str:
def _sanitize_llm_error(message: str, api_key: Optional[str] = None) -> str:
"""
清理错误信息中的敏感字段,避免回显密钥。
"""
@@ -70,11 +70,14 @@ def _sanitize_llm_test_error(message: str, api_key: Optional[str] = None) -> str
)
normalized_message = sanitized.lower().replace("_", "").replace(" ", "")
if "str" in normalized_message and "modeldump" in normalized_message:
if "str" in normalized_message and (
"modeldump" in normalized_message
or "setprivateattributes" in normalized_message
):
return (
"服务返回内容不是兼容的模型响应,"
"请检查基础地址是否填写为 API Base URL不要填写网页地址或完整的 "
"chat/completions 路径"
"服务返回内容不是兼容的模型响应,请检查基础地址是否填写为 "
"API Base URL如果服务要求 /v1 等版本路径,请包含在基础地址中,"
"不要填写网页地址或完整的 chat/completions 路径"
)
return sanitized
@@ -113,7 +116,10 @@ async def get_llm_models(
},
)
except Exception as err:
return schemas.Response(success=False, message=str(err))
return schemas.Response(
success=False,
message=_sanitize_llm_error(str(err), api_key),
)
@router.get("/providers", summary="获取LLM提供商目录", response_model=schemas.Response)
@@ -312,5 +318,5 @@ async def llm_test(
except Exception as err:
return schemas.Response(
success=False,
message=_sanitize_llm_test_error(str(err), payload.api_key),
message=_sanitize_llm_error(str(err), payload.api_key),
)

View File

@@ -24,3 +24,54 @@ def test_llm_test_maps_internal_model_dump_error_to_base_url_hint():
assert "基础地址" in resp.message
assert "API Base URL" in resp.message
assert "model_dump" not in resp.message
def test_llm_test_maps_internal_private_attribute_error_to_base_url_hint():
"""LLM 测试遇到 SDK 内部属性错误时应提示检查基础地址。"""
with patch.object(llm_endpoint.settings, "AI_AGENT_ENABLE", True), patch.object(
llm_endpoint.settings, "LLM_PROVIDER", "openai"
), patch.object(llm_endpoint.settings, "LLM_MODEL", "gpt-4o-mini"), patch.object(
llm_endpoint.settings, "LLM_API_KEY", "sk-test"
), patch.object(
llm_endpoint.LLMHelper,
"test_current_settings",
AsyncMock(
side_effect=AttributeError(
"'str' object has no attribute '_set_private_attributes'"
)
),
create=True,
):
resp = asyncio.run(llm_endpoint.llm_test(_="token"))
assert not resp.success
assert "基础地址" in resp.message
assert "API Base URL" in resp.message
assert "_set_private_attributes" not in resp.message
def test_llm_models_maps_internal_private_attribute_error_to_base_url_hint():
"""LLM 模型列表遇到 SDK 内部属性错误时应提示检查基础地址。"""
with patch.object(
llm_endpoint.LLMHelper,
"get_models",
AsyncMock(
side_effect=AttributeError(
"'str' object has no attribute '_set_private_attributes'"
)
),
create=True,
):
resp = asyncio.run(
llm_endpoint.get_llm_models(
provider="openai",
api_key="sk-test",
base_url="https://example.com",
_="token",
)
)
assert not resp.success
assert "基础地址" in resp.message
assert "API Base URL" in resp.message
assert "_set_private_attributes" not in resp.message