From e3d0d9be730cb5e2705d2692e69039618dd18e77 Mon Sep 17 00:00:00 2001 From: nanako <469449812@qq.com> Date: Sat, 8 Nov 2025 23:16:38 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=90=8E=E7=AB=AF=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=A4=84=E7=90=86=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AE=B0=E5=BD=95=EF=BC=8C=E7=BB=9F=E4=B8=80=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=91=BD=E5=90=8D=E4=B8=BA=E5=B0=8F=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/api/handlers.go | 34 +++++++++++++++++- backend/gateway.db | Bin 98304 -> 356352 bytes backend/internal/models/schema.go | 7 ++-- backend/internal/router/selector.go | 15 ++++---- backend/main.go | 13 +++++-- .../providers/components/ProviderForm.jsx | 16 ++++----- .../providers/components/ProviderList.jsx | 4 +-- .../components/VirtualModelForm.jsx | 12 ++++--- 8 files changed, 73 insertions(+), 28 deletions(-) diff --git a/backend/api/handlers.go b/backend/api/handlers.go index e29a844..9f59c10 100644 --- a/backend/api/handlers.go +++ b/backend/api/handlers.go @@ -50,6 +50,14 @@ type ChatCompletionMessage struct { Content string `json:"content"` } +// BackendChatCompletionRequest 是实际发送到后端模型的请求结构 +// 它只包含通用字段,以避免发送不被支持的参数 +type BackendChatCompletionRequest struct { + Model string `json:"model"` + Messages []ChatCompletionMessage `json:"messages"` + Stream bool `json:"stream,omitempty"` +} + // ResponsesRequest /v1/responses 端点请求结构 type ResponsesRequest struct { Model string `json:"model"` @@ -119,8 +127,13 @@ func (h *APIHandler) ChatCompletions(c *gin.Context) { var req ChatCompletionRequest + // 增加日志记录请求体 + bodyBytes, _ := io.ReadAll(c.Request.Body) + c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) // 把body重新写回去 + // 解析请求体 if err := c.ShouldBindJSON(&req); err != nil { + log.Printf("Failed to bind JSON: %v", err) // 增加错误日志 c.JSON(http.StatusBadRequest, gin.H{ "error": gin.H{ "message": "Invalid request format", @@ -146,7 +159,22 @@ func (h *APIHandler) ChatCompletions(c *gin.Context) { } // 准备转发请求 - requestBody, err := json.Marshal(req) + // 用body创建一个json对象 + var jsonBody map[string]interface{} + if err := json.Unmarshal(bodyBytes, &jsonBody); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": gin.H{ + "message": "Failed to process request", + "type": "internal_error", + }, + }) + return + } + // 然后修改jsonBody的model字段 + jsonBody["model"] = backendModel.Name + // 最后重新marshal回requestBody + requestBody, err := json.Marshal(jsonBody) + if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": gin.H{ @@ -212,6 +240,10 @@ func (h *APIHandler) ChatCompletions(c *gin.Context) { return } + // 增加日志记录后端响应 + log.Printf("Backend Response Status: %s", resp.Status) + log.Printf("Backend Response Body: %s", string(responseBody)) + // 计算响应token数 responseTokenCount := 0 var responseData map[string]interface{} diff --git a/backend/gateway.db b/backend/gateway.db index b07dd9214478c119f9f88bb3512d11b17bfb9f87..e3abd2fd9bf0e0346dbd868cedef43dfe41f29ad 100644 GIT binary patch literal 356352 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 requestTokenCount { + if backendModel.MaxContextLength == 0 || backendModel.MaxContextLength >= requestTokenCount { suitableModels = append(suitableModels, backendModel) } } @@ -67,11 +67,14 @@ func SelectBackendModel(db *gorm.DB, virtualModelName string, requestTokenCount estimatedCost = model.FixedPrice } - // 如果该模型设置了成本阈值,检查成本是否超过阈值 - if model.CostThreshold > 0 { - // 如果成本超过该模型的阈值,跳过该模型 - if estimatedCost > model.CostThreshold { - continue + // 如果CostThreshold不为0,则表示设置了成本阈值 + if model.CostThreshold != 0 { + // 如果该模型设置了成本阈值,检查成本是否超过阈值 + if model.CostThreshold > 0 { + // 如果成本超过该模型的阈值,跳过该模型 + if estimatedCost > model.CostThreshold { + continue + } } } diff --git a/backend/main.go b/backend/main.go index 1c7d073..696ab94 100644 --- a/backend/main.go +++ b/backend/main.go @@ -39,13 +39,20 @@ func main() { DB: database, } + // 创建根组 + root_ := router.Group("/") + root_.Use(middleware.AuthMiddleware(database)) + { + root_.GET("/models", handler.ListModels) + } + // 创建受保护的路由组 - protected := router.Group("/") + protected := router.Group("/v1") protected.Use(middleware.AuthMiddleware(database)) { protected.GET("/models", handler.ListModels) - protected.POST("/v1/chat/completions", handler.ChatCompletions) - protected.POST("/v1/responses", handler.ResponsesCompletions) + protected.POST("/chat/completions", handler.ChatCompletions) + protected.POST("/responses", handler.ResponsesCompletions) } // 创建API管理路由组 diff --git a/frontend/src/features/providers/components/ProviderForm.jsx b/frontend/src/features/providers/components/ProviderForm.jsx index 7d17cb7..b0813d3 100644 --- a/frontend/src/features/providers/components/ProviderForm.jsx +++ b/frontend/src/features/providers/components/ProviderForm.jsx @@ -8,20 +8,20 @@ const ProviderForm = ({ provider, onSave, onCancel }) => { useEffect(() => { if (provider) { - setName(provider.Name || ''); - setBaseURL(provider.BaseURL || ''); - setAPIKey(provider.APIKey || ''); - setAPIVersion(provider.APIVersion || ''); + setName(provider.name || ''); + setBaseURL(provider.base_url || ''); + setAPIKey(provider.api_key || ''); + setAPIVersion(provider.api_version || ''); } }, [provider]); const handleSubmit = (e) => { e.preventDefault(); onSave({ - Name: name, - BaseURL: baseURL, - APIKey: apiKey, - APIVersion: apiVersion, + name: name, + base_url: baseURL, + api_key: apiKey, + api_version: apiVersion, }); }; diff --git a/frontend/src/features/providers/components/ProviderList.jsx b/frontend/src/features/providers/components/ProviderList.jsx index e5e0acc..f0a9768 100644 --- a/frontend/src/features/providers/components/ProviderList.jsx +++ b/frontend/src/features/providers/components/ProviderList.jsx @@ -138,12 +138,12 @@ const ProviderList = () => {
- {provider.Name || 'N/A'} + {provider.name || 'N/A'}
- {provider.BaseURL || 'N/A'} + {provider.base_url || 'N/A'} diff --git a/frontend/src/features/virtual-models/components/VirtualModelForm.jsx b/frontend/src/features/virtual-models/components/VirtualModelForm.jsx index 7231ff1..1a9152a 100644 --- a/frontend/src/features/virtual-models/components/VirtualModelForm.jsx +++ b/frontend/src/features/virtual-models/components/VirtualModelForm.jsx @@ -79,11 +79,13 @@ const VirtualModelForm = ({ model, onSave, onCancel }) => { className="mt-1 block w-full rounded-md border-gray-300 shadow-sm" > - {providers.map((p) => ( - - ))} + {providers.map((p) => { + return ( + + ); + })}