fix(relay): stop injecting empty tools into Claude requests
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/QuantumNous/new-api/relaykit/dto"
|
||||
"github.com/QuantumNous/new-api/relaykit/relayconvert/convmeta"
|
||||
sharedclaude "github.com/QuantumNous/new-api/relaykit/relayconvert/internal/shared/claude"
|
||||
kitutil "github.com/QuantumNous/new-api/relaykit/relayconvert/kitutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -104,6 +105,82 @@ func TestClaudeThinkingAdapterSatisfiesMaxTokensWithoutCallback(t *testing.T) {
|
||||
assert.Equal(t, uint(1280), *got.MaxTokens)
|
||||
}
|
||||
|
||||
func TestOpenAIChatRequestToClaudeMessagesOmitsEmptyTools(t *testing.T) {
|
||||
maxTokens := uint(16)
|
||||
tests := []struct {
|
||||
name string
|
||||
request dto.GeneralOpenAIRequest
|
||||
wantTools bool
|
||||
}{
|
||||
{
|
||||
name: "omitted tools",
|
||||
request: dto.GeneralOpenAIRequest{
|
||||
Model: "claude-test",
|
||||
MaxTokens: &maxTokens,
|
||||
Messages: []dto.Message{{Role: "user", Content: "hi"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "explicit empty tools",
|
||||
request: dto.GeneralOpenAIRequest{
|
||||
Model: "claude-test",
|
||||
MaxTokens: &maxTokens,
|
||||
Messages: []dto.Message{{Role: "user", Content: "hi"}},
|
||||
Tools: []dto.ToolCallRequest{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "function tool",
|
||||
request: dto.GeneralOpenAIRequest{
|
||||
Model: "claude-test",
|
||||
MaxTokens: &maxTokens,
|
||||
Messages: []dto.Message{{Role: "user", Content: "hi"}},
|
||||
Tools: []dto.ToolCallRequest{{
|
||||
Type: "function",
|
||||
Function: dto.FunctionRequest{
|
||||
Name: "get_weather",
|
||||
Description: "Get weather by city",
|
||||
Parameters: map[string]any{
|
||||
"type": "object",
|
||||
"properties": map[string]any{"city": map[string]any{"type": "string"}},
|
||||
"required": []any{"city"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
wantTools: true,
|
||||
},
|
||||
{
|
||||
name: "web search only",
|
||||
request: dto.GeneralOpenAIRequest{
|
||||
Model: "claude-test",
|
||||
MaxTokens: &maxTokens,
|
||||
Messages: []dto.Message{{Role: "user", Content: "hi"}},
|
||||
WebSearchOptions: &dto.WebSearchOptions{SearchContextSize: "low"},
|
||||
},
|
||||
wantTools: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := OpenAIChatRequestToClaudeMessages(context.Background(), &convmeta.Values{}, test.request)
|
||||
require.NoError(t, err)
|
||||
|
||||
body, err := kitutil.Marshal(got)
|
||||
require.NoError(t, err)
|
||||
|
||||
if test.wantTools {
|
||||
assert.NotNil(t, got.Tools)
|
||||
assert.Contains(t, string(body), `"tools":`)
|
||||
return
|
||||
}
|
||||
assert.Nil(t, got.Tools)
|
||||
assert.NotContains(t, string(body), `"tools":`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func claudeDefaultsMeta(defaultMaxTokens func(string) int) convmeta.Meta {
|
||||
return &convmeta.Values{Options: &convmeta.Options{
|
||||
Claude: convmeta.ClaudeOptions{DefaultMaxTokens: defaultMaxTokens},
|
||||
|
||||
@@ -101,7 +101,9 @@ func OpenAIChatRequestToClaudeMessages(c context.Context, info convmeta.Meta, te
|
||||
Model: textRequest.Model,
|
||||
StopSequences: nil,
|
||||
Temperature: textRequest.Temperature,
|
||||
Tools: claudeTools,
|
||||
}
|
||||
if len(claudeTools) > 0 {
|
||||
claudeRequest.Tools = claudeTools
|
||||
}
|
||||
if maxTokens := textRequest.GetMaxTokens(); maxTokens > 0 {
|
||||
claudeRequest.MaxTokens = kitutil.GetPointer(maxTokens)
|
||||
|
||||
Reference in New Issue
Block a user