Provider & Model Management
This page adapts the original AI SDK documentation: Provider & Model Management.
When you work with multiple providers and models, it is often desirable to manage them in a central place and access the models through simple string ids.
The AI SDK offers custom providers and a provider registry for this purpose:
- With custom providers, you can pre-configure model settings, provide model name aliases, and limit the available models.
- The provider registry lets you mix multiple providers and access them through simple string ids.
You can mix and match custom providers, the provider registry, and middleware in your application.
Custom Providers
Section titled “Custom Providers”You can create a custom provider using customProvider.
Example: Custom Model Settings
Section titled “Example: Custom Model Settings”You might want to override the default model settings for a provider or provide model name aliases with pre-configured settings.
import SwiftAISDKimport OpenAIProvider
// Custom provider with different provider options:let customOpenAI = customProvider( languageModels: [ // Replacement model with custom provider options: "gpt-4o": wrapLanguageModel( model: openai.languageModel(modelId: "gpt-4o"), middleware: .single(defaultSettingsMiddleware( settings: DefaultSettings( providerOptions: ["openai": [ "reasoningEffort": "high" ]] ) )) ), // Alias model with custom provider options: "gpt-4o-mini-high-reasoning": wrapLanguageModel( model: openai.languageModel(modelId: "gpt-4o-mini"), middleware: .single(defaultSettingsMiddleware( settings: DefaultSettings( providerOptions: ["openai": [ "reasoningEffort": "high" ]] ) )) ) ], fallbackProvider: openai)Example: Model Name Alias
Section titled “Example: Model Name Alias”You can also provide model name aliases, so you can update the model version in one place in the future:
import SwiftAISDKimport AnthropicProvider
// Custom provider with alias names:let customAnthropic = customProvider( languageModels: [ "opus": anthropic.languageModel(modelId: "claude-3-opus-20240229"), "sonnet": anthropic.languageModel(modelId: "claude-3-5-sonnet-20240620"), "haiku": anthropic.languageModel(modelId: "claude-3-haiku-20240307") ], fallbackProvider: anthropic)Example: Limit Available Models
Section titled “Example: Limit Available Models”You can limit the available models in the system, even if you have multiple providers.
import SwiftAISDKimport AnthropicProviderimport OpenAIProvider
let myProvider = customProvider( languageModels: [ "text-medium": anthropic.languageModel(modelId: "claude-3-5-sonnet-20240620"), "text-small": openai.languageModel(modelId: "gpt-4o-mini"), "reasoning-medium": wrapLanguageModel( model: openai.languageModel(modelId: "gpt-4o"), middleware: .single(defaultSettingsMiddleware( settings: DefaultSettings( providerOptions: ["openai": [ "reasoningEffort": "high" ]] ) )) ), "reasoning-fast": wrapLanguageModel( model: openai.languageModel(modelId: "gpt-4o-mini"), middleware: .single(defaultSettingsMiddleware( settings: DefaultSettings( providerOptions: ["openai": [ "reasoningEffort": "high" ]] ) )) ) ], textEmbeddingModels: [ "embedding": openai.textEmbeddingModel(modelId: "text-embedding-3-small") ] // No fallback provider)Provider Registry
Section titled “Provider Registry”You can create a provider registry with multiple providers and models using createProviderRegistry.
import SwiftAISDKimport AnthropicProviderimport OpenAIProvider
let registry = createProviderRegistry( providers: [ // Register provider with prefix: "anthropic": anthropic,
// Register provider with custom configuration: "openai": createOpenAI( apiKey: ProcessInfo.processInfo.environment["OPENAI_API_KEY"] ) ])Setup with Custom Separator
Section titled “Setup with Custom Separator”By default, the registry uses : as the separator between provider and model IDs. You can customize this separator:
import SwiftAISDKimport AnthropicProviderimport OpenAIProvider
let customSeparatorRegistry = createProviderRegistry( providers: [ "anthropic": anthropic, "openai": openai ], options: ProviderRegistryOptions(separator: " > "))Example: Use Language Models
Section titled “Example: Use Language Models”You can access language models by using the languageModel method on the registry.
The provider id will become the prefix of the model id: providerId:modelId.
import SwiftAISDK
let result = try await generateText( model: registry.languageModel(id: "openai:gpt-4o"), // default separator // or with custom separator: // model: customSeparatorRegistry.languageModel(id: "openai > gpt-4o"), prompt: "Invent a new holiday and describe its traditions.")Example: Use Text Embedding Models
Section titled “Example: Use Text Embedding Models”You can access text embedding models by using the textEmbeddingModel method on the registry.
The provider id will become the prefix of the model id: providerId:modelId.
import SwiftAISDK
let result = try await embed( model: .v3(registry.textEmbeddingModel(id: "openai:text-embedding-3-small")), value: "sunny day at the beach")Example: Use Image Models
Section titled “Example: Use Image Models”You can access image models by using the imageModel method on the registry.
The provider id will become the prefix of the model id: providerId:modelId.
import SwiftAISDK
let result = try await generateImage( model: registry.imageModel(id: "openai:dall-e-3"), prompt: "A beautiful sunset over a calm ocean")Combining Custom Providers, Provider Registry, and Middleware
Section titled “Combining Custom Providers, Provider Registry, and Middleware”The central idea of provider management is to set up a file that contains all the providers and models you want to use. You may want to pre-configure model settings, provide model name aliases, limit the available models, and more.
Here is an example that implements the following concepts:
- Pass through a full provider with a namespace prefix (here:
xai > *) - Setup model name aliases (here:
anthropic > fast,anthropic > writing,anthropic > reasoning) - Pre-configure model settings (here:
anthropic > reasoning) - Use a fallback provider (here:
anthropic > *) - Limit a provider to certain models without a fallback (here:
groq > gemma2-9b-it,groq > qwen-qwq-32b) - Define a custom separator for the provider registry (here:
>)
import SwiftAISDKimport AnthropicProviderimport XAIProviderimport GroqProvider
let registry = createProviderRegistry( providers: [ // Pass through a full provider with a namespace prefix "xai": xai,
// Setup model name aliases "anthropic": customProvider( languageModels: [ "fast": anthropic.languageModel(modelId: "claude-3-haiku-20240307"),
// Simple model "writing": anthropic.languageModel(modelId: "claude-3-7-sonnet-20250219"),
// Extended reasoning model configuration: "reasoning": wrapLanguageModel( model: anthropic.languageModel(modelId: "claude-3-7-sonnet-20250219"), middleware: .single(defaultSettingsMiddleware( settings: DefaultSettings( maxOutputTokens: 100000, // example default setting providerOptions: ["anthropic": [ "thinking": [ "type": "enabled", "budgetTokens": 32000 ] ]] ) )) ) ], fallbackProvider: anthropic ),
// Limit a provider to certain models without a fallback "groq": customProvider( languageModels: [ "gemma2-9b-it": groq.languageModel(modelId: "gemma2-9b-it"), "qwen-qwq-32b": groq.languageModel(modelId: "qwen-qwq-32b") ] ) ], options: ProviderRegistryOptions(separator: " > "))
// Usage:let model = registry.languageModel(id: "anthropic > reasoning")Registry with Middleware
Section titled “Registry with Middleware”You can apply middleware to all language models accessed through the registry:
import SwiftAISDKimport OpenAIProvider
let registry = createProviderRegistry( providers: [ "openai": openai ], options: ProviderRegistryOptions( languageModelMiddleware: .single( extractReasoningMiddleware( options: ExtractReasoningOptions(tagName: "think") ) ) ))
// All language models from this registry will have reasoning extraction enabledlet result = try await generateText( model: registry.languageModel(id: "openai:gpt-4o"), prompt: "Think step by step and wrap reasoning in <think> tags")Best Practices
Section titled “Best Practices”- Create a central registry file - Define all providers and models in one place (e.g.,
Registry.swift) - Use aliases for versioning - Map semantic names to specific model versions for easy updates
- Combine with middleware - Pre-configure models with default settings or behavior modifications
- Limit model access - Use custom providers without fallbacks to restrict available models
- Use custom separators - Choose separators that match your naming conventions (
:,>,/, etc.)