mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-12 15:21:09 +00:00
fix(relaykit): preserve parameterless tools in Claude conversion (#6862)
This commit is contained in:
@@ -32,25 +32,14 @@ func OpenAIChatRequestToClaudeMessages(c context.Context, info convmeta.Meta, te
|
|||||||
claudeTools := make([]any, 0, len(textRequest.Tools))
|
claudeTools := make([]any, 0, len(textRequest.Tools))
|
||||||
|
|
||||||
for _, tool := range textRequest.Tools {
|
for _, tool := range textRequest.Tools {
|
||||||
if params, ok := tool.Function.Parameters.(map[string]any); ok {
|
if _, ok := tool.Function.Parameters.(map[string]any); !ok && tool.Type != "function" {
|
||||||
claudeTool := dto.Tool{
|
continue
|
||||||
Name: tool.Function.Name,
|
|
||||||
Description: tool.Function.Description,
|
|
||||||
}
|
|
||||||
claudeTool.InputSchema = make(map[string]interface{})
|
|
||||||
if params["type"] != nil {
|
|
||||||
claudeTool.InputSchema["type"] = params["type"].(string)
|
|
||||||
}
|
|
||||||
claudeTool.InputSchema["properties"] = params["properties"]
|
|
||||||
claudeTool.InputSchema["required"] = params["required"]
|
|
||||||
for key, value := range params {
|
|
||||||
if key == "type" || key == "properties" || key == "required" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
claudeTool.InputSchema[key] = value
|
|
||||||
}
|
|
||||||
claudeTools = append(claudeTools, &claudeTool)
|
|
||||||
}
|
}
|
||||||
|
claudeTools = append(claudeTools, &dto.Tool{
|
||||||
|
Name: tool.Function.Name,
|
||||||
|
Description: tool.Function.Description,
|
||||||
|
InputSchema: sharedclaude.FunctionParametersToInputSchema(tool.Function.Parameters),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if textRequest.WebSearchOptions != nil {
|
if textRequest.WebSearchOptions != nil {
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package oaichat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/QuantumNous/new-api/relaykit/dto"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOpenAIChatRequestToClaudeMessagesNormalizesToolInputSchema(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
parameters any
|
||||||
|
wantSchema map[string]any
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "omitted parameters",
|
||||||
|
parameters: nil,
|
||||||
|
wantSchema: map[string]any{
|
||||||
|
"type": "object",
|
||||||
|
"properties": map[string]any{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing type and properties",
|
||||||
|
parameters: map[string]any{
|
||||||
|
"additionalProperties": false,
|
||||||
|
},
|
||||||
|
wantSchema: map[string]any{
|
||||||
|
"type": "object",
|
||||||
|
"properties": map[string]any{},
|
||||||
|
"additionalProperties": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-string type",
|
||||||
|
parameters: map[string]any{
|
||||||
|
"type": 123,
|
||||||
|
"properties": map[string]any{},
|
||||||
|
},
|
||||||
|
wantSchema: map[string]any{
|
||||||
|
"type": 123,
|
||||||
|
"properties": map[string]any{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
maxTokens := uint(1024)
|
||||||
|
got, err := OpenAIChatRequestToClaudeMessages(context.Background(), nil, dto.GeneralOpenAIRequest{
|
||||||
|
Model: "claude-test",
|
||||||
|
MaxTokens: &maxTokens,
|
||||||
|
Messages: []dto.Message{
|
||||||
|
{Role: "user", Content: "Call the tool."},
|
||||||
|
},
|
||||||
|
Tools: []dto.ToolCallRequest{
|
||||||
|
{
|
||||||
|
Type: "function",
|
||||||
|
Function: dto.FunctionRequest{
|
||||||
|
Name: "get_current_time",
|
||||||
|
Description: "Get the current time",
|
||||||
|
Parameters: tt.parameters,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
tools, ok := got.Tools.([]any)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Len(t, tools, 1)
|
||||||
|
tool, ok := tools[0].(*dto.Tool)
|
||||||
|
require.True(t, ok)
|
||||||
|
assert.Equal(t, "get_current_time", tool.Name)
|
||||||
|
assert.Equal(t, tt.wantSchema, tool.InputSchema)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -134,32 +134,12 @@ func responsesFunctionDeclarationsToClaudeTools(functions []dto.FunctionRequest)
|
|||||||
tools = append(tools, &dto.Tool{
|
tools = append(tools, &dto.Tool{
|
||||||
Name: function.Name,
|
Name: function.Name,
|
||||||
Description: function.Description,
|
Description: function.Description,
|
||||||
InputSchema: responsesFunctionParametersToClaudeInputSchema(function.Parameters),
|
InputSchema: sharedclaude.FunctionParametersToInputSchema(function.Parameters),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return tools
|
return tools
|
||||||
}
|
}
|
||||||
|
|
||||||
func responsesFunctionParametersToClaudeInputSchema(parameters any) map[string]interface{} {
|
|
||||||
if params, ok := parameters.(map[string]any); ok {
|
|
||||||
schema := make(map[string]interface{}, len(params))
|
|
||||||
for key, value := range params {
|
|
||||||
schema[key] = value
|
|
||||||
}
|
|
||||||
if schema["type"] == nil {
|
|
||||||
schema["type"] = "object"
|
|
||||||
}
|
|
||||||
if schema["properties"] == nil {
|
|
||||||
schema["properties"] = map[string]interface{}{}
|
|
||||||
}
|
|
||||||
return schema
|
|
||||||
}
|
|
||||||
return map[string]interface{}{
|
|
||||||
"type": "object",
|
|
||||||
"properties": map[string]interface{}{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func applyResponsesReasoningToClaude(req *dto.OpenAIResponsesRequest, claudeRequest *dto.ClaudeRequest) {
|
func applyResponsesReasoningToClaude(req *dto.OpenAIResponsesRequest, claudeRequest *dto.ClaudeRequest) {
|
||||||
effort := ReasoningEffort(req)
|
effort := ReasoningEffort(req)
|
||||||
switch effort {
|
switch effort {
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package claude
|
||||||
|
|
||||||
|
func FunctionParametersToInputSchema(parameters any) map[string]any {
|
||||||
|
params, _ := parameters.(map[string]any)
|
||||||
|
schema := make(map[string]any, len(params)+2)
|
||||||
|
for key, value := range params {
|
||||||
|
schema[key] = value
|
||||||
|
}
|
||||||
|
if schema["type"] == nil {
|
||||||
|
schema["type"] = "object"
|
||||||
|
}
|
||||||
|
if schema["properties"] == nil {
|
||||||
|
schema["properties"] = map[string]any{}
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user