mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-09 22:38:10 -05:00
feat: migrate to official anthropics Go SDK
This commit is contained in:
5
go.mod
5
go.mod
@@ -35,6 +35,7 @@ require (
|
|||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.1.2 // indirect
|
github.com/ProtonMail/go-crypto v1.1.2 // indirect
|
||||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||||
|
github.com/anthropics/anthropic-sdk-go v0.2.0-alpha.4 // indirect
|
||||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
|
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
|
||||||
github.com/bytedance/sonic v1.12.4 // indirect
|
github.com/bytedance/sonic v1.12.4 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
||||||
@@ -75,6 +76,10 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||||
github.com/skeema/knownhosts v1.3.0 // indirect
|
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||||
|
github.com/tidwall/gjson v1.14.4 // indirect
|
||||||
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
|
github.com/tidwall/sjson v1.2.5 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
|
|||||||
12
go.sum
12
go.sum
@@ -25,6 +25,8 @@ github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsVi
|
|||||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||||
|
github.com/anthropics/anthropic-sdk-go v0.2.0-alpha.4 h1:TdGQS+RoR4AUO6gqUL74yK1dz/Arrt/WG+dxOj6Yo6A=
|
||||||
|
github.com/anthropics/anthropic-sdk-go v0.2.0-alpha.4/go.mod h1:GJxtdOs9K4neo8Gg65CjJ7jNautmldGli5/OFNabOoo=
|
||||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
|
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
|
||||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
@@ -209,6 +211,16 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
|||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||||
|
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||||
|
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
|
|||||||
@@ -2,17 +2,16 @@ package anthropic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/anthropics/anthropic-sdk-go"
|
||||||
|
"github.com/anthropics/anthropic-sdk-go/option"
|
||||||
|
"github.com/danielmiessler/fabric/common"
|
||||||
"github.com/danielmiessler/fabric/plugins"
|
"github.com/danielmiessler/fabric/plugins"
|
||||||
goopenai "github.com/sashabaranov/go-openai"
|
goopenai "github.com/sashabaranov/go-openai"
|
||||||
|
|
||||||
"github.com/danielmiessler/fabric/common"
|
|
||||||
"github.com/liushuangls/go-anthropic/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const baseUrl = "https://api.anthropic.com/v1"
|
//const baseUrl = "https://api.anthropic.com/"
|
||||||
|
|
||||||
func NewClient() (ret *Client) {
|
func NewClient() (ret *Client) {
|
||||||
vendorName := "Anthropic"
|
vendorName := "Anthropic"
|
||||||
@@ -24,17 +23,20 @@ func NewClient() (ret *Client) {
|
|||||||
ConfigureCustom: ret.configure,
|
ConfigureCustom: ret.configure,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.ApiBaseURL = ret.AddSetupQuestion("API Base URL", false)
|
//ret.ApiBaseURL = ret.AddSetupQuestion("API Base URL", false)
|
||||||
ret.ApiBaseURL.Value = baseUrl
|
//ret.ApiBaseURL.Value = baseUrl
|
||||||
ret.ApiKey = ret.PluginBase.AddSetupQuestion("API key", true)
|
ret.ApiKey = ret.PluginBase.AddSetupQuestion("API key", true)
|
||||||
|
|
||||||
// we could provide a setup question for the following settings
|
// we could provide a setup question for the following settings
|
||||||
ret.maxTokens = 4096
|
ret.maxTokens = 4096
|
||||||
ret.defaultRequiredUserMessage = "Hi"
|
ret.defaultRequiredUserMessage = "Hi"
|
||||||
ret.models = []string{
|
ret.models = []string{
|
||||||
string(anthropic.ModelClaude3Dot5HaikuLatest), string(anthropic.ModelClaude3Opus20240229),
|
anthropic.ModelClaude3_5HaikuLatest, anthropic.ModelClaude3_5Haiku20241022,
|
||||||
string(anthropic.ModelClaude3Opus20240229), string(anthropic.ModelClaude2Dot0), string(anthropic.ModelClaude2Dot1),
|
anthropic.ModelClaude3_5SonnetLatest, anthropic.ModelClaude3_5Sonnet20241022,
|
||||||
string(anthropic.ModelClaude3Dot5SonnetLatest), string(anthropic.ModelClaude3Dot5HaikuLatest),
|
anthropic.ModelClaude_3_5_Sonnet_20240620, anthropic.ModelClaude3OpusLatest,
|
||||||
|
anthropic.ModelClaude_3_Opus_20240229, anthropic.ModelClaude_3_Sonnet_20240229,
|
||||||
|
anthropic.ModelClaude_3_Haiku_20240307, anthropic.ModelClaude_2_1,
|
||||||
|
anthropic.ModelClaude_2_0, anthropic.ModelClaude_Instant_1_2,
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -42,8 +44,8 @@ func NewClient() (ret *Client) {
|
|||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
*plugins.PluginBase
|
*plugins.PluginBase
|
||||||
ApiBaseURL *plugins.SetupQuestion
|
//ApiBaseURL *plugins.SetupQuestion
|
||||||
ApiKey *plugins.SetupQuestion
|
ApiKey *plugins.SetupQuestion
|
||||||
|
|
||||||
maxTokens int
|
maxTokens int
|
||||||
defaultRequiredUserMessage string
|
defaultRequiredUserMessage string
|
||||||
@@ -53,11 +55,14 @@ type Client struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (an *Client) configure() (err error) {
|
func (an *Client) configure() (err error) {
|
||||||
if an.ApiBaseURL.Value != "" {
|
/*if an.ApiBaseURL.Value != "" {
|
||||||
an.client = anthropic.NewClient(an.ApiKey.Value, anthropic.WithBaseURL(an.ApiBaseURL.Value))
|
an.client = anthropic.NewClient(
|
||||||
|
option.WithAPIKey(an.ApiKey.Value), option.WithBaseURL(an.ApiBaseURL.Value),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
an.client = anthropic.NewClient(an.ApiKey.Value)
|
*/
|
||||||
}
|
an.client = anthropic.NewClient(option.WithAPIKey(an.ApiKey.Value))
|
||||||
|
//}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,75 +73,65 @@ func (an *Client) ListModels() (ret []string, err error) {
|
|||||||
func (an *Client) SendStream(
|
func (an *Client) SendStream(
|
||||||
msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions, channel chan string,
|
msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions, channel chan string,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
ctx := context.Background()
|
|
||||||
req := an.buildMessagesRequest(msgs, opts)
|
|
||||||
req.Stream = true
|
|
||||||
|
|
||||||
if _, err = an.client.CreateMessagesStream(ctx, anthropic.MessagesStreamRequest{
|
messages := an.toMessages(msgs)
|
||||||
MessagesRequest: req,
|
|
||||||
OnContentBlockDelta: func(data anthropic.MessagesEventContentBlockDeltaData) {
|
ctx := context.Background()
|
||||||
// fmt.Printf("Stream Content: %s\n", data.Delta.Text)
|
stream := an.client.Messages.NewStreaming(ctx, anthropic.MessageNewParams{
|
||||||
channel <- *data.Delta.Text
|
Model: anthropic.F(opts.Model),
|
||||||
},
|
MaxTokens: anthropic.F(int64(an.maxTokens)),
|
||||||
}); err != nil {
|
TopP: anthropic.F(opts.TopP),
|
||||||
var e *anthropic.APIError
|
Temperature: anthropic.F(opts.Temperature),
|
||||||
if errors.As(err, &e) {
|
Messages: anthropic.F(messages),
|
||||||
fmt.Printf("Messages stream error, type: %s, message: %s", e.Type, e.Message)
|
})
|
||||||
} else {
|
|
||||||
fmt.Printf("Messages stream error: %v\n", err)
|
for stream.Next() {
|
||||||
|
event := stream.Current()
|
||||||
|
|
||||||
|
switch delta := event.Delta.(type) {
|
||||||
|
case anthropic.ContentBlockDeltaEventDelta:
|
||||||
|
if delta.Text != "" {
|
||||||
|
channel <- delta.Text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
close(channel)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if stream.Err() != nil {
|
||||||
|
fmt.Printf("Messages stream error: %v\n", stream.Err())
|
||||||
|
}
|
||||||
|
close(channel)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (an *Client) Send(ctx context.Context, msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret string, err error) {
|
func (an *Client) Send(ctx context.Context, msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret string, err error) {
|
||||||
req := an.buildMessagesRequest(msgs, opts)
|
|
||||||
req.Stream = false
|
|
||||||
|
|
||||||
var resp anthropic.MessagesResponse
|
|
||||||
if resp, err = an.client.CreateMessages(ctx, req); err == nil {
|
|
||||||
ret = *resp.Content[0].Text
|
|
||||||
} else {
|
|
||||||
var e *anthropic.APIError
|
|
||||||
if errors.As(err, &e) {
|
|
||||||
fmt.Printf("Messages error, type: %s, message: %s", e.Type, e.Message)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Messages error: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (an *Client) buildMessagesRequest(msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret anthropic.MessagesRequest) {
|
|
||||||
temperature := float32(opts.Temperature)
|
|
||||||
topP := float32(opts.TopP)
|
|
||||||
|
|
||||||
messages := an.toMessages(msgs)
|
messages := an.toMessages(msgs)
|
||||||
|
|
||||||
ret = anthropic.MessagesRequest{
|
var message *anthropic.Message
|
||||||
Model: anthropic.Model(opts.Model),
|
if message, err = an.client.Messages.New(ctx, anthropic.MessageNewParams{
|
||||||
Temperature: &temperature,
|
Model: anthropic.F(opts.Model),
|
||||||
TopP: &topP,
|
MaxTokens: anthropic.F(int64(an.maxTokens)),
|
||||||
Messages: messages,
|
TopP: anthropic.F(opts.TopP),
|
||||||
MaxTokens: an.maxTokens,
|
Temperature: anthropic.F(opts.Temperature),
|
||||||
|
Messages: anthropic.F(messages),
|
||||||
|
}); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
ret = message.Content[0].Text
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (an *Client) toMessages(msgs []*goopenai.ChatCompletionMessage) (ret []anthropic.Message) {
|
func (an *Client) toMessages(msgs []*goopenai.ChatCompletionMessage) (ret []anthropic.MessageParam) {
|
||||||
// we could call the method before calling the specific vendor
|
// we could call the method before calling the specific vendor
|
||||||
normalizedMessages := common.NormalizeMessages(msgs, an.defaultRequiredUserMessage)
|
normalizedMessages := common.NormalizeMessages(msgs, an.defaultRequiredUserMessage)
|
||||||
|
|
||||||
// Iterate over the incoming session messages and process them
|
// Iterate over the incoming session messages and process them
|
||||||
for _, msg := range normalizedMessages {
|
for _, msg := range normalizedMessages {
|
||||||
var message anthropic.Message
|
var message anthropic.MessageParam
|
||||||
switch msg.Role {
|
switch msg.Role {
|
||||||
case goopenai.ChatMessageRoleUser:
|
case goopenai.ChatMessageRoleUser:
|
||||||
message = anthropic.NewUserTextMessage(msg.Content)
|
message = anthropic.NewUserMessage(anthropic.NewTextBlock(msg.Content))
|
||||||
default:
|
default:
|
||||||
message = anthropic.NewAssistantTextMessage(msg.Content)
|
message = anthropic.NewAssistantMessage(anthropic.NewTextBlock(msg.Content))
|
||||||
}
|
}
|
||||||
ret = append(ret, message)
|
ret = append(ret, message)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user