diff --git a/llms/marshaling.go b/llms/marshaling.go index a9297a97..c0a18a0a 100644 --- a/llms/marshaling.go +++ b/llms/marshaling.go @@ -245,10 +245,15 @@ func (tc *ToolCall) UnmarshalJSON(data []byte) error { } var fc FunctionCall fcData, ok := toolCall["function"].(json.RawMessage) - if ok { - if err := json.Unmarshal(fcData, &fc); err != nil { - return fmt.Errorf("error unmarshalling function call: %w", err) + if !ok { + b, err := json.Marshal(toolCall["function"]) + if err != nil { + return err } + fcData = b + } + if err := json.Unmarshal(fcData, &fc); err != nil { + return fmt.Errorf("error unmarshalling function call: %w", err) } tc.ID = id tc.Type = typ diff --git a/llms/marshaling_test.go b/llms/marshaling_test.go index 9e3c686b..280fd220 100644 --- a/llms/marshaling_test.go +++ b/llms/marshaling_test.go @@ -240,9 +240,12 @@ func TestUnmarshalJSONMessageContent(t *testing.T) { Parts: []ContentPart{ TextContent{Text: "Hello there!"}, ToolCall{ - ID: "t42", - Type: "function", - FunctionCall: &FunctionCall{Name: "get_current_weather", Arguments: `{ "location": "New York" }`}, + ID: "t42", + Type: "function", + FunctionCall: &FunctionCall{ + Name: "get_current_weather", + Arguments: `{ "location": "New York" }`, + }, }, }, }, @@ -397,7 +400,14 @@ role: user in: MessageContent{ Role: "assistant", Parts: []ContentPart{ - ToolCall{Type: "function", ID: "t01", FunctionCall: &FunctionCall{Name: "get_current_weather", Arguments: `{ "location": "New York" }`}}, + ToolCall{ + Type: "function", + ID: "t01", + FunctionCall: &FunctionCall{ + Name: "get_current_weather", + Arguments: `{ "location": "New York" }`, + }, + }, }, }, }, @@ -406,8 +416,19 @@ role: user in: MessageContent{ Role: "assistant", Parts: []ContentPart{ - ToolCall{Type: "function", ID: "tc01", FunctionCall: &FunctionCall{Name: "get_current_weather", Arguments: `{ "location": "New York" }`}}, - ToolCall{Type: "function", ID: "tc02", FunctionCall: &FunctionCall{Name: "get_current_weather", Arguments: `{ "location": "Berlin" }`}}, + ToolCall{ + Type: "function", + ID: "tc01", + FunctionCall: &FunctionCall{ + Name: "get_current_weather", + Arguments: `{ "location": "New York" }`, + }, + }, + ToolCall{ + Type: "function", + ID: "tc02", + FunctionCall: &FunctionCall{Name: "get_current_weather", Arguments: `{ "location": "Berlin" }`}, + }, }, }, assertedJSON: `{"role":"assistant","parts":[{"type":"tool_call","tool_call":{"function":{"name":"get_current_weather","arguments":"{ \"location\": \"New York\" }"},"id":"tc01","type":"function"}},{"type":"tool_call","tool_call":{"function":{"name":"get_current_weather","arguments":"{ \"location\": \"Berlin\" }"},"id":"tc02","type":"function"}}]}`, @@ -443,7 +464,10 @@ role: assistant in: MessageContent{ Role: "assistant", Parts: []ContentPart{ - ToolCall{Type: "hammer", FunctionCall: &FunctionCall{Name: "hit", Arguments: `{ "force": 10, "direction": "down" }`}}, + ToolCall{ + Type: "hammer", + FunctionCall: &FunctionCall{Name: "hit", Arguments: `{ "force": 10, "direction": "down" }`}, + }, }, }, }, @@ -533,3 +557,27 @@ role: assistant }) } } + +func TestToolCallSerialization(t *testing.T) { + t.Parallel() + toolCall := ToolCall{ + ID: "test_id", + Type: "tool_call", + FunctionCall: &FunctionCall{ + Name: "getIpLocation", + Arguments: `{"ip":"8.8.8.8"}`, + }, + } + b, err := json.Marshal(toolCall) + if err != nil { + t.Fatal(err) + } + + var unmarshalToolCall ToolCall + if e := json.Unmarshal(b, &unmarshalToolCall); e != nil { + t.Fatal(e) + } + if diff := cmp.Diff(toolCall, unmarshalToolCall); diff != "" { + t.Errorf("") + } +}