Documentation
¶
Overview ¶
Package provider implements a unified interface for creating and managing multiple LLM providers with intelligent routing, fallback strategies, and metrics tracking.
Overview ¶
The provider package provides a consistent way to create and configure any of the supported LLM providers (Anthropic, GitHub Copilot, Ollama, OpenAI) while maintaining backward compatibility and supporting all provider-specific features. It also includes a Router component for managing multiple providers with configurable routing and fallback strategies.
Supported Providers ¶
- Anthropic (Claude models)
- GitHub Copilot
- Ollama (local models)
- OpenAI (GPT models)
Single Provider Usage ¶
The simplest way to create a provider is using the factory pattern with NewProvider:
model, cleanup, err := provider.NewProvider(ctx, provider.ProviderOpenAI,
provider.WithModel("gpt-4o"),
provider.WithTemperature(0.7),
provider.WithAPIKey("sk-..."),
)
if err != nil {
return err
}
defer cleanup()
response, err := model.Invoke(ctx, messages)
The factory returns three values:
- A ChatModel instance that implements the llms.ChatModel interface
- A cleanup function that must be called to release resources
- An error if creation fails
Common Configuration Options ¶
All providers support these common options:
WithModel(model string) // Model name (e.g., "gpt-4o", "claude-3-opus") WithTemperature(temp float64) // Temperature (0.0-2.0) WithMaxTokens(tokens int) // Maximum tokens to generate WithTopP(topP float64) // Top-p sampling (0.0-1.0) WithStop(sequences []string) // Stop sequences WithAPIKey(key string) // API key for authentication WithBaseURL(url string) // Custom base URL
Provider-Specific Configuration ¶
Provider-specific options are set using WithProviderSpecific:
// GitHub Copilot with tools
model, cleanup, err := provider.NewProvider(ctx, provider.ProviderGitHubCopilot,
provider.WithModel("gpt-4o"),
provider.WithProviderSpecific("tools", []tools.Tool{myTool}),
provider.WithProviderSpecific("cli_path", "/usr/local/bin/github-copilot-cli"),
)
// Ollama with custom options
model, cleanup, err := provider.NewProvider(ctx, provider.ProviderOllama,
provider.WithModel("llama2"),
provider.WithProviderSpecific("keep_alive", "5m"),
provider.WithProviderSpecific("num_ctx", 4096),
)
Multi-Provider Router ¶
The Router manages multiple provider instances and routes requests based on configurable strategies:
router, err := provider.NewRouter(ctx,
[]provider.ProviderEntry{
{
Name: "fast-gpt",
ProviderType: provider.ProviderOpenAI,
Options: []provider.ProviderOption{provider.WithModel("gpt-3.5-turbo")},
Weight: 3,
Tags: []string{"fast", "cheap"},
},
{
Name: "smart-claude",
ProviderType: provider.ProviderAnthropic,
Options: []provider.ProviderOption{provider.WithModel("claude-3-opus-20240229")},
Weight: 1,
Tags: []string{"smart", "expensive"},
},
},
&provider.WeightedStrategy{},
provider.WithFallback(&provider.SequentialFallback{Order: []string{"fast-gpt", "smart-claude"}}),
)
if err != nil {
return err
}
defer router.Cleanup()
// Use router like any ChatModel
response, err := router.Invoke(ctx, messages)
Routing Strategies ¶
The package provides seven built-in routing strategies:
1. SimpleStrategy - Always routes to a specific provider:
strategy := &provider.SimpleStrategy{ProviderName: "fast-gpt"}
2. RoundRobinStrategy - Distributes requests evenly across providers:
strategy := &provider.RoundRobinStrategy{}
3. WeightedStrategy - Routes based on provider weights:
strategy := provider.NewWeightedStrategy(map[string]int{
"fast-gpt": 3, // 75% of requests
"smart-claude": 1, // 25% of requests
})
4. RuleBasedStrategy - Routes based on request characteristics:
strategy := provider.NewRuleBasedStrategy(
[]provider.RoutingRule{
{
Name: "complex-to-claude",
Priority: 100,
Condition: func(ctx provider.RequestContext) bool {
return ctx.Complexity == "complex" || ctx.HasToolCalls
},
Provider: "smart-claude",
},
{
Name: "simple-to-gpt",
Priority: 50,
Condition: func(ctx provider.RequestContext) bool {
return ctx.Complexity == "simple"
},
Provider: "fast-gpt",
},
},
"fast-gpt", // default provider
)
5. LoadBalancedStrategy - Routes based on performance metrics:
strategy := provider.NewLoadBalancedStrategy(router.GetMetrics())
This strategy automatically selects the provider with the best combination of:
- Lowest average latency
- Lowest error rate
- Least recent usage (for load distribution)
6. LLMRoutingStrategy - Uses an LLM to make intelligent routing decisions:
metaModel, cleanup, _ := provider.NewProvider(ctx, provider.ProviderOpenAI,
provider.WithModel("gpt-4o-mini"),
)
defer cleanup()
strategy := provider.NewLLMRoutingStrategy(
metaModel,
[]string{"fast-gpt", "smart-claude"},
map[string]string{
"fast-gpt": "Fast and cost-effective for simple queries",
"smart-claude": "Best for complex reasoning and analysis",
},
)
The LLM analyzes each request and selects the most appropriate provider. Decisions are cached to avoid repeated LLM calls for similar requests.
7. CustomStrategy - User-defined routing logic:
strategy := &provider.CustomStrategy{
SelectFunc: func(ctx context.Context, reqCtx provider.RequestContext, providers map[string]llms.ChatModel) (string, error) {
// Custom logic here
if reqCtx.TotalTokens > 5000 {
return "smart-claude", nil
}
return "fast-gpt", nil
},
OnSuccessFunc: func(ctx context.Context, providerName string, latency time.Duration) {
// Track successes
},
OnErrorFunc: func(ctx context.Context, providerName string, err error) {
// Track errors
},
}
Fallback Strategies ¶
When a provider fails, the router can automatically try alternative providers:
1. NoFallback - Never retries (default):
provider.WithFallback(&provider.NoFallback{})
2. SequentialFallback - Tries providers in order:
provider.WithFallback(&provider.SequentialFallback{
Order: []string{"fast-gpt", "smart-claude", "local-ollama"},
})
3. SmartFallback - Selects fallback based on success rate:
provider.WithFallback(&provider.SmartFallback{})
SmartFallback uses metrics to choose the provider with the highest success rate, giving preference to recently successful providers.
Metrics Tracking ¶
The router automatically tracks metrics for all providers:
metrics := router.GetMetrics()
for name, m := range metrics {
fmt.Printf("Provider: %s\n", name)
fmt.Printf(" Requests: %d\n", m.RequestCount)
fmt.Printf(" Errors: %d\n", m.ErrorCount)
fmt.Printf(" Avg Latency: %v\n", m.TotalLatency/time.Duration(m.RequestCount))
fmt.Printf(" Last Used: %v\n", m.LastUsed)
}
Metrics include:
- Request count per provider
- Error count per provider
- Total latency per provider
- Last usage timestamp per provider
Request Context ¶
The router builds a RequestContext for each request, which routing strategies use to make decisions:
type RequestContext struct {
Messages []core.Message // The messages being sent
MessageCount int // Number of messages
TotalTokens int // Estimated token count
HasToolCalls bool // Whether request involves tool calls
Priority string // "low", "medium", "high"
Complexity string // "simple", "moderate", "complex"
UserMetadata map[string]any // Custom metadata
}
Complexity is automatically inferred:
- "complex": >10,000 tokens or has tool calls
- "simple": <1,000 tokens and no tool calls
- "moderate": everything else
Authentication ¶
The package supports multiple authentication methods:
1. Explicit API key:
provider.WithAPIKey("sk-...")
2. Environment variables:
ANTHROPIC_API_KEY // For Anthropic OPENAI_API_KEY // For OpenAI GITHUB_TOKEN // For GitHub Copilot
3. GitHub CLI (for Copilot):
gh auth token
Ollama doesn't require authentication.
Resource Cleanup ¶
Always call cleanup functions to release resources:
// Single provider
model, cleanup, err := provider.NewProvider(ctx, provider.ProviderOpenAI, ...)
if err != nil {
return err
}
defer cleanup()
// Router
router, err := provider.NewRouter(ctx, entries, strategy)
if err != nil {
return err
}
defer router.Cleanup()
For most providers, cleanup is a no-op. For GitHub Copilot, cleanup stops the CLI server process.
Thread Safety ¶
All components are thread-safe and support concurrent usage:
- Multiple goroutines can invoke the same provider or router concurrently
- Metrics updates are atomic
- Routing strategy state is protected by mutexes
Error Handling ¶
The package provides detailed error types:
err := provider.NewProviderError(providerType, name, operation, cause) err := provider.NewRoutingError(operation, cause) err := provider.NewFallbackError(failedProvider, attemptedProviders, cause)
Common errors:
- ErrUnknownProvider: Invalid provider type
- ErrProviderNotFound: Provider name not found in router
- ErrNoProvidersAvailable: Router has no providers
- ErrNoFallbackAvailable: No fallback provider available
- ErrRouterClosed: Router has been cleaned up
Complete Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/LucaLanziani/langchain-go/core"
"github.com/LucaLanziani/langchain-go/provider"
)
func main() {
ctx := context.Background()
// Create router with multiple providers
router, err := provider.NewRouter(ctx,
[]provider.ProviderEntry{
{
Name: "fast",
ProviderType: provider.ProviderOpenAI,
Options: []provider.ProviderOption{
provider.WithModel("gpt-3.5-turbo"),
provider.WithTemperature(0.7),
},
Weight: 3,
},
{
Name: "smart",
ProviderType: provider.ProviderAnthropic,
Options: []provider.ProviderOption{
provider.WithModel("claude-3-opus-20240229"),
provider.WithMaxTokens(4096),
},
Weight: 1,
},
},
provider.NewWeightedStrategy(map[string]int{
"fast": 3,
"smart": 1,
}),
provider.WithFallback(&provider.SequentialFallback{
Order: []string{"fast", "smart"},
}),
)
if err != nil {
log.Fatal(err)
}
defer router.Cleanup()
// Use router like any ChatModel
messages := []core.Message{
core.NewHumanMessage("What is the capital of France?"),
}
response, err := router.Invoke(ctx, messages)
if err != nil {
log.Fatal(err)
}
fmt.Println(response.GetContent())
// Check metrics
metrics := router.GetMetrics()
for name, m := range metrics {
fmt.Printf("%s: %d requests, %d errors\n", name, m.RequestCount, m.ErrorCount)
}
}
Backward Compatibility ¶
The package maintains full backward compatibility with existing provider-specific constructors:
// Still works
model := anthropic.New(anthropic.WithModelName("claude-3-opus-20240229"))
model := openai.New(openai.WithModelName("gpt-4o"))
model := ollama.New(ollama.WithModel("llama2"))
model, _ := copilot.New(ctx, copilot.WithModelName("gpt-4o"))
The unified interface is an addition, not a replacement.
Index ¶
- Constants
- Variables
- func NewFallbackError(failedProvider string, attemptedFallbacks []string, err error) error
- func NewFallbackErrorWithStrategy(failedProvider string, attemptedFallbacks []string, fallbackStrategy string, ...) error
- func NewProviderError(providerType ProviderType, providerName, operation string, err error) error
- func NewProviderErrorWithContext(providerType ProviderType, providerName, operation string, err error, ...) error
- func NewRoutingError(strategy string, err error) error
- func NewRoutingErrorWithContext(strategy string, availableProviders []string, requestComplexity string, ...) error
- func NewValidationError(field string, value any, message string) error
- type BatchError
- type CleanupFunc
- type CustomStrategy
- func (s *CustomStrategy) OnError(ctx context.Context, providerName string, err error)
- func (s *CustomStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
- func (s *CustomStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, ...) (providerName string, err error)
- type FallbackError
- type FallbackStrategy
- type LLMRoutingStrategy
- func (s *LLMRoutingStrategy) OnError(ctx context.Context, providerName string, err error)
- func (s *LLMRoutingStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
- func (s *LLMRoutingStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, ...) (string, error)
- type LoadBalancedStrategy
- func (s *LoadBalancedStrategy) OnError(ctx context.Context, providerName string, err error)
- func (s *LoadBalancedStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
- func (s *LoadBalancedStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, ...) (string, error)
- type NoFallback
- type ProviderConfig
- type ProviderEntry
- type ProviderError
- type ProviderMetrics
- type ProviderOption
- func WithAPIKey(apiKey string) ProviderOption
- func WithAnthropicVersion(version string) ProviderOption
- func WithBaseURL(baseURL string) ProviderOption
- func WithCLIPath(cliPath string) ProviderOption
- func WithFormat(format string) ProviderOption
- func WithKeepAlive(keepAlive string) ProviderOption
- func WithLogLevel(logLevel string) ProviderOption
- func WithMaxTokens(maxTokens int) ProviderOption
- func WithModel(model string) ProviderOption
- func WithNumCtx(numCtx int) ProviderOption
- func WithOrganization(organization string) ProviderOption
- func WithProviderSpecific(key string, value any) ProviderOption
- func WithStop(stop []string) ProviderOption
- func WithTemperature(temperature float64) ProviderOption
- func WithTools(tools ...tools.Tool) ProviderOption
- func WithTopK(topK int) ProviderOption
- func WithTopP(topP float64) ProviderOption
- type ProviderStats
- type ProviderType
- type RequestContext
- type RoundRobinStrategy
- func (s *RoundRobinStrategy) OnError(ctx context.Context, providerName string, err error)
- func (s *RoundRobinStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
- func (s *RoundRobinStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, ...) (string, error)
- type Router
- func (r *Router) Batch(ctx context.Context, inputs [][]core.Message, opts ...core.Option) ([]*core.AIMessage, error)
- func (r *Router) BindTools(tools ...llms.ToolDefinition) llms.ChatModel
- func (r *Router) Cleanup() error
- func (r *Router) Generate(ctx context.Context, messages []core.Message, opts ...core.Option) (*llms.ChatResult, error)
- func (r *Router) GetMetrics() map[string]ProviderMetrics
- func (r *Router) GetName() string
- func (r *Router) GetProvider(name string) llms.ChatModel
- func (r *Router) Invoke(ctx context.Context, messages []core.Message, opts ...core.Option) (*core.AIMessage, error)
- func (r *Router) ListProviders() []string
- func (r *Router) Stream(ctx context.Context, messages []core.Message, opts ...core.Option) (*core.StreamIterator[*core.AIMessage], error)
- func (r *Router) WithStructuredOutput(schema map[string]any) llms.ChatModel
- type RouterConfig
- type RouterMetrics
- type RouterOption
- type RoutingError
- type RoutingRule
- type RoutingStrategy
- type RuleBasedStrategy
- func (s *RuleBasedStrategy) AddRule(rule RoutingRule)
- func (s *RuleBasedStrategy) GetRules() []RoutingRule
- func (s *RuleBasedStrategy) OnError(ctx context.Context, providerName string, err error)
- func (s *RuleBasedStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
- func (s *RuleBasedStrategy) RemoveRule(name string)
- func (s *RuleBasedStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, ...) (string, error)
- type SequentialFallback
- type SimpleStrategy
- type SmartFallback
- type ValidationError
- type WeightedStrategy
- func (s *WeightedStrategy) GetWeight(providerName string) int
- func (s *WeightedStrategy) OnError(ctx context.Context, providerName string, err error)
- func (s *WeightedStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
- func (s *WeightedStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, ...) (string, error)
- func (s *WeightedStrategy) SetWeight(providerName string, weight int)
Constants ¶
const (
// Version is the current version of the provider package
Version = "1.0.0"
)
Version information
Variables ¶
var ( // ErrUnknownProvider is returned when an invalid provider type is specified ErrUnknownProvider = errors.New("unknown provider type") // ErrInvalidConfig is returned when provider configuration is invalid ErrInvalidConfig = errors.New("invalid provider configuration") // ErrDuplicateProviderName is returned when router entries have duplicate names ErrDuplicateProviderName = errors.New("duplicate provider name in router entries") // ErrEmptyProviderList is returned when router is created with no providers ErrEmptyProviderList = errors.New("router requires at least one provider") // ErrProviderNotFound is returned when a requested provider doesn't exist ErrProviderNotFound = errors.New("provider not found") // ErrNoFallbackAvailable is returned when fallback is needed but no providers are available ErrNoFallbackAvailable = errors.New("no fallback provider available") // ErrMaxRetriesExceeded is returned when all retry attempts have been exhausted ErrMaxRetriesExceeded = errors.New("maximum retry attempts exceeded") // ErrInvalidProviderFromLLM is returned when LLM routing returns an invalid provider name ErrInvalidProviderFromLLM = errors.New("LLM returned invalid provider name") // ErrMissingRequiredField is returned when a required configuration field is missing ErrMissingRequiredField = errors.New("missing required configuration field") // ErrInvalidFieldValue is returned when a configuration field has an invalid value ErrInvalidFieldValue = errors.New("invalid configuration field value") // ErrAuthenticationFailed is returned when provider authentication fails ErrAuthenticationFailed = errors.New("provider authentication failed") // ErrProviderInitialization is returned when provider initialization fails ErrProviderInitialization = errors.New("provider initialization failed") // ErrRouterClosed is returned when operations are attempted on a closed router ErrRouterClosed = errors.New("router has been closed") // ErrNoProvidersAvailable is returned when no providers are available for routing ErrNoProvidersAvailable = errors.New("no providers available") )
Sentinel errors for provider operations
Functions ¶
func NewFallbackError ¶
NewFallbackError creates a new fallback error
func NewFallbackErrorWithStrategy ¶
func NewFallbackErrorWithStrategy(failedProvider string, attemptedFallbacks []string, fallbackStrategy string, err error) error
NewFallbackErrorWithStrategy creates a new fallback error with strategy information
func NewProviderError ¶
func NewProviderError(providerType ProviderType, providerName, operation string, err error) error
NewProviderError creates a new provider error with context
func NewProviderErrorWithContext ¶
func NewProviderErrorWithContext(providerType ProviderType, providerName, operation string, err error, context map[string]string) error
NewProviderErrorWithContext creates a new provider error with additional context
func NewRoutingError ¶
NewRoutingError creates a new routing error
Types ¶
type BatchError ¶
BatchError reports per-item failures from Router.Batch while preserving partial results.
func (*BatchError) Error ¶
func (e *BatchError) Error() string
func (*BatchError) Unwrap ¶
func (e *BatchError) Unwrap() error
type CleanupFunc ¶
type CleanupFunc func() error
CleanupFunc releases provider resources (e.g., Copilot CLI server)
func NewProvider ¶
func NewProvider(ctx context.Context, providerType ProviderType, opts ...ProviderOption) (llms.ChatModel, CleanupFunc, error)
NewProvider creates a ChatModel for the specified provider type with unified configuration. Returns the created model, a cleanup function, and an error if creation fails.
The cleanup function must be called when the model is no longer needed to release resources. For most providers (Anthropic, OpenAI, Ollama), cleanup is a no-op. For GitHub Copilot, cleanup stops the CLI server process.
Example:
model, cleanup, err := provider.NewProvider(ctx, provider.ProviderOpenAI,
provider.WithModel("gpt-4o"),
provider.WithTemperature(0.7),
provider.WithAPIKey("sk-..."),
)
if err != nil {
return err
}
defer cleanup()
type CustomStrategy ¶
type CustomStrategy struct {
SelectFunc func(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (string, error)
OnSuccessFunc func(ctx context.Context, providerName string, latency time.Duration)
OnErrorFunc func(ctx context.Context, providerName string, err error)
}
CustomStrategy allows user-defined routing logic
func (*CustomStrategy) OnError ¶
func (s *CustomStrategy) OnError(ctx context.Context, providerName string, err error)
OnError calls the user-provided error callback if defined. Panics are recovered and logged but don't propagate.
func (*CustomStrategy) OnSuccess ¶
OnSuccess calls the user-provided success callback if defined. Panics are recovered and logged but don't propagate.
func (*CustomStrategy) SelectProvider ¶
func (s *CustomStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (providerName string, err error)
SelectProvider executes the user-provided selection function. Panics are recovered and returned as errors.
type FallbackError ¶
type FallbackError struct {
FailedProvider string
AttemptedFallbacks []string
FallbackStrategy string
Err error
}
FallbackError wraps errors that occur during fallback attempts
func (*FallbackError) Error ¶
func (e *FallbackError) Error() string
func (*FallbackError) Unwrap ¶
func (e *FallbackError) Unwrap() error
type FallbackStrategy ¶
type FallbackStrategy interface {
// GetFallbackProvider returns next provider to try after failure
GetFallbackProvider(ctx context.Context, failedProvider string, providers map[string]llms.ChatModel) (string, error)
// ShouldRetry determines if request should be retried
ShouldRetry(err error, attemptCount int) bool
}
FallbackStrategy determines fallback behavior when primary provider fails
type LLMRoutingStrategy ¶
type LLMRoutingStrategy struct {
// contains filtered or unexported fields
}
LLMRoutingStrategy uses an LLM to make routing decisions
func (*LLMRoutingStrategy) OnError ¶
func (s *LLMRoutingStrategy) OnError(ctx context.Context, providerName string, err error)
OnError is a no-op for LLMRoutingStrategy. The LLM makes routing decisions based on request characteristics, not historical performance.
func (*LLMRoutingStrategy) OnSuccess ¶
func (s *LLMRoutingStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
OnSuccess is a no-op for LLMRoutingStrategy. The LLM makes routing decisions based on request characteristics, not historical performance.
func (*LLMRoutingStrategy) SelectProvider ¶
func (s *LLMRoutingStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (string, error)
SelectProvider uses an LLM to analyze the request and select the most appropriate provider. It caches routing decisions for similar requests to minimize LLM calls.
type LoadBalancedStrategy ¶
type LoadBalancedStrategy struct {
// contains filtered or unexported fields
}
LoadBalancedStrategy routes based on current load and latency
func NewLoadBalancedStrategy ¶
func NewLoadBalancedStrategy(metrics *RouterMetrics) *LoadBalancedStrategy
NewLoadBalancedStrategy creates a new LoadBalancedStrategy.
func (*LoadBalancedStrategy) OnError ¶
func (s *LoadBalancedStrategy) OnError(ctx context.Context, providerName string, err error)
OnError is a no-op for LoadBalancedStrategy. Metrics are updated by the router, so no additional action needed.
func (*LoadBalancedStrategy) OnSuccess ¶
func (s *LoadBalancedStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
OnSuccess is a no-op for LoadBalancedStrategy. Metrics are updated by the router, so no additional action needed.
func (*LoadBalancedStrategy) SelectProvider ¶
func (s *LoadBalancedStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (string, error)
SelectProvider returns the provider with the best score. Score is calculated based on latency, error rate, and load.
type NoFallback ¶
type NoFallback struct{}
NoFallback never retries or falls back
func (*NoFallback) GetFallbackProvider ¶
func (n *NoFallback) GetFallbackProvider(ctx context.Context, failedProvider string, providers map[string]llms.ChatModel) (string, error)
GetFallbackProvider always returns an error (no fallback)
func (*NoFallback) ShouldRetry ¶
func (n *NoFallback) ShouldRetry(err error, attemptCount int) bool
ShouldRetry always returns false (never retry)
type ProviderConfig ¶
type ProviderConfig struct {
// Common fields (applicable to all providers)
Model string
Temperature *float64
MaxTokens *int
TopP *float64
Stop []string
// Authentication
APIKey string // Anthropic, OpenAI, GitHub Copilot (Ollama doesn't need auth)
// Base URLs
BaseURL string // Anthropic, OpenAI, Ollama
// Provider-specific fields
ProviderSpecific map[string]any
}
ProviderConfig holds unified configuration for all providers
type ProviderEntry ¶
type ProviderEntry struct {
Name string // Unique identifier (e.g., "fast-openai", "smart-anthropic")
ProviderType ProviderType // Type of provider
Options []ProviderOption // Configuration options
Weight int // Weight for weighted routing (default: 1)
Tags []string // Tags for categorization (e.g., "fast", "cheap", "smart")
}
ProviderEntry defines a provider configuration for the router
type ProviderError ¶
type ProviderError struct {
ProviderType ProviderType
ProviderName string
Operation string
Err error
// Additional context for debugging (never includes sensitive data)
Context map[string]string
}
ProviderError wraps errors with provider context
func (*ProviderError) Error ¶
func (e *ProviderError) Error() string
func (*ProviderError) Unwrap ¶
func (e *ProviderError) Unwrap() error
type ProviderMetrics ¶
type ProviderMetrics struct {
RequestCount int64
ErrorCount int64
CancelledCount int64
TotalLatency time.Duration
LastUsed time.Time
}
ProviderMetrics holds metrics for a single provider
type ProviderOption ¶
type ProviderOption func(*ProviderConfig)
ProviderOption configures the unified provider
func WithAPIKey ¶
func WithAPIKey(apiKey string) ProviderOption
WithAPIKey sets the API key for authentication
func WithAnthropicVersion ¶
func WithAnthropicVersion(version string) ProviderOption
WithAnthropicVersion sets the Anthropic API version
func WithBaseURL ¶
func WithBaseURL(baseURL string) ProviderOption
WithBaseURL sets the base URL for the provider API
func WithCLIPath ¶
func WithCLIPath(cliPath string) ProviderOption
WithCLIPath sets the path to the GitHub Copilot CLI executable
func WithFormat ¶
func WithFormat(format string) ProviderOption
WithFormat sets the response format for Ollama Currently supports "json" for JSON-formatted responses
func WithKeepAlive ¶
func WithKeepAlive(keepAlive string) ProviderOption
WithKeepAlive sets the keep_alive duration for Ollama models Controls how long the model stays loaded in memory Examples: "5m", "10m", "-1" (keep forever), "0" (unload immediately)
func WithLogLevel ¶
func WithLogLevel(logLevel string) ProviderOption
WithLogLevel sets the log level for GitHub Copilot CLI Valid values: "debug", "info", "warn", "error"
func WithMaxTokens ¶
func WithMaxTokens(maxTokens int) ProviderOption
WithMaxTokens sets the maximum number of tokens to generate
func WithModel ¶
func WithModel(model string) ProviderOption
WithModel sets the model name for the provider
func WithNumCtx ¶
func WithNumCtx(numCtx int) ProviderOption
WithNumCtx sets the context window size for Ollama models Determines how many tokens the model can consider
func WithOrganization ¶
func WithOrganization(organization string) ProviderOption
WithOrganization sets the OpenAI organization ID
func WithProviderSpecific ¶
func WithProviderSpecific(key string, value any) ProviderOption
WithProviderSpecific adds a provider-specific configuration option
func WithTemperature ¶
func WithTemperature(temperature float64) ProviderOption
WithTemperature sets the temperature parameter (0.0 to 2.0)
func WithTools ¶
func WithTools(tools ...tools.Tool) ProviderOption
WithTools sets the tools available to GitHub Copilot
func WithTopK ¶
func WithTopK(topK int) ProviderOption
WithTopK sets the top-k sampling parameter for Ollama Limits the next token selection to the K most likely tokens
func WithTopP ¶
func WithTopP(topP float64) ProviderOption
WithTopP sets the top-p sampling parameter (0.0 to 1.0)
type ProviderStats ¶
type ProviderStats struct {
ProviderName string // Name of the provider
RequestCount int64 // Total number of requests
ErrorCount int64 // Total number of errors
CancelledCount int64 // Total number of cancelled requests
SuccessCount int64 // Total number of successful requests
TotalLatency time.Duration // Cumulative latency
AverageLatency time.Duration // Average latency per request
ErrorRate float64 // Error rate (0.0 to 1.0)
CancelledRate float64 // Cancelled rate (0.0 to 1.0)
SuccessRate float64 // Success rate (0.0 to 1.0)
LastUsed time.Time // Last usage timestamp
}
ProviderStats contains computed statistics for a single provider
type ProviderType ¶
type ProviderType string
ProviderType identifies which LLM provider to use
const ( ProviderAnthropic ProviderType = "anthropic" ProviderGitHubCopilot ProviderType = "github-copilot" ProviderOllama ProviderType = "ollama" ProviderOpenAI ProviderType = "openai" )
type RequestContext ¶
type RequestContext struct {
Messages []core.Message
MessageCount int
TotalTokens int // Estimated
HasToolCalls bool
Priority string // "low", "medium", "high"
Complexity string // "simple", "moderate", "complex"
UserMetadata map[string]any
}
RequestContext provides metadata about a request for routing decisions
type RoundRobinStrategy ¶
type RoundRobinStrategy struct {
// contains filtered or unexported fields
}
RoundRobinStrategy distributes requests evenly across providers
func (*RoundRobinStrategy) OnError ¶
func (s *RoundRobinStrategy) OnError(ctx context.Context, providerName string, err error)
OnError is a no-op for RoundRobinStrategy.
func (*RoundRobinStrategy) OnSuccess ¶
func (s *RoundRobinStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
OnSuccess is a no-op for RoundRobinStrategy.
func (*RoundRobinStrategy) SelectProvider ¶
func (s *RoundRobinStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (string, error)
SelectProvider returns providers in round-robin order. The distribution is guaranteed to be even across all providers over time.
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router manages multiple providers and routes requests between them Implements llms.ChatModel interface for transparent usage
func NewRouter ¶
func NewRouter(ctx context.Context, entries []ProviderEntry, strategy RoutingStrategy, opts ...RouterOption) (*Router, error)
NewRouter creates a router that manages multiple providers. It validates that all provider entries have unique names and creates all providers using the factory. If any provider fails to initialize, all successfully created providers are cleaned up before returning an error.
The router implements the llms.ChatModel interface, allowing it to be used transparently in place of a single provider.
Example:
router, err := provider.NewRouter(ctx,
[]provider.ProviderEntry{
{Name: "openai", ProviderType: provider.ProviderOpenAI, Options: []provider.ProviderOption{provider.WithModel("gpt-4o")}},
{Name: "anthropic", ProviderType: provider.ProviderAnthropic, Options: []provider.ProviderOption{provider.WithModel("claude-3-opus")}},
},
&provider.SimpleStrategy{ProviderName: "openai"},
)
if err != nil {
return err
}
defer router.Cleanup()
func (*Router) Batch ¶
func (r *Router) Batch(ctx context.Context, inputs [][]core.Message, opts ...core.Option) ([]*core.AIMessage, error)
Batch implements the core.Runnable interface. It processes multiple message sets in parallel using the routing strategy.
func (*Router) BindTools ¶
func (r *Router) BindTools(tools ...llms.ToolDefinition) llms.ChatModel
BindTools implements the llms.ChatModel interface. It binds tools to all providers managed by the router.
func (*Router) Cleanup ¶
Cleanup releases all resources held by the router and its providers. It calls the cleanup function for every provider it manages.
Cleanup is idempotent - it can be called multiple times safely. If called while requests are in flight, those requests may fail.
Returns the first error encountered during cleanup, but continues cleaning up remaining providers.
func (*Router) Generate ¶
func (r *Router) Generate(ctx context.Context, messages []core.Message, opts ...core.Option) (*llms.ChatResult, error)
Generate implements the llms.ChatModel interface. It selects a provider using the routing strategy and generates a response.
func (*Router) GetMetrics ¶
func (r *Router) GetMetrics() map[string]ProviderMetrics
GetMetrics returns a copy of the current routing metrics. Returns nil if the router has been cleaned up.
func (*Router) GetProvider ¶
GetProvider returns the ChatModel for a specific provider by name. Returns nil if the provider doesn't exist or the router has been cleaned up.
func (*Router) Invoke ¶
func (r *Router) Invoke(ctx context.Context, messages []core.Message, opts ...core.Option) (*core.AIMessage, error)
Invoke implements the core.Runnable interface. It selects a provider using the routing strategy and invokes it.
func (*Router) ListProviders ¶
ListProviders returns the names of all providers managed by this router. Returns nil if the router has been cleaned up.
type RouterConfig ¶
type RouterConfig struct {
FallbackStrategy FallbackStrategy
EnableMetrics bool
MaxRetries int
RetryDelay time.Duration
}
RouterConfig holds router configuration
type RouterMetrics ¶
type RouterMetrics struct {
RequestCount map[string]int64 // Requests per provider
ErrorCount map[string]int64 // Errors per provider
CancelledCount map[string]int64 // Cancelled streams per provider
TotalLatency map[string]time.Duration // Total latency per provider
LastUsed map[string]time.Time // Last usage timestamp
// contains filtered or unexported fields
}
RouterMetrics tracks routing statistics
func (*RouterMetrics) GetAllStats ¶
func (m *RouterMetrics) GetAllStats() map[string]*ProviderStats
GetAllStats returns computed statistics for all providers. Returns an empty map if no providers have been tracked.
func (*RouterMetrics) GetStats ¶
func (m *RouterMetrics) GetStats(providerName string) *ProviderStats
GetStats returns computed statistics for a specific provider. Returns nil if the provider doesn't exist in the metrics.
func (*RouterMetrics) Reset ¶
func (m *RouterMetrics) Reset(providerName string)
Reset clears all metrics for a specific provider. This is useful for resetting statistics without recreating the router.
func (*RouterMetrics) ResetAll ¶
func (m *RouterMetrics) ResetAll()
ResetAll clears all metrics for all providers.
type RoutingError ¶
type RoutingError struct {
Strategy string
AvailableProviders []string
RequestComplexity string
Err error
}
RoutingError wraps errors that occur during request routing
func (*RoutingError) Error ¶
func (e *RoutingError) Error() string
func (*RoutingError) Unwrap ¶
func (e *RoutingError) Unwrap() error
type RoutingRule ¶
type RoutingRule struct {
Name string
Condition func(RequestContext) bool
Provider string
Priority int // Higher priority rules evaluated first
}
RoutingRule defines a condition and target provider
type RoutingStrategy ¶
type RoutingStrategy interface {
// SelectProvider chooses a provider for the given request
SelectProvider(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (string, error)
// OnSuccess is called after a successful request
OnSuccess(ctx context.Context, providerName string, latency time.Duration)
// OnError is called after a failed request
OnError(ctx context.Context, providerName string, err error)
}
RoutingStrategy determines which provider to use for a request
type RuleBasedStrategy ¶
type RuleBasedStrategy struct {
// contains filtered or unexported fields
}
RuleBasedStrategy routes based on request characteristics
func NewRuleBasedStrategy ¶
func NewRuleBasedStrategy(rules []RoutingRule, defaultProvider string) *RuleBasedStrategy
NewRuleBasedStrategy creates a new RuleBasedStrategy. Rules are automatically sorted by priority (highest first).
func (*RuleBasedStrategy) AddRule ¶
func (s *RuleBasedStrategy) AddRule(rule RoutingRule)
AddRule adds a new rule to the strategy. Rules are automatically re-sorted by priority.
func (*RuleBasedStrategy) GetRules ¶
func (s *RuleBasedStrategy) GetRules() []RoutingRule
GetRules returns a copy of all rules.
func (*RuleBasedStrategy) OnError ¶
func (s *RuleBasedStrategy) OnError(ctx context.Context, providerName string, err error)
OnError is a no-op for RuleBasedStrategy.
func (*RuleBasedStrategy) OnSuccess ¶
func (s *RuleBasedStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
OnSuccess is a no-op for RuleBasedStrategy.
func (*RuleBasedStrategy) RemoveRule ¶
func (s *RuleBasedStrategy) RemoveRule(name string)
RemoveRule removes a rule by name.
func (*RuleBasedStrategy) SelectProvider ¶
func (s *RuleBasedStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (string, error)
SelectProvider evaluates rules in priority order and returns the first match. If no rules match, returns the default provider.
type SequentialFallback ¶
type SequentialFallback struct {
Order []string
}
SequentialFallback tries providers in order
func (*SequentialFallback) GetFallbackProvider ¶
func (s *SequentialFallback) GetFallbackProvider(ctx context.Context, failedProvider string, providers map[string]llms.ChatModel) (string, error)
GetFallbackProvider returns the next provider in the configured order Never returns the failed provider
func (*SequentialFallback) ShouldRetry ¶
func (s *SequentialFallback) ShouldRetry(err error, attemptCount int) bool
ShouldRetry returns true if there are more providers to try
type SimpleStrategy ¶
type SimpleStrategy struct {
ProviderName string
}
SimpleStrategy always routes to a specific provider
func (*SimpleStrategy) OnError ¶
func (s *SimpleStrategy) OnError(ctx context.Context, providerName string, err error)
OnError is a no-op for SimpleStrategy.
func (*SimpleStrategy) SelectProvider ¶
func (s *SimpleStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (string, error)
SelectProvider returns the configured provider name.
type SmartFallback ¶
type SmartFallback struct {
// contains filtered or unexported fields
}
SmartFallback uses metrics to choose best fallback
func (*SmartFallback) GetFallbackProvider ¶
func (s *SmartFallback) GetFallbackProvider(ctx context.Context, failedProvider string, providers map[string]llms.ChatModel) (string, error)
GetFallbackProvider selects the best alternative provider based on metrics Never returns the failed provider
func (*SmartFallback) ShouldRetry ¶
func (s *SmartFallback) ShouldRetry(err error, attemptCount int) bool
ShouldRetry returns true if the error is retryable and attempt count is reasonable
type ValidationError ¶
ValidationError represents a configuration validation error
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
type WeightedStrategy ¶
type WeightedStrategy struct {
// contains filtered or unexported fields
}
WeightedStrategy routes based on provider weights
func NewWeightedStrategy ¶
func NewWeightedStrategy(weights map[string]int) *WeightedStrategy
NewWeightedStrategy creates a new WeightedStrategy with the given weights. If a provider is not in the weights map, it defaults to weight 1.
func (*WeightedStrategy) GetWeight ¶
func (s *WeightedStrategy) GetWeight(providerName string) int
GetWeight returns the weight for a provider.
func (*WeightedStrategy) OnError ¶
func (s *WeightedStrategy) OnError(ctx context.Context, providerName string, err error)
OnError is a no-op for WeightedStrategy.
func (*WeightedStrategy) OnSuccess ¶
func (s *WeightedStrategy) OnSuccess(ctx context.Context, providerName string, latency time.Duration)
OnSuccess is a no-op for WeightedStrategy.
func (*WeightedStrategy) SelectProvider ¶
func (s *WeightedStrategy) SelectProvider(ctx context.Context, reqCtx RequestContext, providers map[string]llms.ChatModel) (string, error)
SelectProvider returns a provider based on weighted random selection. The probability of selecting a provider is proportional to its weight.
func (*WeightedStrategy) SetWeight ¶
func (s *WeightedStrategy) SetWeight(providerName string, weight int)
SetWeight updates the weight for a provider. This allows dynamic adjustment of routing weights.