fix(clients): preserve gemini tool call responses
This commit is contained in:
@@ -265,7 +265,7 @@ func geminiResult(request Request, raw map[string]any) map[string]any {
|
||||
"raw": raw,
|
||||
}
|
||||
}
|
||||
content := geminiText(raw)
|
||||
message, finishReason := geminiChatMessage(raw)
|
||||
return map[string]any{
|
||||
"id": "gemini-chat",
|
||||
"object": "chat.completion",
|
||||
@@ -273,8 +273,8 @@ func geminiResult(request Request, raw map[string]any) map[string]any {
|
||||
"model": request.Model,
|
||||
"choices": []any{map[string]any{
|
||||
"index": 0,
|
||||
"finish_reason": "stop",
|
||||
"message": map[string]any{"role": "assistant", "content": content},
|
||||
"finish_reason": finishReason,
|
||||
"message": message,
|
||||
}},
|
||||
"usage": geminiUsageMap(raw),
|
||||
"raw": raw,
|
||||
@@ -303,19 +303,59 @@ func textFromMessages(body map[string]any) string {
|
||||
}
|
||||
|
||||
func geminiText(raw map[string]any) string {
|
||||
message, _ := geminiChatMessage(raw)
|
||||
content, _ := message["content"].(string)
|
||||
return content
|
||||
}
|
||||
|
||||
func geminiChatMessage(raw map[string]any) (map[string]any, string) {
|
||||
candidates, _ := raw["candidates"].([]any)
|
||||
for _, candidate := range candidates {
|
||||
candidateMap, _ := candidate.(map[string]any)
|
||||
content, _ := candidateMap["content"].(map[string]any)
|
||||
parts, _ := content["parts"].([]any)
|
||||
textParts := make([]string, 0, len(parts))
|
||||
toolCalls := make([]any, 0)
|
||||
for _, part := range parts {
|
||||
partMap, _ := part.(map[string]any)
|
||||
if text, ok := partMap["text"].(string); ok && text != "" {
|
||||
return text
|
||||
textParts = append(textParts, text)
|
||||
}
|
||||
functionCall := mapFromAny(firstPresent(partMap["functionCall"], partMap["function_call"]))
|
||||
if len(functionCall) == 0 {
|
||||
continue
|
||||
}
|
||||
if toolCall := normalizeGeminiFunctionCall(functionCall, len(toolCalls), false); toolCall != nil {
|
||||
toolCalls = append(toolCalls, toolCall)
|
||||
}
|
||||
}
|
||||
message := map[string]any{
|
||||
"role": "assistant",
|
||||
"content": strings.Join(textParts, ""),
|
||||
}
|
||||
if len(toolCalls) > 0 {
|
||||
message["tool_calls"] = toolCalls
|
||||
if len(textParts) == 0 {
|
||||
message["content"] = nil
|
||||
}
|
||||
}
|
||||
return message, geminiFinishReason(candidateMap, len(toolCalls) > 0)
|
||||
}
|
||||
return map[string]any{"role": "assistant", "content": ""}, "stop"
|
||||
}
|
||||
|
||||
func geminiFinishReason(candidate map[string]any, hasToolCalls bool) string {
|
||||
if hasToolCalls {
|
||||
return "tool_calls"
|
||||
}
|
||||
switch strings.ToUpper(stringFromAny(candidate["finishReason"])) {
|
||||
case "MAX_TOKENS":
|
||||
return "length"
|
||||
case "SAFETY", "RECITATION", "BLOCKLIST", "PROHIBITED_CONTENT", "SPII":
|
||||
return "content_filter"
|
||||
default:
|
||||
return "stop"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func geminiImageData(raw map[string]any) []any {
|
||||
|
||||
Reference in New Issue
Block a user