// Package ollama provides an Adapter that calls a local Ollama server. package ollama import ( "context" "net/http" "strings" "time" "go.uber.org/zap" "iop/packages/go/config" runtime "iop/packages/go/execution" ) const Name = "ollama" const runtimeMetadataOpenAIToolCalls = "openai_tool_calls" type Ollama struct { instanceName string baseURL string contextSize int capacity int maxQueue int queueTimeoutMS int requestTimeoutMS int client *http.Client logger *zap.Logger } // New creates an Ollama adapter. The optional instanceName is the registry // instance key used to disambiguate multiple Ollama instances on the same node. func New(cfg config.OllamaConf, logger *zap.Logger, instanceName ...string) *Ollama { baseURL := strings.TrimRight(cfg.BaseURL, "/") if baseURL == "" { baseURL = "http://localhost:11434" } name := Name if len(instanceName) > 0 && instanceName[0] != "" { name = instanceName[0] } return &Ollama{ instanceName: name, baseURL: baseURL, contextSize: cfg.ContextSize, capacity: cfg.Capacity, maxQueue: cfg.MaxQueue, queueTimeoutMS: cfg.QueueTimeoutMS, requestTimeoutMS: cfg.RequestTimeoutMS, client: &http.Client{}, logger: logger, } } func (o *Ollama) Name() string { return Name } func (o *Ollama) Capabilities(ctx context.Context) (runtime.Capabilities, error) { probeCtx, cancel := context.WithTimeout(ctx, 2*time.Second) defer cancel() targets, err := o.fetchTargets(probeCtx) status := runtime.ProviderStatusAvailable if err != nil { status = runtime.ProviderStatusUnavailable } return runtime.Capabilities{ AdapterName: Name, InstanceKey: o.instanceName, Targets: targets, MaxConcurrency: effectiveCapacity(o.capacity, 4), MaxQueue: o.maxQueue, QueueTimeoutMS: o.queueTimeoutMS, RequestTimeoutMS: o.requestTimeoutMS, ProviderStatus: runtime.NormalizeProviderStatus(status), }, nil } func effectiveCapacity(capacity, defaultVal int) int { if capacity <= 0 { return defaultVal } return capacity }