|
|
@@ -44,6 +44,8 @@ var geminiSupportedMimeTypes = map[string]bool{
|
|
|
"video/flv": true,
|
|
|
}
|
|
|
|
|
|
+const thoughtSignatureBypassValue = "context_engineering_is_the_way_to_go"
|
|
|
+
|
|
|
// Gemini 允许的思考预算范围
|
|
|
const (
|
|
|
pro25MinBudget = 128
|
|
|
@@ -181,7 +183,7 @@ func ThinkingAdaptor(geminiRequest *dto.GeminiChatRequest, info *relaycommon.Rel
|
|
|
}
|
|
|
|
|
|
// Setting safety to the lowest possible values since Gemini is already powerless enough
|
|
|
-func CovertGemini2OpenAI(c *gin.Context, textRequest dto.GeneralOpenAIRequest, info *relaycommon.RelayInfo) (*dto.GeminiChatRequest, error) {
|
|
|
+func CovertOpenAI2Gemini(c *gin.Context, textRequest dto.GeneralOpenAIRequest, info *relaycommon.RelayInfo) (*dto.GeminiChatRequest, error) {
|
|
|
|
|
|
geminiRequest := dto.GeminiChatRequest{
|
|
|
Contents: make([]dto.GeminiChatContent, 0, len(textRequest.Messages)),
|
|
|
@@ -193,6 +195,10 @@ func CovertGemini2OpenAI(c *gin.Context, textRequest dto.GeneralOpenAIRequest, i
|
|
|
},
|
|
|
}
|
|
|
|
|
|
+ attachThoughtSignature := (info.ChannelType == constant.ChannelTypeGemini ||
|
|
|
+ info.ChannelType == constant.ChannelTypeVertexAi) &&
|
|
|
+ model_setting.GetGeminiSettings().FunctionCallThoughtSignatureEnabled
|
|
|
+
|
|
|
if model_setting.IsGeminiModelSupportImagine(info.UpstreamModelName) {
|
|
|
geminiRequest.GenerationConfig.ResponseModalities = []string{
|
|
|
"TEXT",
|
|
|
@@ -371,6 +377,8 @@ func CovertGemini2OpenAI(c *gin.Context, textRequest dto.GeneralOpenAIRequest, i
|
|
|
content := dto.GeminiChatContent{
|
|
|
Role: message.Role,
|
|
|
}
|
|
|
+ shouldAttachThoughtSignature := attachThoughtSignature && (message.Role == "assistant" || message.Role == "model")
|
|
|
+ signatureAttached := false
|
|
|
// isToolCall := false
|
|
|
if message.ToolCalls != nil {
|
|
|
// message.Role = "model"
|
|
|
@@ -388,6 +396,10 @@ func CovertGemini2OpenAI(c *gin.Context, textRequest dto.GeneralOpenAIRequest, i
|
|
|
Arguments: args,
|
|
|
},
|
|
|
}
|
|
|
+ if shouldAttachThoughtSignature && !signatureAttached && hasFunctionCallContent(toolCall.FunctionCall) && len(toolCall.ThoughtSignature) == 0 {
|
|
|
+ toolCall.ThoughtSignature = json.RawMessage(strconv.Quote(thoughtSignatureBypassValue))
|
|
|
+ signatureAttached = true
|
|
|
+ }
|
|
|
parts = append(parts, toolCall)
|
|
|
tool_call_ids[call.ID] = call.Function.Name
|
|
|
}
|
|
|
@@ -496,6 +508,28 @@ func CovertGemini2OpenAI(c *gin.Context, textRequest dto.GeneralOpenAIRequest, i
|
|
|
return &geminiRequest, nil
|
|
|
}
|
|
|
|
|
|
+func hasFunctionCallContent(call *dto.FunctionCall) bool {
|
|
|
+ if call == nil {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if strings.TrimSpace(call.FunctionName) != "" {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ switch v := call.Arguments.(type) {
|
|
|
+ case nil:
|
|
|
+ return false
|
|
|
+ case string:
|
|
|
+ return strings.TrimSpace(v) != ""
|
|
|
+ case map[string]interface{}:
|
|
|
+ return len(v) > 0
|
|
|
+ case []interface{}:
|
|
|
+ return len(v) > 0
|
|
|
+ default:
|
|
|
+ return true
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// Helper function to get a list of supported MIME types for error messages
|
|
|
func getSupportedMimeTypesList() []string {
|
|
|
keys := make([]string, 0, len(geminiSupportedMimeTypes))
|