a3e9982d49
The Ollama provider now targets /api/chat directly via the native provider introduced in the previous commits. Public API is unchanged for callers that go through llm.Ollama() (and is extended by Task 5's OllamaCloud() constructor). DefaultBaseURL was renamed to DefaultLocalBaseURL (without the trailing /v1 segment used by the OpenAI-compat path). registry.go is updated correspondingly; no other callers referenced the old name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
159 lines
4.5 KiB
Go
159 lines
4.5 KiB
Go
package llm
|
|
|
|
import (
|
|
"gitea.stevedudenhoeffer.com/steve/go-llm/v2/deepseek"
|
|
"gitea.stevedudenhoeffer.com/steve/go-llm/v2/groq"
|
|
"gitea.stevedudenhoeffer.com/steve/go-llm/v2/moonshot"
|
|
"gitea.stevedudenhoeffer.com/steve/go-llm/v2/ollama"
|
|
"gitea.stevedudenhoeffer.com/steve/go-llm/v2/openai"
|
|
"gitea.stevedudenhoeffer.com/steve/go-llm/v2/xai"
|
|
)
|
|
|
|
// ProviderInfo describes a registered provider for discovery purposes (CLI
|
|
// pickers, wiring layers, admin tools). It is the single source of truth for
|
|
// "what providers exist and how do I instantiate one."
|
|
type ProviderInfo struct {
|
|
// Name is the short lowercase identifier used in provider/model strings
|
|
// (e.g., "openai", "deepseek", "moonshot").
|
|
Name string
|
|
|
|
// DisplayName is a human-readable label for UIs.
|
|
DisplayName string
|
|
|
|
// EnvKey is the conventional environment variable that holds the API key
|
|
// for this provider. Empty string means "no key needed" (e.g., Ollama).
|
|
EnvKey string
|
|
|
|
// DefaultURL is the default base URL used when no override is supplied.
|
|
DefaultURL string
|
|
|
|
// Models is a list of well-known model names, populated for CLI pickers
|
|
// and similar. It is not exhaustive and not validated against the API.
|
|
Models []string
|
|
|
|
// New returns a ready-to-use Client for this provider, given an API key
|
|
// (ignored for key-less providers like Ollama) and optional ClientOptions.
|
|
New func(apiKey string, opts ...ClientOption) *Client
|
|
}
|
|
|
|
// providerRegistry is the in-process list of known providers. Order is
|
|
// intentional: the three original providers first, then OpenAI-compatible
|
|
// additions in the order they were added.
|
|
var providerRegistry = []ProviderInfo{
|
|
{
|
|
Name: "openai",
|
|
DisplayName: "OpenAI",
|
|
EnvKey: "OPENAI_API_KEY",
|
|
DefaultURL: openai.DefaultBaseURL,
|
|
Models: []string{
|
|
"gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano",
|
|
"gpt-4o", "gpt-4o-mini",
|
|
"gpt-4-turbo", "gpt-3.5-turbo",
|
|
"o1", "o1-mini", "o1-preview", "o3-mini",
|
|
},
|
|
New: OpenAI,
|
|
},
|
|
{
|
|
Name: "anthropic",
|
|
DisplayName: "Anthropic",
|
|
EnvKey: "ANTHROPIC_API_KEY",
|
|
DefaultURL: "https://api.anthropic.com",
|
|
Models: []string{
|
|
"claude-opus-4-7",
|
|
"claude-sonnet-4-6",
|
|
"claude-haiku-4-5-20251001",
|
|
"claude-opus-4-20250514",
|
|
"claude-sonnet-4-20250514",
|
|
"claude-3-7-sonnet-20250219",
|
|
"claude-3-5-sonnet-20241022",
|
|
"claude-3-5-haiku-20241022",
|
|
},
|
|
New: Anthropic,
|
|
},
|
|
{
|
|
Name: "google",
|
|
DisplayName: "Google",
|
|
EnvKey: "GOOGLE_API_KEY",
|
|
DefaultURL: "https://generativelanguage.googleapis.com",
|
|
Models: []string{
|
|
"gemini-2.0-flash", "gemini-2.0-flash-lite",
|
|
"gemini-1.5-pro", "gemini-1.5-flash", "gemini-1.5-flash-8b",
|
|
},
|
|
New: Google,
|
|
},
|
|
{
|
|
Name: "deepseek",
|
|
DisplayName: "DeepSeek",
|
|
EnvKey: "DEEPSEEK_API_KEY",
|
|
DefaultURL: deepseek.DefaultBaseURL,
|
|
Models: []string{"deepseek-chat", "deepseek-reasoner"},
|
|
New: DeepSeek,
|
|
},
|
|
{
|
|
Name: "moonshot",
|
|
DisplayName: "Moonshot (Kimi)",
|
|
EnvKey: "MOONSHOT_API_KEY",
|
|
DefaultURL: moonshot.DefaultBaseURL,
|
|
Models: []string{
|
|
"kimi-k2-0711-preview",
|
|
"moonshot-v1-8k", "moonshot-v1-32k", "moonshot-v1-128k",
|
|
"moonshot-v1-8k-vision-preview",
|
|
},
|
|
New: Moonshot,
|
|
},
|
|
{
|
|
Name: "xai",
|
|
DisplayName: "xAI (Grok)",
|
|
EnvKey: "XAI_API_KEY",
|
|
DefaultURL: xai.DefaultBaseURL,
|
|
Models: []string{
|
|
"grok-2", "grok-2-mini", "grok-2-vision", "grok-beta",
|
|
},
|
|
New: XAI,
|
|
},
|
|
{
|
|
Name: "groq",
|
|
DisplayName: "Groq",
|
|
EnvKey: "GROQ_API_KEY",
|
|
DefaultURL: groq.DefaultBaseURL,
|
|
Models: []string{
|
|
"llama-3.3-70b-versatile",
|
|
"llama-3.1-8b-instant",
|
|
"mixtral-8x7b-32768",
|
|
"gemma2-9b-it",
|
|
"llama-3.2-90b-vision-preview",
|
|
},
|
|
New: Groq,
|
|
},
|
|
{
|
|
Name: "ollama",
|
|
DisplayName: "Ollama (local)",
|
|
EnvKey: "", // no key needed
|
|
DefaultURL: ollama.DefaultLocalBaseURL,
|
|
Models: []string{
|
|
"llama3.2", "llama3.1", "qwen2.5", "mistral", "gemma2", "phi4",
|
|
},
|
|
New: func(_ string, opts ...ClientOption) *Client { return Ollama(opts...) },
|
|
},
|
|
}
|
|
|
|
// Providers returns a copy of the registered provider list so callers cannot
|
|
// mutate library state.
|
|
func Providers() []ProviderInfo {
|
|
out := make([]ProviderInfo, len(providerRegistry))
|
|
copy(out, providerRegistry)
|
|
return out
|
|
}
|
|
|
|
// ProviderByName returns the registered ProviderInfo with the given name, or
|
|
// nil if no such provider is registered. Name matching is exact.
|
|
func ProviderByName(name string) *ProviderInfo {
|
|
for i := range providerRegistry {
|
|
if providerRegistry[i].Name == name {
|
|
p := providerRegistry[i]
|
|
return &p
|
|
}
|
|
}
|
|
return nil
|
|
}
|