Multiple provider configuration

Add support for having multiple openai or anthropic compatible providers
accessible via different baseUrls
This commit is contained in:
Matt Low 2024-05-05 08:08:17 +00:00
parent bdaf6204f6
commit 8e4ff90ab4
4 changed files with 41 additions and 32 deletions

View File

@ -19,16 +19,14 @@ type Config struct {
TitleGenerationModel *string `yaml:"titleGenerationModel" default:"gpt-3.5-turbo"` TitleGenerationModel *string `yaml:"titleGenerationModel" default:"gpt-3.5-turbo"`
} `yaml:"conversations"` } `yaml:"conversations"`
Tools *struct { Tools *struct {
EnabledTools *[]string `yaml:"enabledTools"` EnabledTools []string `yaml:"enabledTools"`
} `yaml:"tools"` } `yaml:"tools"`
OpenAI *struct { Providers []*struct {
APIKey *string `yaml:"apiKey" default:"your_key_here"` Kind *string `yaml:"kind"`
BaseURL *string `yaml:"baseUrl"`
APIKey *string `yaml:"apiKey"`
Models *[]string `yaml:"models"` Models *[]string `yaml:"models"`
} `yaml:"openai"` } `yaml:"providers"`
Anthropic *struct {
APIKey *string `yaml:"apiKey" default:"your_key_here"`
Models *[]string `yaml:"models"`
} `yaml:"anthropic"`
Chroma *struct { Chroma *struct {
Style *string `yaml:"style" default:"onedark"` Style *string `yaml:"style" default:"onedark"`
Formatter *string `yaml:"formatter" default:"terminal16m"` Formatter *string `yaml:"formatter" default:"terminal16m"`

View File

@ -43,7 +43,7 @@ func NewContext() (*Context, error) {
chroma := tty.NewChromaHighlighter("markdown", *config.Chroma.Formatter, *config.Chroma.Style) chroma := tty.NewChromaHighlighter("markdown", *config.Chroma.Formatter, *config.Chroma.Style)
var enabledTools []model.Tool var enabledTools []model.Tool
for _, toolName := range *config.Tools.EnabledTools { for _, toolName := range config.Tools.EnabledTools {
tool, ok := tools.AvailableTools[toolName] tool, ok := tools.AvailableTools[toolName]
if ok { if ok {
enabledTools = append(enabledTools, tool) enabledTools = append(enabledTools, tool)
@ -54,31 +54,43 @@ func NewContext() (*Context, error) {
} }
func (c *Context) GetModels() (models []string) { func (c *Context) GetModels() (models []string) {
for _, m := range *c.Config.Anthropic.Models { for _, p := range c.Config.Providers {
for _, m := range *p.Models {
models = append(models, m) models = append(models, m)
} }
for _, m := range *c.Config.OpenAI.Models {
models = append(models, m)
} }
return return
} }
func (c *Context) GetCompletionProvider(model string) (provider.ChatCompletionClient, error) { func (c *Context) GetCompletionProvider(model string) (provider.ChatCompletionClient, error) {
for _, m := range *c.Config.Anthropic.Models { for _, p := range c.Config.Providers {
for _, m := range *p.Models {
if m == model { if m == model {
switch *p.Kind {
case "anthropic":
url := "https://api.anthropic.com/v1"
if p.BaseURL != nil {
url = *p.BaseURL
}
anthropic := &anthropic.AnthropicClient{ anthropic := &anthropic.AnthropicClient{
APIKey: *c.Config.Anthropic.APIKey, BaseURL: url,
APIKey: *p.APIKey,
} }
return anthropic, nil return anthropic, nil
case "openai":
url := "https://api.openai.com/v1"
if p.BaseURL != nil {
url = *p.BaseURL
} }
}
for _, m := range *c.Config.OpenAI.Models {
if m == model {
openai := &openai.OpenAIClient{ openai := &openai.OpenAIClient{
BaseURL: "https://api.openai.com/v1", BaseURL: url,
APIKey: *c.Config.OpenAI.APIKey, APIKey: *p.APIKey,
} }
return openai, nil return openai, nil
default:
return nil, fmt.Errorf("unknown provider kind: %s", *p.Kind)
}
}
} }
} }
return nil, fmt.Errorf("unknown model: %s", model) return nil, fmt.Errorf("unknown model: %s", model)

View File

@ -81,14 +81,12 @@ func buildRequest(params model.RequestParameters, messages []model.Message) Requ
} }
func sendRequest(ctx context.Context, c *AnthropicClient, r Request) (*http.Response, error) { func sendRequest(ctx context.Context, c *AnthropicClient, r Request) (*http.Response, error) {
url := "https://api.anthropic.com/v1/messages"
jsonBody, err := json.Marshal(r) jsonBody, err := json.Marshal(r)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to marshal request body: %v", err) return nil, fmt.Errorf("failed to marshal request body: %v", err)
} }
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonBody)) req, err := http.NewRequestWithContext(ctx, "POST", c.BaseURL+"/messages", bytes.NewBuffer(jsonBody))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create HTTP request: %v", err) return nil, fmt.Errorf("failed to create HTTP request: %v", err)
} }

View File

@ -1,6 +1,7 @@
package anthropic package anthropic
type AnthropicClient struct { type AnthropicClient struct {
BaseURL string
APIKey string APIKey string
} }