Forráskód Böngészése

fix: support raw JSON response tool arguments

Seefs 1 hónapja
szülő
commit
db89b57e1c

+ 16 - 0
common/json.go

@@ -43,3 +43,19 @@ func GetJsonType(data json.RawMessage) string {
 		return "number"
 	}
 }
+
+// JsonRawMessageToString returns JSON strings as their decoded value and other JSON values as raw text.
+func JsonRawMessageToString(data json.RawMessage) string {
+	trimmed := bytes.TrimSpace(data)
+	if len(trimmed) == 0 || bytes.Equal(trimmed, []byte("null")) {
+		return ""
+	}
+	if trimmed[0] != '"' {
+		return string(trimmed)
+	}
+	var value string
+	if err := Unmarshal(trimmed, &value); err != nil {
+		return string(trimmed)
+	}
+	return value
+}

+ 43 - 0
common/json_test.go

@@ -0,0 +1,43 @@
+package common
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestJsonRawMessageToString(t *testing.T) {
+	tests := []struct {
+		name string
+		data json.RawMessage
+		want string
+	}{
+		{
+			name: "object",
+			data: json.RawMessage(`{"city":"Paris","days":0,"strict":false}`),
+			want: `{"city":"Paris","days":0,"strict":false}`,
+		},
+		{
+			name: "string",
+			data: json.RawMessage(`"{\"city\":\"Paris\",\"days\":0,\"strict\":false}"`),
+			want: `{"city":"Paris","days":0,"strict":false}`,
+		},
+		{
+			name: "null",
+			data: json.RawMessage(`null`),
+			want: "",
+		},
+		{
+			name: "empty",
+			data: nil,
+			want: "",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			require.Equal(t, tt.want, JsonRawMessageToString(tt.data))
+		})
+	}
+}

+ 15 - 1
dto/openai_response.go

@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"fmt"
 
+	"github.com/QuantumNous/new-api/common"
 	"github.com/QuantumNous/new-api/types"
 )
 
@@ -346,7 +347,20 @@ type ResponsesOutput struct {
 	Size      string                   `json:"size"`
 	CallId    string                   `json:"call_id,omitempty"`
 	Name      string                   `json:"name,omitempty"`
-	Arguments string                   `json:"arguments,omitempty"`
+	Arguments json.RawMessage          `json:"arguments,omitempty"`
+}
+
+// ArgumentsString returns function call arguments in the string form expected by Chat Completions.
+func (r *ResponsesOutput) ArgumentsString() string {
+	if r == nil {
+		return ""
+	}
+	return ResponsesArgumentsString(r.Arguments)
+}
+
+// ResponsesArgumentsString returns function call arguments in the string form expected by Chat Completions.
+func ResponsesArgumentsString(arguments json.RawMessage) string {
+	return common.JsonRawMessageToString(arguments)
 }
 
 type ResponsesOutputContent struct {

+ 1 - 1
relay/channel/openai/chat_via_responses.go

@@ -408,7 +408,7 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
 				toolCallNameByID[callID] = name
 			}
 
-			newArgs := streamResp.Item.Arguments
+			newArgs := streamResp.Item.ArgumentsString()
 			prevArgs := toolCallArgsByID[callID]
 			argsDelta := ""
 			if newArgs != "" {

+ 1 - 1
service/openaicompat/responses_to_chat.go

@@ -60,7 +60,7 @@ func ResponsesResponseToChatCompletionsResponse(resp *dto.OpenAIResponsesRespons
 				Type: "function",
 				Function: dto.FunctionResponse{
 					Name:      name,
-					Arguments: out.Arguments,
+					Arguments: out.ArgumentsString(),
 				},
 			})
 		}