Provider Registry
The provider registry allows you to register and access AI providers globally.
Registry Functions
The package-level functions operate on a shared global registry:
// Register a provider in the global registry
func RegisterProvider(name string, p provider.Provider)
// Get a registered provider from the global registry
func GetProvider(name string) (provider.Provider, error)
// Resolve a "provider:model" string directly to a model, using the global registry
func ResolveLanguageModel(model string) (provider.LanguageModel, error)
func ResolveEmbeddingModel(model string) (provider.EmbeddingModel, error)
func ResolveImageModel(model string) (provider.ImageModel, error)
func ResolveSpeechModel(model string) (provider.SpeechModel, error)
func ResolveTranscriptionModel(model string) (provider.TranscriptionModel, error)
func ResolveRerankingModel(model string) (provider.RerankingModel, error)
// GetGlobalRegistry returns the shared *Registry instance the above functions use
func GetGlobalRegistry() *Registry
NoSuchProviderError is returned when a provider ID can't be resolved or
doesn't support the requested model type:
type NoSuchProviderError struct {
ProviderID string
ModelID string
ModelType string
AvailableProviders []string
Reason string
}
Registry Type
For an isolated registry (instead of the shared global one), use NewRegistry:
func NewRegistry(opts ...RegistryOption) *Registry
func WithSeparator(separator string) RegistryOption // default ":"
func WithLanguageModelMiddleware(mw ...*middleware.LanguageModelMiddleware) RegistryOption
func WithImageModelMiddleware(mw ...*middleware.ImageModelMiddleware) RegistryOption
*Registry exposes the same operations as methods: RegisterProvider,
GetProvider, ListProviders, ResolveLanguageModel,
ResolveEmbeddingModel, ResolveImageModel, ResolveSpeechModel,
ResolveTranscriptionModel, ResolveRerankingModel, plus alias and tool
helpers (RegisterAlias, ListAliases, RegisterTool, LookupTool,
ListTools).
Examples
Registering Providers
package main
import (
"github.com/digitallysavvy/go-ai/pkg/providers/anthropic"
"github.com/digitallysavvy/go-ai/pkg/providers/openai"
"github.com/digitallysavvy/go-ai/pkg/registry"
)
func main() {
// Register OpenAI
registry.RegisterProvider("openai", openai.New(openai.Config{
APIKey: "openai-key",
}))
// Register Anthropic
registry.RegisterProvider("anthropic", anthropic.New(anthropic.Config{
APIKey: "anthropic-key",
}))
}
Getting Providers
// Get a provider by name
p, err := registry.GetProvider("openai")
if err != nil {
log.Fatal(err)
}
// Get a model
model, err := p.LanguageModel("gpt-4")
if err != nil {
log.Fatal(err)
}
Resolving a "provider:model" String Directly
// Equivalent to GetProvider("openai") then LanguageModel("gpt-4")
model, err := registry.ResolveLanguageModel("openai:gpt-4")
if err != nil {
log.Fatal(err)
}
Listing Registered Providers
providers := registry.GetGlobalRegistry().ListProviders()
fmt.Println("Available providers:")
for _, name := range providers {
fmt.Printf(" - %s\n", name)
}
Checking Provider Existence
There's no dedicated Has-style check; call GetProvider and inspect the error:
if _, err := registry.GetProvider("openai"); err == nil {
fmt.Println("OpenAI is registered")
}
Using with Configuration
type Config struct {
ProviderName string
ModelID string
}
func getModel(cfg Config) (provider.LanguageModel, error) {
p, err := registry.GetProvider(cfg.ProviderName)
if err != nil {
return nil, fmt.Errorf("provider not found: %w", err)
}
model, err := p.LanguageModel(cfg.ModelID)
if err != nil {
return nil, fmt.Errorf("model not found: %w", err)
}
return model, nil
}
// Usage
config := Config{
ProviderName: "openai",
ModelID: "gpt-4",
}
model, err := getModel(config)
if err != nil {
log.Fatal(err)
}
Dynamic Provider Selection
func generateWithProvider(providerName, modelID, prompt string) (string, error) {
// Get provider from registry
p, err := registry.GetProvider(providerName)
if err != nil {
return "", fmt.Errorf("provider %s not found: %w", providerName, err)
}
// Get model
model, err := p.LanguageModel(modelID)
if err != nil {
return "", fmt.Errorf("model %s not found: %w", modelID, err)
}
// Generate
result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: prompt,
})
if err != nil {
return "", err
}
return result.Text, nil
}
// Usage
text, err := generateWithProvider("openai", "gpt-4", "Hello!")
Multi-Provider Setup
func setupProviders(config map[string]string) error {
providers := map[string]provider.Provider{
"openai": openai.New(openai.Config{
APIKey: config["openai_key"],
}),
"anthropic": anthropic.New(anthropic.Config{
APIKey: config["anthropic_key"],
}),
"google": google.New(google.Config{
APIKey: config["google_key"],
}),
}
for name, p := range providers {
registry.RegisterProvider(name, p)
}
return nil
}
// Usage
config := map[string]string{
"openai_key": os.Getenv("OPENAI_API_KEY"),
"anthropic_key": os.Getenv("ANTHROPIC_API_KEY"),
"google_key": os.Getenv("GOOGLE_GENERATIVE_AI_API_KEY"),
}
if err := setupProviders(config); err != nil {
log.Fatal(err)
}
Provider Fallback
func generateWithFallback(modelConfigs []struct{ Provider, Model string }, prompt string) (string, error) {
var lastErr error
for _, cfg := range modelConfigs {
p, err := registry.GetProvider(cfg.Provider)
if err != nil {
lastErr = err
continue
}
model, err := p.LanguageModel(cfg.Model)
if err != nil {
lastErr = err
continue
}
result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: prompt,
})
if err != nil {
lastErr = err
continue
}
return result.Text, nil
}
return "", fmt.Errorf("all providers failed: %w", lastErr)
}
// Usage with fallback chain
configs := []struct{ Provider, Model string }{
{"openai", "gpt-4"},
{"anthropic", "claude-3-opus"},
{"google", "gemini-pro"},
}
text, err := generateWithFallback(configs, "Hello!")
Error Handling
_, err := registry.GetProvider("unknown")
if err != nil {
var notFound *registry.NoSuchProviderError
if errors.As(err, ¬Found) {
log.Printf("Provider %q is not registered (available: %v)", notFound.ProviderID, notFound.AvailableProviders)
} else {
log.Fatal("Registry error:", err)
}
}
See Also
- Custom Provider - Implementing custom providers
- LanguageModel Interface - Language model interface
- Provider Guide - Provider overview