From dddb327885e28a17eaefeb53d95189942b0d8149 Mon Sep 17 00:00:00 2001 From: fawney19 Date: Thu, 25 Dec 2025 19:36:29 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E6=B5=8B=E8=AF=95=E9=94=99=E8=AF=AF=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=B9=B6=E4=BF=AE=E5=A4=8D=E7=94=A8=E9=87=8F?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E5=8F=98=E9=87=8F=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 ModelsTab 和 ModelAliasesTab 中重复的错误解析逻辑提取到 errorParser.ts - 添加 parseTestModelError 函数统一处理测试响应错误 - 为 testModel API 添加 TypeScript 类型定义 (TestModelRequest/TestModelResponse) - 修复 endpoint_checker.py 中 usage_data 变量引用错误 --- frontend/src/api/endpoints/providers.ts | 26 ++++++++++- .../components/ModelMappingDialog.vue | 2 +- .../provider-tabs/ModelAliasesTab.vue | 35 +------------- .../components/provider-tabs/ModelsTab.vue | 33 +------------ frontend/src/utils/errorParser.ts | 46 +++++++++++++++++++ src/api/handlers/base/endpoint_checker.py | 2 +- 6 files changed, 76 insertions(+), 68 deletions(-) diff --git a/frontend/src/api/endpoints/providers.ts b/frontend/src/api/endpoints/providers.ts index 8fcd183..960f833 100644 --- a/frontend/src/api/endpoints/providers.ts +++ b/frontend/src/api/endpoints/providers.ts @@ -61,12 +61,34 @@ export async function deleteProvider(providerId: string): Promise<{ message: str /** * 测试模型连接性 */ -export async function testModel(data: { +export interface TestModelRequest { provider_id: string model_name: string api_key_id?: string message?: string -}): Promise { + api_format?: string +} + +export interface TestModelResponse { + success: boolean + error?: string + data?: { + response?: { + status_code?: number + error?: string | { message?: string } + choices?: Array<{ message?: { content?: string } }> + } + content_preview?: string + } + provider?: { + id: string + name: string + display_name: string + } + model?: string +} + +export async function testModel(data: TestModelRequest): Promise { const response = await client.post('/api/admin/provider-query/test-model', data) return response.data } diff --git a/frontend/src/features/providers/components/ModelMappingDialog.vue b/frontend/src/features/providers/components/ModelMappingDialog.vue index ef243b7..61c63ba 100644 --- a/frontend/src/features/providers/components/ModelMappingDialog.vue +++ b/frontend/src/features/providers/components/ModelMappingDialog.vue @@ -518,7 +518,7 @@ function initForm() { upstreamModels.value = [] } } - + // 处理模型选择变更 function handleModelChange(value: string) { formData.value.modelId = value diff --git a/frontend/src/features/providers/components/provider-tabs/ModelAliasesTab.vue b/frontend/src/features/providers/components/provider-tabs/ModelAliasesTab.vue index 7d2aff7..11ce169 100644 --- a/frontend/src/features/providers/components/provider-tabs/ModelAliasesTab.vue +++ b/frontend/src/features/providers/components/provider-tabs/ModelAliasesTab.vue @@ -193,6 +193,7 @@ import { type ProviderModelAlias } from '@/api/endpoints' import { updateModel } from '@/api/endpoints/models' +import { parseTestModelError } from '@/utils/errorParser' const props = defineProps<{ provider: any @@ -368,8 +369,6 @@ async function testMapping(group: any, mapping: any) { apiFormat = group.model.effective_api_format || group.model.api_format } - console.log(`测试映射 ${mapping.name},使用 API Format: ${apiFormat}`) - const result = await testModel({ provider_id: props.provider.id, model_name: mapping.name, // 使用映射名称进行测试 @@ -388,37 +387,7 @@ async function testMapping(group: any, mapping: any) { showSuccess(`流式测试成功,预览: ${result.data.content_preview}`) } } else { - // 根据不同的错误类型显示更详细的信息 - let errorMsg = result.error || '测试失败' - - // 检查HTTP状态码错误 - if (result.data?.response?.status_code) { - const status = result.data.response.status_code - if (status === 403) { - errorMsg = '认证失败: API密钥无效或客户端类型不被允许' - } else if (status === 401) { - errorMsg = '认证失败: API密钥无效或已过期' - } else if (status === 404) { - errorMsg = '模型不存在: 请检查模型名称是否正确' - } else if (status === 429) { - errorMsg = '请求频率过高: 请稍后重试' - } else if (status >= 500) { - errorMsg = `服务器错误: HTTP ${status}` - } else { - errorMsg = `请求失败: HTTP ${status}` - } - } - - // 尝试从错误响应中提取更多信息 - if (result.data?.response?.error) { - if (typeof result.data.response.error === 'string') { - errorMsg = result.data.response.error - } else if (result.data.response.error?.message) { - errorMsg = result.data.response.error.message - } - } - - showError(`映射测试失败: ${errorMsg}`) + showError(`映射测试失败: ${parseTestModelError(result)}`) } } catch (err: any) { const errorMsg = err.response?.data?.detail || err.message || '测试请求失败' diff --git a/frontend/src/features/providers/components/provider-tabs/ModelsTab.vue b/frontend/src/features/providers/components/provider-tabs/ModelsTab.vue index 628a8fa..f5c35ba 100644 --- a/frontend/src/features/providers/components/provider-tabs/ModelsTab.vue +++ b/frontend/src/features/providers/components/provider-tabs/ModelsTab.vue @@ -226,6 +226,7 @@ import Button from '@/components/ui/button.vue' import { useToast } from '@/composables/useToast' import { getProviderModels, testModel, type Model } from '@/api/endpoints' import { updateModel } from '@/api/endpoints/models' +import { parseTestModelError } from '@/utils/errorParser' const props = defineProps<{ provider: any @@ -415,37 +416,7 @@ async function testModelConnection(model: Model) { showSuccess(`流式测试成功,预览: ${result.data.content_preview}`) } } else { - // 根据不同的错误类型显示更详细的信息 - let errorMsg = result.error || '测试失败' - - // 检查HTTP状态码错误 - if (result.data?.response?.status_code) { - const status = result.data.response.status_code - if (status === 403) { - errorMsg = '认证失败: API密钥无效或客户端类型不被允许' - } else if (status === 401) { - errorMsg = '认证失败: API密钥无效或已过期' - } else if (status === 404) { - errorMsg = '模型不存在: 请检查模型名称是否正确' - } else if (status === 429) { - errorMsg = '请求频率过高: 请稍后重试' - } else if (status >= 500) { - errorMsg = `服务器错误: HTTP ${status}` - } else { - errorMsg = `请求失败: HTTP ${status}` - } - } - - // 尝试从错误响应中提取更多信息 - if (result.data?.response?.error) { - if (typeof result.data.response.error === 'string') { - errorMsg = result.data.response.error - } else if (result.data.response.error?.message) { - errorMsg = result.data.response.error.message - } - } - - showError(`模型测试失败: ${errorMsg}`) + showError(`模型测试失败: ${parseTestModelError(result)}`) } } catch (err: any) { const errorMsg = err.response?.data?.detail || err.message || '测试请求失败' diff --git a/frontend/src/utils/errorParser.ts b/frontend/src/utils/errorParser.ts index 9c23188..ad92f41 100644 --- a/frontend/src/utils/errorParser.ts +++ b/frontend/src/utils/errorParser.ts @@ -198,3 +198,49 @@ export function parseApiErrorShort(err: unknown, defaultMessage: string = '操 const lines = fullError.split('\n') return lines[0] || defaultMessage } + +/** + * 解析模型测试响应的错误信息 + * @param result 测试响应结果 + * @returns 格式化的错误信息 + */ +export function parseTestModelError(result: { + error?: string + data?: { + response?: { + status_code?: number + error?: string | { message?: string } + } + } +}): string { + let errorMsg = result.error || '测试失败' + + // 检查HTTP状态码错误 + if (result.data?.response?.status_code) { + const status = result.data.response.status_code + if (status === 403) { + errorMsg = '认证失败: API密钥无效或客户端类型不被允许' + } else if (status === 401) { + errorMsg = '认证失败: API密钥无效或已过期' + } else if (status === 404) { + errorMsg = '模型不存在: 请检查模型名称是否正确' + } else if (status === 429) { + errorMsg = '请求频率过高: 请稍后重试' + } else if (status >= 500) { + errorMsg = `服务器错误: HTTP ${status}` + } else { + errorMsg = `请求失败: HTTP ${status}` + } + } + + // 尝试从错误响应中提取更多信息 + if (result.data?.response?.error) { + if (typeof result.data.response.error === 'string') { + errorMsg = result.data.response.error + } else if (result.data.response.error?.message) { + errorMsg = result.data.response.error.message + } + } + + return errorMsg +} diff --git a/src/api/handlers/base/endpoint_checker.py b/src/api/handlers/base/endpoint_checker.py index ab981da..c1d836e 100644 --- a/src/api/handlers/base/endpoint_checker.py +++ b/src/api/handlers/base/endpoint_checker.py @@ -1243,7 +1243,7 @@ class EndpointCheckOrchestrator: api_format=api_format, ) - logger.info(f"[{request.api_format}] Usage calculated successfully: {usage_data}") + logger.info(f"[{request.api_format}] Usage calculated successfully: {result.usage_data}") except Exception as e: logger.error(f"[{request.api_format}] Failed to calculate usage: {e}") import traceback