79 lines
3.0 KiB
Go
79 lines
3.0 KiB
Go
// This file implements model-name → provider inference (US: auto-infer provider
|
|
// from --model alone). When a user supplies only --model, with no --provider,
|
|
// --protocol, or --base-url, pigo tries to guess the owning provider from the
|
|
// model id's well-known name prefix (e.g. "claude-*" → anthropic, "deepseek-*"
|
|
// → deepseek). This lets `pigo -m claude-opus-4-8` reach the Anthropic API
|
|
// without the user spelling out the provider or its wire protocol.
|
|
//
|
|
// The mapping is deliberately conservative: only names that unambiguously
|
|
// identify a single built-in provider are inferred. Ambiguous families served
|
|
// by many gateways (notably "llama-*", "qwq-*", "gemma-*", "mixtral-*") are NOT
|
|
// inferred — they return ok=false so the caller falls through to its existing
|
|
// default (OpenRouter), which is the safe, unchanged behavior.
|
|
//
|
|
// Every provider name returned here is guaranteed to exist in providerRegistry
|
|
// (enforced by a test), so callers can hand the result straight to the
|
|
// registry-driven resolution path.
|
|
package provider
|
|
|
|
import "strings"
|
|
|
|
// modelPrefixProvider maps a lowercase model-name prefix to the built-in
|
|
// provider name that serves that family. Order matters: the table is scanned
|
|
// top-to-bottom and the FIRST matching prefix wins, so list more specific
|
|
// prefixes before shorter ones that would also match.
|
|
//
|
|
// Each provider name here must be present in providerRegistry (registry.go).
|
|
var modelPrefixProvider = []struct {
|
|
prefix string
|
|
provider string
|
|
}{
|
|
{"claude-", "anthropic"},
|
|
{"gpt-", "openai"},
|
|
{"o1-", "openai"},
|
|
{"o3-", "openai"},
|
|
{"o4-", "openai"},
|
|
{"gemini-", "google"},
|
|
{"deepseek-", "deepseek"},
|
|
{"glm-", "zai"},
|
|
{"kimi-", "moonshotai"},
|
|
{"moonshot-", "moonshotai"},
|
|
{"qwen-", "dashscope"},
|
|
{"ernie-", "qianfan"},
|
|
{"doubao-", "volcengine"},
|
|
{"grok-", "xai"},
|
|
{"mistral-", "mistral"},
|
|
{"codestral-", "mistral"},
|
|
{"devstral-", "mistral"},
|
|
{"hunyuan-", "hunyuan"},
|
|
{"minimax-", "minimax"},
|
|
{"mimo-", "xiaomi"},
|
|
}
|
|
|
|
// InferProviderFromModel guesses the built-in provider name that serves a given
|
|
// model id, based on the id's well-known name prefix. It returns the provider
|
|
// name and ok=true on a confident match, or ("", false) when the id is unknown
|
|
// or ambiguous (served by multiple gateways). Matching is case-insensitive.
|
|
//
|
|
// The returned name is always a valid entry in providerRegistry. Callers should
|
|
// use it only when no explicit --provider/--protocol/--base-url was given; those
|
|
// flags take precedence over any inference.
|
|
func InferProviderFromModel(model string) (string, bool) {
|
|
id := strings.ToLower(strings.TrimSpace(model))
|
|
if id == "" {
|
|
return "", false
|
|
}
|
|
// A "provider/model" style id (e.g. "openai/gpt-4o") is an OpenRouter-style
|
|
// routed id, not a bare model name — leave those to the caller's preset/
|
|
// prefix handling rather than inferring from the leading segment.
|
|
if strings.Contains(id, "/") {
|
|
return "", false
|
|
}
|
|
for _, m := range modelPrefixProvider {
|
|
if strings.HasPrefix(id, m.prefix) {
|
|
return m.provider, true
|
|
}
|
|
}
|
|
return "", false
|
|
}
|