nub/internal/llm/registry/registry.go
Tom a97013d876 initial commit
- v 0.1.0 siehe CHANGELOG.md
2026-07-25 11:08:01 +02:00

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
}