فهرست منبع

Fix: Correctly relay FunctionResponse content for Gemini API

RedwindA 9 ماه پیش
والد
کامیت
f13e4bf486
2فایلهای تغییر یافته به همراه36 افزوده شده و 31 حذف شده
  1. 6 6
      relay/channel/gemini/dto.go
  2. 30 25
      relay/channel/gemini/relay-gemini.go

+ 6 - 6
relay/channel/gemini/dto.go

@@ -27,14 +27,14 @@ type FunctionCall struct {
 	Arguments    any    `json:"args"`
 	Arguments    any    `json:"args"`
 }
 }
 
 
-type GeminiFunctionResponseContent struct {
-	Name    string `json:"name"`
-	Content any    `json:"content"`
-}
+// type GeminiFunctionResponseContent struct {
+// 	Name    string `json:"name"`
+// 	Content any    `json:"content"`
+// }
 
 
 type FunctionResponse struct {
 type FunctionResponse struct {
-	Name     string                        `json:"name"`
-	Response GeminiFunctionResponseContent `json:"response"`
+	Name     string                 `json:"name"`
+	Response map[string]interface{} `json:"response"`
 }
 }
 
 
 type GeminiPartExecutableCode struct {
 type GeminiPartExecutableCode struct {

+ 30 - 25
relay/channel/gemini/relay-gemini.go

@@ -57,22 +57,22 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon
 	}
 	}
 
 
 	if model_setting.GetGeminiSettings().ThinkingAdapterEnabled {
 	if model_setting.GetGeminiSettings().ThinkingAdapterEnabled {
-	        if strings.HasSuffix(info.OriginModelName, "-thinking") {
-	            // 如果模型名以 gemini-2.5-pro 开头,不设置 ThinkingBudget
-	            if strings.HasPrefix(info.OriginModelName, "gemini-2.5-pro") {
-	                geminiRequest.GenerationConfig.ThinkingConfig = &GeminiThinkingConfig{
-	                    IncludeThoughts: true,
-	                }
-	            } else {
-	                budgetTokens := model_setting.GetGeminiSettings().ThinkingAdapterBudgetTokensPercentage * float64(geminiRequest.GenerationConfig.MaxOutputTokens)
-	                if budgetTokens == 0 || budgetTokens > 24576 {
-	                    budgetTokens = 24576
-	                }
-	                geminiRequest.GenerationConfig.ThinkingConfig = &GeminiThinkingConfig{
-	                    ThinkingBudget:  common.GetPointer(int(budgetTokens)),
-	                    IncludeThoughts: true,
-	                }
-	            }
+		if strings.HasSuffix(info.OriginModelName, "-thinking") {
+			// 如果模型名以 gemini-2.5-pro 开头,不设置 ThinkingBudget
+			if strings.HasPrefix(info.OriginModelName, "gemini-2.5-pro") {
+				geminiRequest.GenerationConfig.ThinkingConfig = &GeminiThinkingConfig{
+					IncludeThoughts: true,
+				}
+			} else {
+				budgetTokens := model_setting.GetGeminiSettings().ThinkingAdapterBudgetTokensPercentage * float64(geminiRequest.GenerationConfig.MaxOutputTokens)
+				if budgetTokens == 0 || budgetTokens > 24576 {
+					budgetTokens = 24576
+				}
+				geminiRequest.GenerationConfig.ThinkingConfig = &GeminiThinkingConfig{
+					ThinkingBudget:  common.GetPointer(int(budgetTokens)),
+					IncludeThoughts: true,
+				}
+			}
 		} else if strings.HasSuffix(info.OriginModelName, "-nothinking") {
 		} else if strings.HasSuffix(info.OriginModelName, "-nothinking") {
 			geminiRequest.GenerationConfig.ThinkingConfig = &GeminiThinkingConfig{
 			geminiRequest.GenerationConfig.ThinkingConfig = &GeminiThinkingConfig{
 				ThinkingBudget: common.GetPointer(0),
 				ThinkingBudget: common.GetPointer(0),
@@ -173,17 +173,22 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon
 			} else if val, exists := tool_call_ids[message.ToolCallId]; exists {
 			} else if val, exists := tool_call_ids[message.ToolCallId]; exists {
 				name = val
 				name = val
 			}
 			}
-			content := common.StrToMap(message.StringContent())
+			contentMap := common.StrToMap(message.StringContent())
 			functionResp := &FunctionResponse{
 			functionResp := &FunctionResponse{
-				Name: name,
-				Response: GeminiFunctionResponseContent{
-					Name:    name,
-					Content: content,
-				},
-			}
-			if content == nil {
-				functionResp.Response.Content = message.StringContent()
+				Name:     name,
+				Response: contentMap,
 			}
 			}
+			// If StrToMap returns nil because message.StringContent() is not a valid JSON object string,
+			// and Gemini strictly requires an object (e.g., {}), this might need adjustment.
+			// For example:
+			// if contentMap == nil && message.StringContent() != "" {
+			//    // Option 1: Send an empty object if that's preferred over null
+			//    // functionResp.Response = make(map[string]interface{})
+			//    // Option 2: Wrap the plain string if that's ever the case and needs to be an object
+			//    // functionResp.Response = map[string]interface{}{"text_content": message.StringContent()}
+			// }
+			// For now, directly assigning contentMap is the most straightforward fix for the reported issue.
+
 			*parts = append(*parts, GeminiPart{
 			*parts = append(*parts, GeminiPart{
 				FunctionResponse: functionResp,
 				FunctionResponse: functionResp,
 			})
 			})