-
-
Notifications
You must be signed in to change notification settings - Fork 13
Model Configuration Spec
This document defines the model configuration system for dartantic 1.0, including model string formats, naming conventions, and provider defaults.
The ModelStringParser supports flexible URI-based parsing with multiple formats for backward compatibility:
| Format | Example | Parsed Result |
|---|---|---|
| Provider only | openai |
provider: openai, chat: null, embeddings: null, media: null
|
| Provider:model | openai:gpt-4o |
provider: openai, chat: gpt-4o, embeddings: null, media: null
|
| Provider/model | openai/gpt-4o |
provider: openai, chat: gpt-4o, embeddings: null, media: null
|
| Query params | openai?chat=gpt-4o&embeddings=text-embedding-3 |
provider: openai, chat: gpt-4o, embeddings: text-embedding-3, media: null
|
| Media query | openai?media=gpt-image-1 |
provider: openai, chat: null, embeddings: null, media: gpt-image-1
|
| All selectors | openai?chat=gpt-4o&embeddings=text-embedding-3&media=gpt-image-1 |
provider: openai, chat: gpt-4o, embeddings: text-embedding-3, media: gpt-image-1
|
flowchart TD
A[/"Input: 'openai?chat=gpt-4&embeddings=ada'"/] --> B{Try URI Parsing}
B -->|Success| C[Parse URI Format]
B -->|Failure| D[Fallback Parser<br/>slash splitting]
C --> E[Extract Components]
E --> F[provider: openai]
E --> G[chat: gpt-4]
E --> H[embeddings: ada]
F --> J[/ModelStringParser<br/>providerName: 'openai'<br/>chatModelName: 'gpt-4'<br/>embeddingsModelName: 'ada'/]
G --> J
H --> J
style A fill:#f9f,stroke:#333,stroke-width:2px
style J fill:#9f9,stroke:#333,stroke-width:2px
factory ModelStringParser.parse(String model) {
final uri = Uri.tryParse(model);
if (uri != null) {
// Handles all formats elegantly using Uri parsing
// - Absolute URIs: provider:model (colon becomes scheme separator)
// - Relative URIs: provider, provider/model, or provider?params
}
// Fallback for edge cases
}The parser can also build model strings using toString():
- Provider only →
"openai" - Chat model only →
"openai:gpt-4"(uses colon format) - Multiple models →
"openai?chat=gpt-4&embeddings=ada&media=gpt-image-1"(uses query format)
Each provider defines default models for chat, embeddings, and optionally media operations:
flowchart TD
A[/"Agent('openai?chat=gpt-4')"/] --> B[Parse Model String]
B --> C["provider: 'openai'<br/>chat: 'gpt-4'<br/>embeddings: null"]
C --> D[Provider Lookup]
D --> E["Providers.get('openai')"]
E --> F["defaultModelNames:<br/>chat: 'gpt-4o'<br/>embeddings: 'text-embedding-3-small'"]
F --> G{Model Resolution}
G -->|Chat specified| H["Chat: use 'gpt-4'"]
G -->|Embeddings null| I["Embeddings: use default<br/>'text-embedding-3-small'"]
H --> J[Create Chat Model]
I --> K[Create Embeddings Model]
J --> L[/"Agent ready with:<br/>Chat: gpt-4<br/>Embeddings: text-embedding-3-small"/]
K --> L
style A fill:#f9f,stroke:#333,stroke-width:2px
style J fill:#9f9,stroke:#333,stroke-width:2px
Media selectors follow the same precedence rules—if ModelKind.media has a
default configured by the provider, the agent will use it whenever the model
string omits an explicit media= query parameter.
| Provider | Chat Default | Embeddings Default | Media Default |
|---|---|---|---|
| OpenAI | gpt-4o |
text-embedding-3-small |
N/A |
| OpenAI Responses | gpt-4o |
text-embedding-3-small |
gpt-4o |
| Anthropic | claude-sonnet-4-0 |
N/A (no embeddings) | N/A |
gemini-2.0-flash |
models/text-embedding-004 |
N/A | |
| Mistral | mistral-7b-instruct |
mistral-embed |
N/A |
| Cohere | command-r-plus |
embed-v4.0 |
N/A |
| Ollama | llama3.2 |
N/A (no embeddings) | N/A |
| OpenRouter | google/gemini-2.0-flash |
N/A (chat only) | N/A |
| Together | meta-llama/Llama-3.2-3B-Instruct-Turbo |
N/A (chat only) | N/A |
abstract class Provider {
final Map<ModelKind, String> defaultModelNames;
// Example provider with both chat and embeddings
static final openai = OpenAIProvider(
name: 'openai',
displayName: 'OpenAI',
defaultModelNames: {
ModelKind.chat: 'gpt-4o',
ModelKind.embeddings: 'text-embedding-3-small',
// Optional: ModelKind.media: 'gpt-image-1',
},
apiKeyName: 'OPENAI_API_KEY',
// Use Provider.listModels() for runtime capability discovery
);
}All models use consistent parameter naming across the codebase:
// Chat models
ChatModel({
required this.name, // Always 'name', not 'model' or 'modelId'
required this.defaultOptions,
this.tools,
this.temperature,
});
// Embeddings models
EmbeddingsModel({
required this.name, // Same convention
required this.defaultOptions,
this.dimensions,
this.batchSize,
});This consistency ensures:
- Easy refactoring and searching
- Clear API surface
- No confusion between
model,modelId,modelName, etc.
// Uses provider defaults for both chat and embeddings
final agent = Agent('openai');
// Chat: gpt-4o, Embeddings: text-embedding-3-small// Overrides chat model, uses default embeddings
final agent = Agent('openai:gpt-4o');
// or
final agent = Agent('openai/gpt-4o');
// Chat: gpt-4o, Embeddings: text-embedding-3-small// Explicit models for both operations
final agent = Agent('openai?chat=gpt-4o&embeddings=text-embedding-3-large');
// Chat: gpt-4o, Embeddings: text-embedding-3-largefinal provider = Providers.openai;
final chatModel = provider.createChatModel(name: 'gpt-4o');
final embeddingsModel = provider.createEmbeddingsModel(); // Uses defaultfinal provider = OpenAIProvider(
apiKey: 'sk-custom',
baseUrl: Uri.parse('https://proxy.com/v1'),
defaultModelNames: {
ModelKind.chat: 'gpt-4o',
ModelKind.embeddings: 'text-embedding-3-large',
},
);
final agent = Agent.forProvider(provider);-
Provider name lookup (case-insensitive)
-
Agent('OpenAI')→ findsopenaiprovider
-
-
Alias resolution
-
Agent('claude')→ resolves toanthropicprovider
-
-
Model defaults from
provider.defaultModelNames[ModelKind]- Used when no explicit model specified
-
Explicit model names override defaults
-
Agent('openai:gpt-4')overrides chat default
-
-
openai- Provider only, uses all defaults -
openai:gpt-4- Explicit chat model -
openai/gpt-4- Alternative syntax for chat model -
openai?chat=gpt-4&embeddings=ada- Explicit both models -
google?embeddings=models/text-embedding-004- Embeddings only
- Empty string → throws
Exception('Invalid model string format: ""') - Invalid format → throws parsing exception
- Providers without embeddings support throw
UnsupportedErrorwhen embeddings methods are called - Custom models override defaults only for specified types
-
Agent.forProviderallows direct provider instance usage with optional model overrides
The Agent.model property returns a fully-qualified model string that can be used to reconstruct an equivalent Agent configuration. This is a critical invariant:
final agent1 = Agent.forProvider(provider);
final modelString = agent1.model;
// Round-trip: creating a new Agent from the model string produces equivalent config
final agent2 = Agent(modelString);
assert(agent2.model == agent1.model);The Agent.model getter constructs the model string by:
- Using explicit model names if provided during Agent creation
- Falling back to provider defaults for any unspecified model types
- Including all three model types (chat, embeddings, media) when the provider has defaults
For providers with all three model type defaults, Agent.model produces:
openai?chat=gpt-4o&embeddings=text-embedding-3-small&media=dall-e-3
For providers with only chat and embeddings:
openai?chat=gpt-4o&embeddings=text-embedding-3-small
For providers with only chat (or when only chat is specified):
openai:gpt-4o
- Serialization: Model strings can be stored and used to recreate agents
- Display: UI can show the complete configuration to users
- Debugging: Easy to see exactly what models an Agent is configured to use
- Cloning: Create equivalent agents from the model string
- Simplicity: URI parsing handles all formats cleanly
-
Consistency: All models use
nameparameter - Flexibility: Support both simple and complex configurations
- Type Safety: Separate chat and embeddings model creation
-
Backwards Compatibility: Legacy
provider:modelformat still works - Extensibility: Query format allows future model types
-
Round-Trip:
Agent.modelproduces strings that reconstruct equivalent agents
- API Key Resolution: See Agent-Config-Spec
- Provider Architecture: See Unified-Provider-Architecture