ScuttleBot

scuttlebot / internal / llm / factory.go
Source Blame History 106 lines
5ac549c… lmata 1 package llm
5ac549c… lmata 2
5ac549c… lmata 3 import (
5ac549c… lmata 4 "context"
5ac549c… lmata 5 "fmt"
5ac549c… lmata 6 "net/http"
5ac549c… lmata 7 )
5ac549c… lmata 8
5ac549c… lmata 9 // KnownBackends maps OpenAI-compatible backend names to their default base URLs.
5ac549c… lmata 10 var KnownBackends = map[string]string{
5ac549c… lmata 11 "openai": "https://api.openai.com/v1",
5ac549c… lmata 12 "openrouter": "https://openrouter.ai/api/v1",
5ac549c… lmata 13 "together": "https://api.together.xyz/v1",
5ac549c… lmata 14 "groq": "https://api.groq.com/openai/v1",
5ac549c… lmata 15 "fireworks": "https://api.fireworks.ai/inference/v1",
5ac549c… lmata 16 "mistral": "https://api.mistral.ai/v1",
5ac549c… lmata 17 "ai21": "https://api.ai21.com/studio/v1",
5ac549c… lmata 18 "huggingface": "https://api-inference.huggingface.co/v1",
5ac549c… lmata 19 "deepseek": "https://api.deepseek.com/v1",
5ac549c… lmata 20 "cerebras": "https://api.cerebras.ai/v1",
5ac549c… lmata 21 "xai": "https://api.x.ai/v1",
5ac549c… lmata 22 // Local / self-hosted (defaults — override with base_url)
1066004… lmata 23 "litellm": "http://localhost:4000/v1",
1066004… lmata 24 "lmstudio": "http://localhost:1234/v1",
1066004… lmata 25 "jan": "http://localhost:1337/v1",
1066004… lmata 26 "localai": "http://localhost:8080/v1",
1066004… lmata 27 "vllm": "http://localhost:8000/v1",
5ac549c… lmata 28 "anythingllm": "http://localhost:3001/v1",
5ac549c… lmata 29 }
5ac549c… lmata 30
5ac549c… lmata 31 // New creates a Provider from the given config. The returned value may also
5ac549c… lmata 32 // implement ModelDiscoverer — check with a type assertion before calling
5ac549c… lmata 33 // DiscoverModels. Allow/block filters in cfg are applied transparently by
5ac549c… lmata 34 // wrapping the discoverer.
5ac549c… lmata 35 func New(cfg BackendConfig) (Provider, error) {
5ac549c… lmata 36 hc := &http.Client{}
5ac549c… lmata 37 switch cfg.Backend {
5ac549c… lmata 38 case "anthropic":
5ac549c… lmata 39 return newAnthropicProvider(cfg, hc), nil
5ac549c… lmata 40
5ac549c… lmata 41 case "gemini":
5ac549c… lmata 42 return newGeminiProvider(cfg, hc), nil
5ac549c… lmata 43
5ac549c… lmata 44 case "bedrock":
5ac549c… lmata 45 return newBedrockProvider(cfg, hc)
5ac549c… lmata 46
5ac549c… lmata 47 case "ollama":
5ac549c… lmata 48 baseURL := cfg.BaseURL
5ac549c… lmata 49 if baseURL == "" {
5ac549c… lmata 50 baseURL = "http://localhost:11434"
5ac549c… lmata 51 }
5ac549c… lmata 52 return newOllamaProvider(cfg, baseURL, hc), nil
5ac549c… lmata 53
5ac549c… lmata 54 default:
5ac549c… lmata 55 // OpenAI-compatible backend.
5ac549c… lmata 56 baseURL := cfg.BaseURL
5ac549c… lmata 57 if baseURL == "" {
5ac549c… lmata 58 u, ok := KnownBackends[cfg.Backend]
5ac549c… lmata 59 if !ok {
5ac549c… lmata 60 return nil, fmt.Errorf("llm: unknown backend %q — set base_url for custom endpoints", cfg.Backend)
5ac549c… lmata 61 }
5ac549c… lmata 62 baseURL = u
5ac549c… lmata 63 }
5ac549c… lmata 64 model := cfg.Model
5ac549c… lmata 65 if model == "" {
5ac549c… lmata 66 model = "gpt-4o-mini"
5ac549c… lmata 67 }
5ac549c… lmata 68 return newOpenAIProvider(cfg.APIKey, baseURL, model, hc), nil
5ac549c… lmata 69 }
5ac549c… lmata 70 }
5ac549c… lmata 71
5ac549c… lmata 72 // Discover runs model discovery for the given config, applying any allow/block
5ac549c… lmata 73 // filters from the config. Returns an error if the provider doesn't support
5ac549c… lmata 74 // discovery.
5ac549c… lmata 75 func Discover(ctx context.Context, cfg BackendConfig) ([]ModelInfo, error) {
5ac549c… lmata 76 p, err := New(cfg)
5ac549c… lmata 77 if err != nil {
5ac549c… lmata 78 return nil, err
5ac549c… lmata 79 }
5ac549c… lmata 80 d, ok := p.(ModelDiscoverer)
5ac549c… lmata 81 if !ok {
5ac549c… lmata 82 return nil, fmt.Errorf("llm: backend %q does not support model discovery", cfg.Backend)
5ac549c… lmata 83 }
5ac549c… lmata 84 models, err := d.DiscoverModels(ctx)
5ac549c… lmata 85 if err != nil {
5ac549c… lmata 86 return nil, err
5ac549c… lmata 87 }
5ac549c… lmata 88 if len(cfg.Allow) > 0 || len(cfg.Block) > 0 {
5ac549c… lmata 89 f, ferr := NewModelFilter(cfg.Allow, cfg.Block)
5ac549c… lmata 90 if ferr != nil {
5ac549c… lmata 91 return nil, ferr
5ac549c… lmata 92 }
5ac549c… lmata 93 models = f.Apply(models)
5ac549c… lmata 94 }
5ac549c… lmata 95 return models, nil
5ac549c… lmata 96 }
5ac549c… lmata 97
5ac549c… lmata 98 // BackendNames returns a sorted list of all known backend names.
5ac549c… lmata 99 func BackendNames() []string {
5ac549c… lmata 100 names := make([]string, 0, len(KnownBackends)+4)
5ac549c… lmata 101 for k := range KnownBackends {
5ac549c… lmata 102 names = append(names, k)
5ac549c… lmata 103 }
5ac549c… lmata 104 names = append(names, "anthropic", "gemini", "bedrock", "ollama")
5ac549c… lmata 105 return names
5ac549c… lmata 106 }

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button