mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
fix(apicompat): default tool strict to false
This commit is contained in:
@@ -113,6 +113,91 @@ func TestChatCompletionsToResponses_ToolCalls(t *testing.T) {
|
||||
assert.Equal(t, "ping", resp.Tools[0].Name)
|
||||
}
|
||||
|
||||
func TestChatCompletionsToResponses_ToolStrict(t *testing.T) {
|
||||
strictTrue := true
|
||||
strictFalse := false
|
||||
tests := []struct {
|
||||
name string
|
||||
strict *bool
|
||||
want bool
|
||||
}{
|
||||
{name: "defaults omitted strict to false", want: false},
|
||||
{name: "preserves explicit true", strict: &strictTrue, want: true},
|
||||
{name: "preserves explicit false", strict: &strictFalse, want: false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req := &ChatCompletionsRequest{
|
||||
Model: "gpt-4o",
|
||||
Messages: []ChatMessage{{Role: "user", Content: json.RawMessage(`"Hi"`)}},
|
||||
Tools: []ChatTool{{
|
||||
Type: "function",
|
||||
Function: &ChatFunction{
|
||||
Name: "lookup",
|
||||
Strict: tt.strict,
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
resp, err := ChatCompletionsToResponses(req)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resp.Tools, 1)
|
||||
require.NotNil(t, resp.Tools[0].Strict)
|
||||
assert.Equal(t, tt.want, *resp.Tools[0].Strict)
|
||||
|
||||
payload, err := json.Marshal(resp)
|
||||
require.NoError(t, err)
|
||||
|
||||
var serialized struct {
|
||||
Tools []map[string]json.RawMessage `json:"tools"`
|
||||
}
|
||||
require.NoError(t, json.Unmarshal(payload, &serialized))
|
||||
require.Len(t, serialized.Tools, 1)
|
||||
strictJSON, ok := serialized.Tools[0]["strict"]
|
||||
require.True(t, ok, "strict must be present in the Responses payload")
|
||||
assert.JSONEq(t, string(mustMarshalJSON(t, tt.want)), string(strictJSON))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChatCompletionsToResponses_LegacyFunctionDefaultsStrictFalse(t *testing.T) {
|
||||
req := &ChatCompletionsRequest{
|
||||
Model: "gpt-4o",
|
||||
Messages: []ChatMessage{{Role: "user", Content: json.RawMessage(`"Hi"`)}},
|
||||
Functions: []ChatFunction{{
|
||||
Name: "lookup",
|
||||
}},
|
||||
}
|
||||
|
||||
resp, err := ChatCompletionsToResponses(req)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resp.Tools, 1)
|
||||
require.NotNil(t, resp.Tools[0].Strict)
|
||||
assert.False(t, *resp.Tools[0].Strict)
|
||||
|
||||
payload, err := json.Marshal(resp)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(payload), `"strict":false`)
|
||||
}
|
||||
|
||||
func TestResponsesTool_StrictFalseIsSerialized(t *testing.T) {
|
||||
strict := false
|
||||
payload, err := json.Marshal(ResponsesTool{
|
||||
Type: "function",
|
||||
Strict: &strict,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, `{"type":"function","strict":false}`, string(payload))
|
||||
}
|
||||
|
||||
func mustMarshalJSON(t *testing.T, value any) []byte {
|
||||
t.Helper()
|
||||
data, err := json.Marshal(value)
|
||||
require.NoError(t, err)
|
||||
return data
|
||||
}
|
||||
|
||||
func TestChatCompletionsToResponses_MaxTokens(t *testing.T) {
|
||||
t.Run("max_tokens", func(t *testing.T) {
|
||||
maxTokens := 100
|
||||
|
||||
@@ -419,7 +419,7 @@ func convertChatToolsToResponses(tools []ChatTool, functions []ChatFunction) []R
|
||||
Name: t.Function.Name,
|
||||
Description: t.Function.Description,
|
||||
Parameters: t.Function.Parameters,
|
||||
Strict: t.Function.Strict,
|
||||
Strict: defaultStrictFalse(t.Function.Strict),
|
||||
}
|
||||
out = append(out, rt)
|
||||
}
|
||||
@@ -431,7 +431,7 @@ func convertChatToolsToResponses(tools []ChatTool, functions []ChatFunction) []R
|
||||
Name: f.Name,
|
||||
Description: f.Description,
|
||||
Parameters: f.Parameters,
|
||||
Strict: f.Strict,
|
||||
Strict: defaultStrictFalse(f.Strict),
|
||||
}
|
||||
out = append(out, rt)
|
||||
}
|
||||
@@ -439,6 +439,14 @@ func convertChatToolsToResponses(tools []ChatTool, functions []ChatFunction) []R
|
||||
return out
|
||||
}
|
||||
|
||||
func defaultStrictFalse(src *bool) *bool {
|
||||
if src == nil {
|
||||
value := false
|
||||
return &value
|
||||
}
|
||||
return src
|
||||
}
|
||||
|
||||
// convertChatFunctionCallToToolChoice maps the legacy function_call field to a
|
||||
// Responses API tool_choice value.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user