added anthropic tool support i think

This commit is contained in:
Steve Dudenhoeffer 2025-04-12 03:41:48 -04:00
parent 3093b988f8
commit 916f07be18
7 changed files with 79 additions and 27 deletions

View File

@ -123,7 +123,6 @@ func (a anthropic) requestToAnthropicRequest(req Request) anth.MessagesRequest {
// if this has the same role as the previous message, we can append it to the previous message
// as anthropic expects alternating assistant and user roles
if len(msgs) > 0 && msgs[len(msgs)-1].Role == role {
m2 := &msgs[len(msgs)-1]
@ -134,16 +133,13 @@ func (a anthropic) requestToAnthropicRequest(req Request) anth.MessagesRequest {
}
}
/*
for _, tool := range req.Toolbox.functions {
res.Tools = append(res.Tools, anth.ToolDefinition{
Name: tool.Name,
Description: tool.Description,
InputSchema: tool.Parameters.OpenAIParameters(),
})
}
*/
for _, tool := range req.Toolbox.functions {
res.Tools = append(res.Tools, anth.ToolDefinition{
Name: tool.Name,
Description: tool.Description,
InputSchema: tool.Parameters.AnthropicInputSchema(),
})
}
res.Messages = msgs
@ -158,15 +154,13 @@ func (a anthropic) requestToAnthropicRequest(req Request) anth.MessagesRequest {
}
func (a anthropic) responseToLLMResponse(in anth.MessagesResponse) Response {
res := Response{}
choice := ResponseChoice{}
for _, msg := range in.Content {
choice := ResponseChoice{}
switch msg.Type {
case anth.MessagesContentTypeText:
if msg.Text != nil {
choice.Content = *msg.Text
choice.Content += *msg.Text
}
case anth.MessagesContentTypeToolUse:
@ -185,13 +179,13 @@ func (a anthropic) responseToLLMResponse(in anth.MessagesResponse) Response {
}
}
}
res.Choices = append(res.Choices, choice)
}
log.Println("anthropic response to llm response", res)
log.Println("anthropic response to llm response", choice)
return res
return Response{
Choices: []ResponseChoice{choice},
}
}
func (a anthropic) ChatComplete(ctx context.Context, req Request) (Response, error) {

8
go.sum
View File

@ -35,8 +35,6 @@ github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrk
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
github.com/liushuangls/go-anthropic/v2 v2.15.0 h1:zpplg7BRV/9FlMmeMPI0eDwhViB0l9SkNrF8ErYlRoQ=
github.com/liushuangls/go-anthropic/v2 v2.15.0/go.mod h1:kq2yW3JVy1/rph8u5KzX7F3q95CEpCT2RXp/2nfCmb4=
github.com/openai/openai-go v0.1.0-beta.6 h1:JquYDpprfrGnlKvQQg+apy9dQ8R9mIrm+wNvAPp6jCQ=
github.com/openai/openai-go v0.1.0-beta.6/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/openai/openai-go v0.1.0-beta.9 h1:ABpubc5yU/3ejee2GgRrbFta81SG/d7bQbB8mIdP0Xo=
github.com/openai/openai-go v0.1.0-beta.9/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -71,8 +69,6 @@ go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
@ -87,12 +83,8 @@ golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
google.golang.org/api v0.228.0 h1:X2DJ/uoWGnY5obVjewbp8icSL5U4FzuCfy9OjbLSnLs=
google.golang.org/api v0.228.0/go.mod h1:wNvRS1Pbe8r4+IfBIniV8fwCpGwTrYa+kMUDiC5z5a4=
google.golang.org/genproto/googleapis/api v0.0.0-20250404141209-ee84b53bf3d0 h1:Qbb5RVn5xzI4naMJSpJ7lhvmos6UwZkbekd5Uz7rt9E=
google.golang.org/genproto/googleapis/api v0.0.0-20250404141209-ee84b53bf3d0/go.mod h1:6T35kB3IPpdw7Wul09by0G/JuOuIFkXV6OOvt8IZeT8=
google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a h1:OQ7sHVzkx6L57dQpzUS4ckfWJ51KDH74XHTDe23xWAs=
google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a/go.mod h1:2R6XrVC8Oc08GlNh8ujEpc7HkLiEZ16QeY7FxIs20ac=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250404141209-ee84b53bf3d0 h1:0K7wTWyzxZ7J+L47+LbFogJW1nn/gnnMCN0vGXNYtTI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250404141209-ee84b53bf3d0/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a h1:GIqLhp/cYUkuGuiT+vJk8vhOP86L4+SP5j8yXgeVpvI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=

View File

@ -31,6 +31,14 @@ func (a array) GoogleParameters() *genai.Schema {
}
}
func (a array) AnthropicInputSchema() map[string]any {
return map[string]any{
"type": "array",
"description": a.Description(),
"items": a.items.AnthropicInputSchema(),
}
}
func (a array) FromAny(val any) (reflect.Value, error) {
v := reflect.ValueOf(val)

View File

@ -70,6 +70,32 @@ func (b basic) GoogleParameters() *genai.Schema {
}
}
func (b basic) AnthropicInputSchema() map[string]any {
var t = "string"
switch b.DataType {
case TypeString:
t = "string"
case TypeInteger:
t = "integer"
case TypeNumber:
t = "number"
case TypeBoolean:
t = "boolean"
case TypeObject:
t = "object"
case TypeArray:
t = "array"
default:
t = "unknown"
}
return map[string]any{
"type": t,
"description": b.description,
}
}
func (b basic) Required() bool {
return b.required
}

View File

@ -31,6 +31,14 @@ func (e enum) GoogleParameters() *genai.Schema {
}
}
func (e enum) AnthropicInputSchema() map[string]any {
return map[string]any{
"type": "string",
"description": e.Description(),
"enum": e.values,
}
}
func (e enum) FromAny(val any) (reflect.Value, error) {
v := reflect.ValueOf(val)
if v.Kind() != reflect.String {

View File

@ -98,6 +98,29 @@ func (o Object) GoogleParameters() *genai.Schema {
return res
}
func (o Object) AnthropicInputSchema() map[string]any {
var properties = map[string]any{}
var required []string
for k, v := range o.fields {
properties[k] = v.AnthropicInputSchema()
if v.Required() {
required = append(required, k)
}
}
var res = map[string]any{
"type": "object",
"description": o.Description(),
"properties": properties,
}
if len(required) > 0 {
res["required"] = required
}
return res
}
// FromAny converts the value from any to the correct type, returning the value, and an error if any
func (o Object) FromAny(val any) (reflect.Value, error) {
// if the value is nil, we can't do anything

View File

@ -10,6 +10,7 @@ import (
type Type interface {
OpenAIParameters() openai.FunctionParameters
GoogleParameters() *genai.Schema
AnthropicInputSchema() map[string]any
//SchemaType() jsonschema.DataType
//Definition() jsonschema.Definition