mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
**fix(translator): normalize function calls and outputs for consistent input processing**
- Implemented logic to pair consecutive function calls and their outputs, ensuring proper sequencing for processing. - Adjusted `gemini_openai-responses_request.go` to normalize message structures and maintain expected flow.
This commit is contained in:
@@ -33,7 +33,83 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
|
|
||||||
// Convert input messages to Gemini contents format
|
// Convert input messages to Gemini contents format
|
||||||
if input := root.Get("input"); input.Exists() && input.IsArray() {
|
if input := root.Get("input"); input.Exists() && input.IsArray() {
|
||||||
input.ForEach(func(_, item gjson.Result) bool {
|
items := input.Array()
|
||||||
|
|
||||||
|
// Normalize consecutive function calls and outputs so each call is immediately followed by its response
|
||||||
|
normalized := make([]gjson.Result, 0, len(items))
|
||||||
|
for i := 0; i < len(items); {
|
||||||
|
item := items[i]
|
||||||
|
itemType := item.Get("type").String()
|
||||||
|
itemRole := item.Get("role").String()
|
||||||
|
if itemType == "" && itemRole != "" {
|
||||||
|
itemType = "message"
|
||||||
|
}
|
||||||
|
|
||||||
|
if itemType == "function_call" {
|
||||||
|
var calls []gjson.Result
|
||||||
|
var outputs []gjson.Result
|
||||||
|
|
||||||
|
for i < len(items) {
|
||||||
|
next := items[i]
|
||||||
|
nextType := next.Get("type").String()
|
||||||
|
nextRole := next.Get("role").String()
|
||||||
|
if nextType == "" && nextRole != "" {
|
||||||
|
nextType = "message"
|
||||||
|
}
|
||||||
|
if nextType != "function_call" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
calls = append(calls, next)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
for i < len(items) {
|
||||||
|
next := items[i]
|
||||||
|
nextType := next.Get("type").String()
|
||||||
|
nextRole := next.Get("role").String()
|
||||||
|
if nextType == "" && nextRole != "" {
|
||||||
|
nextType = "message"
|
||||||
|
}
|
||||||
|
if nextType != "function_call_output" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
outputs = append(outputs, next)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(calls) > 0 {
|
||||||
|
outputMap := make(map[string]gjson.Result, len(outputs))
|
||||||
|
for _, out := range outputs {
|
||||||
|
outputMap[out.Get("call_id").String()] = out
|
||||||
|
}
|
||||||
|
for _, call := range calls {
|
||||||
|
normalized = append(normalized, call)
|
||||||
|
callID := call.Get("call_id").String()
|
||||||
|
if resp, ok := outputMap[callID]; ok {
|
||||||
|
normalized = append(normalized, resp)
|
||||||
|
delete(outputMap, callID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, out := range outputs {
|
||||||
|
if _, ok := outputMap[out.Get("call_id").String()]; ok {
|
||||||
|
normalized = append(normalized, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if itemType == "function_call_output" {
|
||||||
|
normalized = append(normalized, item)
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized = append(normalized, item)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range normalized {
|
||||||
itemType := item.Get("type").String()
|
itemType := item.Get("type").String()
|
||||||
itemRole := item.Get("role").String()
|
itemRole := item.Get("role").String()
|
||||||
if itemType == "" && itemRole != "" {
|
if itemType == "" && itemRole != "" {
|
||||||
@@ -59,7 +135,7 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
out, _ = sjson.SetRaw(out, "system_instruction", systemInstr)
|
out, _ = sjson.SetRaw(out, "system_instruction", systemInstr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle regular messages
|
// Handle regular messages
|
||||||
@@ -222,8 +298,7 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
functionContent, _ = sjson.SetRaw(functionContent, "parts.-1", functionResponse)
|
functionContent, _ = sjson.SetRaw(functionContent, "parts.-1", functionResponse)
|
||||||
out, _ = sjson.SetRaw(out, "contents.-1", functionContent)
|
out, _ = sjson.SetRaw(out, "contents.-1", functionContent)
|
||||||
}
|
}
|
||||||
return true
|
}
|
||||||
})
|
|
||||||
} else if input.Exists() && input.Type == gjson.String {
|
} else if input.Exists() && input.Type == gjson.String {
|
||||||
// Simple string input conversion to user message
|
// Simple string input conversion to user message
|
||||||
userContent := `{"role":"user","parts":[{"text":""}]}`
|
userContent := `{"role":"user","parts":[{"text":""}]}`
|
||||||
|
|||||||
Reference in New Issue
Block a user