Browse Source

feat: gemini reasoning content (#179)

zijiren 7 months ago
parent
commit
33efcf1582
2 changed files with 25 additions and 3 deletions
  1. 22 2
      core/relay/adaptor/gemini/main.go
  2. 3 1
      core/relay/adaptor/gemini/model.go

+ 22 - 2
core/relay/adaptor/gemini/main.go

@@ -95,6 +95,14 @@ func buildGenerationConfig(meta *meta.Meta, req *http.Request, textRequest *rela
 		config.ThinkingConfig = thinkingConfigOnly.ThinkingConfig
 		config.ThinkingConfig = thinkingConfigOnly.ThinkingConfig
 	}
 	}
 
 
+	// https://ai.google.dev/gemini-api/docs/thinking
+	if strings.Contains(meta.ActualModel, "2.5") {
+		if config.ThinkingConfig == nil {
+			config.ThinkingConfig = &ThinkingConfig{}
+		}
+		config.ThinkingConfig.IncludeThoughts = true
+	}
+
 	return &config, nil
 	return &config, nil
 }
 }
 
 
@@ -436,6 +444,7 @@ func responseChat2OpenAI(meta *meta.Meta, response *ChatResponse) *relaymodel.Te
 		}
 		}
 		if len(candidate.Content.Parts) > 0 {
 		if len(candidate.Content.Parts) > 0 {
 			var contents []relaymodel.MessageContent
 			var contents []relaymodel.MessageContent
+			var reasoningContent strings.Builder
 			var builder strings.Builder
 			var builder strings.Builder
 			hasImage := false
 			hasImage := false
 			for _, part := range candidate.Content.Parts {
 			for _, part := range candidate.Content.Parts {
@@ -461,7 +470,11 @@ func responseChat2OpenAI(meta *meta.Meta, response *ChatResponse) *relaymodel.Te
 							Text: part.Text,
 							Text: part.Text,
 						})
 						})
 					} else {
 					} else {
-						builder.WriteString(part.Text)
+						if part.Thought {
+							reasoningContent.WriteString(part.Text)
+						} else {
+							builder.WriteString(part.Text)
+						}
 					}
 					}
 				}
 				}
 				if part.InlineData != nil {
 				if part.InlineData != nil {
@@ -477,6 +490,7 @@ func responseChat2OpenAI(meta *meta.Meta, response *ChatResponse) *relaymodel.Te
 				choice.Message.Content = contents
 				choice.Message.Content = contents
 			} else {
 			} else {
 				choice.Message.Content = builder.String()
 				choice.Message.Content = builder.String()
+				choice.Message.ReasoningContent = reasoningContent.String()
 			}
 			}
 		}
 		}
 		fullTextResponse.Choices = append(fullTextResponse.Choices, &choice)
 		fullTextResponse.Choices = append(fullTextResponse.Choices, &choice)
@@ -506,6 +520,7 @@ func streamResponseChat2OpenAI(meta *meta.Meta, geminiResponse *ChatResponse) *r
 		}
 		}
 		if len(candidate.Content.Parts) > 0 {
 		if len(candidate.Content.Parts) > 0 {
 			var contents []relaymodel.MessageContent
 			var contents []relaymodel.MessageContent
+			var reasoningContent strings.Builder
 			var builder strings.Builder
 			var builder strings.Builder
 			hasImage := false
 			hasImage := false
 			for _, part := range candidate.Content.Parts {
 			for _, part := range candidate.Content.Parts {
@@ -531,7 +546,11 @@ func streamResponseChat2OpenAI(meta *meta.Meta, geminiResponse *ChatResponse) *r
 							Text: part.Text,
 							Text: part.Text,
 						})
 						})
 					} else {
 					} else {
-						builder.WriteString(part.Text)
+						if part.Thought {
+							reasoningContent.WriteString(part.Text)
+						} else {
+							builder.WriteString(part.Text)
+						}
 					}
 					}
 				}
 				}
 				if part.InlineData != nil {
 				if part.InlineData != nil {
@@ -547,6 +566,7 @@ func streamResponseChat2OpenAI(meta *meta.Meta, geminiResponse *ChatResponse) *r
 				choice.Delta.Content = contents
 				choice.Delta.Content = contents
 			} else {
 			} else {
 				choice.Delta.Content = builder.String()
 				choice.Delta.Content = builder.String()
+				choice.Delta.ReasoningContent = reasoningContent.String()
 			}
 			}
 		}
 		}
 		response.Choices = append(response.Choices, &choice)
 		response.Choices = append(response.Choices, &choice)

+ 3 - 1
core/relay/adaptor/gemini/model.go

@@ -10,7 +10,8 @@ type ChatRequest struct {
 }
 }
 
 
 type ThinkingConfig struct {
 type ThinkingConfig struct {
-	ThinkingBudget int `json:"thinking_budget"`
+	ThinkingBudget  *int `json:"thinking_budget,omitempty"`
+	IncludeThoughts bool `json:"includeThoughts,omitempty"`
 }
 }
 
 
 type EmbeddingRequest struct {
 type EmbeddingRequest struct {
@@ -63,6 +64,7 @@ type Part struct {
 	FunctionCall     *FunctionCall     `json:"functionCall,omitempty"`
 	FunctionCall     *FunctionCall     `json:"functionCall,omitempty"`
 	FunctionResponse *FunctionResponse `json:"functionResponse,omitempty"`
 	FunctionResponse *FunctionResponse `json:"functionResponse,omitempty"`
 	Text             string            `json:"text,omitempty"`
 	Text             string            `json:"text,omitempty"`
+	Thought          bool              `json:"thought,omitempty"`
 }
 }
 
 
 type ChatContent struct {
 type ChatContent struct {