90 lines
2.9 KiB
Go
90 lines
2.9 KiB
Go
// Package registry löst Modell-Namen auf Caps-Defaults auf (E-10):
|
|
// "OpenAI-kompatibel" ist ein Sammelbegriff, Groq/Cerebras/vLLM/Ollama/
|
|
// LM Studio/OpenRouter verhalten sich unterschiedlich. Die Tabelle hier ist
|
|
// bewusst klein — unbekannte Modelle fallen auf einen konservativen Default,
|
|
// Config-Overrides (CapsOverride) korrigieren im Einzelfall.
|
|
package registry
|
|
|
|
import "nub/internal/llm"
|
|
|
|
var known = map[string]llm.Caps{
|
|
"gpt-4o": {
|
|
ParallelToolCalls: true, UsageInStream: true, SystemRole: "system",
|
|
MaxContext: 128000,
|
|
},
|
|
"gpt-4o-mini": {
|
|
ParallelToolCalls: true, UsageInStream: true, SystemRole: "system",
|
|
MaxContext: 128000,
|
|
},
|
|
"gpt-4.1": {
|
|
ParallelToolCalls: true, UsageInStream: true, SystemRole: "system",
|
|
MaxContext: 1000000,
|
|
},
|
|
"o1": {
|
|
ParallelToolCalls: false, UsageInStream: true, SystemRole: "developer",
|
|
Reasoning: true, MaxContext: 200000,
|
|
},
|
|
}
|
|
|
|
// DefaultCaps liefert die bekannten Caps für ein Modell, oder einen
|
|
// Fallback für unbekannte Modelle (z.B. neuere OpenAI-Modelle, die noch
|
|
// nicht in der Tabelle stehen, oder Drittanbieter/lokale Endpoints).
|
|
//
|
|
// UsageInStream im Fallback ist bewusst true: stream_options.include_usage
|
|
// ist ein Request-Flag, kein modellspezifisches Feature — praktisch jedes
|
|
// OpenAI-Modell (auch zukünftige) honoriert es. Ein Endpoint, der es nicht
|
|
// unterstützt, ist die Ausnahme, nicht die Regel, und lässt sich gezielt
|
|
// über [endpoint.caps] usage_in_stream = false abschalten.
|
|
func DefaultCaps(model string) llm.Caps {
|
|
if caps, ok := known[model]; ok {
|
|
return caps
|
|
}
|
|
return llm.Caps{
|
|
ParallelToolCalls: true,
|
|
UsageInStream: true,
|
|
SystemRole: "system",
|
|
MaxContext: 32000,
|
|
}
|
|
}
|
|
|
|
// CapsOverride überschreibt einzelne Caps-Felder aus der Endpoint-Config.
|
|
// Pointer-Felder unterscheiden "nicht gesetzt" von "explizit false".
|
|
type CapsOverride struct {
|
|
ParallelToolCalls *bool `toml:"parallel_tool_calls"`
|
|
UsageInStream *bool `toml:"usage_in_stream"`
|
|
SystemRole *string `toml:"system_role"`
|
|
ExplicitCache *bool `toml:"explicit_cache"`
|
|
Reasoning *bool `toml:"reasoning"`
|
|
StrictSchemas *bool `toml:"strict_schemas"`
|
|
MaxContext *int `toml:"max_context"`
|
|
SupportsImages *bool `toml:"supports_images"`
|
|
}
|
|
|
|
// Apply merged eine CapsOverride über eine Basis-Caps-Struktur.
|
|
func Apply(base llm.Caps, o CapsOverride) llm.Caps {
|
|
if o.ParallelToolCalls != nil {
|
|
base.ParallelToolCalls = *o.ParallelToolCalls
|
|
}
|
|
if o.UsageInStream != nil {
|
|
base.UsageInStream = *o.UsageInStream
|
|
}
|
|
if o.SystemRole != nil {
|
|
base.SystemRole = *o.SystemRole
|
|
}
|
|
if o.ExplicitCache != nil {
|
|
base.ExplicitCache = *o.ExplicitCache
|
|
}
|
|
if o.Reasoning != nil {
|
|
base.Reasoning = *o.Reasoning
|
|
}
|
|
if o.StrictSchemas != nil {
|
|
base.StrictSchemas = *o.StrictSchemas
|
|
}
|
|
if o.MaxContext != nil {
|
|
base.MaxContext = *o.MaxContext
|
|
}
|
|
if o.SupportsImages != nil {
|
|
base.SupportsImages = *o.SupportsImages
|
|
}
|
|
return base
|
|
}
|