Models Module¶
File: src/selectools/models.py
Classes: ModelInfo
Constants: ALL_MODELS, MODELS_BY_ID, OpenAI, Anthropic, Gemini, Ollama, Cohere
Table of Contents¶
Overview¶
The Models module provides a single source of truth for all supported LLM and embedding models. It includes:
- 152 models across 5 providers
- Pricing per 1M tokens
- Context windows
- Max output tokens
- Type-safe constants with IDE autocomplete
Why a Model Registry?¶
Before:
# ❌ Error-prone
provider = OpenAIProvider(default_model="gpt-4o-mini") # Typo?
# ❌ No pricing info
# ❌ No autocomplete
After:
# ✅ Type-safe with autocomplete
from selectools.models import OpenAI
provider = OpenAIProvider(default_model=OpenAI.GPT_4O_MINI.id)
# ✅ Access metadata
model = OpenAI.GPT_4O_MINI
print(f"Cost: ${model.prompt_cost}/${model.completion_cost} per 1M tokens")
print(f"Context: {model.context_window:,} tokens")
Model Registry System¶
ModelInfo Dataclass¶
@dataclass(frozen=True)
class ModelInfo:
id: str # Model identifier (e.g., "gpt-4o")
provider: str # "openai", "anthropic", "gemini", "ollama"
type: ModelType # "chat", "embedding", "image", "audio"
prompt_cost: float # USD per 1M input tokens
completion_cost: float # USD per 1M output tokens
max_tokens: int # Maximum output tokens
context_window: int # Maximum context length
Registry Structure¶
# Typed model constants
OpenAI.GPT_4O # ModelInfo instance
Anthropic.SONNET_3_5 # ModelInfo instance
Gemini.FLASH_2_0 # ModelInfo instance
# Complete list
ALL_MODELS # List[ModelInfo] - all 152 models
# Quick lookup
MODELS_BY_ID # Dict[str, ModelInfo] - O(1) lookup
Model Classes¶
OpenAI Models (77 models)¶
from selectools.models import OpenAI
# GPT-5.4 Series (Latest Flagship — 1.05M context)
OpenAI.GPT_5_4 # $2.50 / $15.00 per 1M tokens
OpenAI.GPT_5_4_PRO # $30.00 / $180.00 per 1M tokens
# GPT-5.x Series
OpenAI.GPT_5_2 # $1.75 / $14.00 per 1M tokens
OpenAI.GPT_5_1 # $1.25 / $10.00 per 1M tokens
OpenAI.GPT_5_MINI # $0.25 / $2.00 per 1M tokens
OpenAI.GPT_5_NANO # $0.05 / $0.40 per 1M tokens
# GPT-4.1 Series (1M context)
OpenAI.GPT_4_1 # $2.00 / $8.00 per 1M tokens
OpenAI.GPT_4_1_MINI # $0.40 / $1.60 per 1M tokens
OpenAI.GPT_4_1_NANO # $0.10 / $0.40 per 1M tokens
# GPT-4o Series
OpenAI.GPT_4O # $2.50 / $10.00 per 1M tokens
OpenAI.GPT_4O_MINI # $0.15 / $0.60 per 1M tokens ⭐ Best value
# o-series (Reasoning)
OpenAI.O3_PRO # $20.00 / $80.00 per 1M tokens
OpenAI.O3 # $2.00 / $8.00 per 1M tokens
OpenAI.O4_MINI # $1.10 / $4.40 per 1M tokens
OpenAI.O1 # $15.00 / $60.00 per 1M tokens
# Embeddings
OpenAI.Embeddings.TEXT_EMBEDDING_3_SMALL # $0.02 per 1M tokens ⭐
OpenAI.Embeddings.TEXT_EMBEDDING_3_LARGE # $0.13 per 1M tokens
OpenAI.Embeddings.ADA_002 # $0.10 per 1M tokens
Anthropic Models (22 models)¶
from selectools.models import Anthropic
# Claude 4.6 Series (Latest)
Anthropic.OPUS_4_6 # $5.00 / $25.00 per 1M tokens
Anthropic.SONNET_4_6 # $3.00 / $15.00 per 1M tokens
# Claude 4.5 Series
Anthropic.OPUS_4_5 # $5.00 / $25.00 per 1M tokens
Anthropic.SONNET_4_5 # $3.00 / $15.00 per 1M tokens
Anthropic.HAIKU_4_5 # $1.00 / $5.00 per 1M tokens
# Claude 3.5 Series
Anthropic.SONNET_3_5_20241022 # $3.00 / $15.00 per 1M tokens
Anthropic.HAIKU_3_5_20241022 # $0.80 / $4.00 per 1M tokens
# Embeddings (Voyage AI)
Anthropic.Embeddings.VOYAGE_3 # $0.06 per 1M tokens
Anthropic.Embeddings.VOYAGE_3_LITE # $0.02 per 1M tokens
Gemini Models (30 models)¶
from selectools.models import Gemini
# Gemini 3.1 Series (Latest)
Gemini.PRO_3_1 # $2.00 / $12.00 per 1M tokens (1M context)
Gemini.FLASH_LITE_3_1 # $0.25 / $1.50 per 1M tokens
# Gemini 3 Series
Gemini.PRO_3 # $2.00 / $12.00 per 1M tokens (2M context)
Gemini.FLASH_3_PREVIEW # $0.50 / $3.00 per 1M tokens
# Gemini 2.5 Series
Gemini.PRO_2_5 # $1.25 / $10.00 per 1M tokens
Gemini.FLASH_2_5 # $0.30 / $2.50 per 1M tokens
Gemini.FLASH_LITE_2_5 # $0.10 / $0.40 per 1M tokens
# Gemini 2.0 Series
Gemini.FLASH_2_0 # $0.10 / $0.40 per 1M tokens ⭐ Great value
# Embeddings
Gemini.Embeddings.EMBEDDING_004 # FREE ⭐⭐⭐
Gemini.Embeddings.EMBEDDING_001 # FREE
Ollama Models (13 models)¶
from selectools.models import Ollama
# All FREE (local execution)
Ollama.LLAMA_3_2 # Local, FREE
Ollama.LLAMA_3_1 # Local, FREE
Ollama.MISTRAL # Local, FREE
Ollama.CODELLAMA # Local, FREE ⭐ For coding
Ollama.PHI # Local, FREE
Cohere Models (3 models)¶
from selectools.models import Cohere
# Embeddings only
Cohere.Embeddings.EMBED_V3 # $0.10 per 1M tokens
Cohere.Embeddings.EMBED_MULTILINGUAL_V3 # $0.10 per 1M tokens ⭐ 100+ languages
Cohere.Embeddings.EMBED_V3_LIGHT # $0.10 per 1M tokens
Usage Patterns¶
With Providers¶
from selectools import OpenAIProvider, AnthropicProvider, GeminiProvider
from selectools.models import OpenAI, Anthropic, Gemini
# OpenAI
provider = OpenAIProvider(default_model=OpenAI.GPT_4O_MINI.id)
# Anthropic
provider = AnthropicProvider(default_model=Anthropic.SONNET_3_5_20241022.id)
# Gemini
provider = GeminiProvider(default_model=Gemini.FLASH_2_0.id)
With Agent Config¶
from selectools import Agent, AgentConfig
from selectools.models import OpenAI
config = AgentConfig(
model=OpenAI.GPT_4O_MINI.id,
temperature=0.0,
max_tokens=OpenAI.GPT_4O_MINI.max_tokens
)
agent = Agent(tools=[...], provider=provider, config=config)
Accessing Model Metadata¶
from selectools.models import OpenAI
model = OpenAI.GPT_4O_MINI
print(f"Model ID: {model.id}")
print(f"Provider: {model.provider}")
print(f"Type: {model.type}")
print(f"Prompt cost: ${model.prompt_cost} per 1M tokens")
print(f"Completion cost: ${model.completion_cost} per 1M tokens")
print(f"Max output: {model.max_tokens:,} tokens")
print(f"Context window: {model.context_window:,} tokens")
# Output:
# Model ID: gpt-4o-mini
# Provider: openai
# Type: chat
# Prompt cost: $0.15 per 1M tokens
# Completion cost: $0.60 per 1M tokens
# Max output: 16,384 tokens
# Context window: 128,000 tokens
Calculating Costs¶
from selectools.pricing import calculate_cost
from selectools.models import OpenAI
cost = calculate_cost(
model=OpenAI.GPT_4O_MINI.id,
prompt_tokens=1000,
completion_tokens=500
)
# Or manually:
model = OpenAI.GPT_4O_MINI
cost = (1000 / 1_000_000 * model.prompt_cost) + (500 / 1_000_000 * model.completion_cost)
Quick Lookup¶
from selectools.models import MODELS_BY_ID
# O(1) lookup
model = MODELS_BY_ID["gpt-4o-mini"]
print(f"Cost: ${model.prompt_cost}/${model.completion_cost}")
# Check if model exists
if "gpt-99" in MODELS_BY_ID:
print("Model supported")
else:
print("Model not in registry")
List All Models¶
from selectools.models import ALL_MODELS
# All 152 models
print(f"Total models: {len(ALL_MODELS)}")
# Filter by provider
openai_models = [m for m in ALL_MODELS if m.provider == "openai"]
print(f"OpenAI models: {len(openai_models)}")
# Filter by type
embedding_models = [m for m in ALL_MODELS if m.type == "embedding"]
print(f"Embedding models: {len(embedding_models)}")
# Sort by cost
cheapest = sorted(ALL_MODELS, key=lambda m: m.prompt_cost)[:5]
for model in cheapest:
print(f"{model.id}: ${model.prompt_cost}")
Model Metadata¶
Complete Example¶
from selectools.models import OpenAI
model = OpenAI.GPT_4O
# Core identification
model.id # "gpt-4o"
model.provider # "openai"
model.type # "chat"
# Pricing (USD per 1M tokens)
model.prompt_cost # 2.50
model.completion_cost # 10.00
# Capabilities
model.max_tokens # 16384 (max output)
model.context_window # 128000 (max input+output)
# Example calculation
input_tokens = 50000
output_tokens = 5000
input_cost = input_tokens / 1_000_000 * model.prompt_cost
output_cost = output_tokens / 1_000_000 * model.completion_cost
total_cost = input_cost + output_cost
print(f"Total cost: ${total_cost:.6f}") # $0.175000
ModelType Enum¶
ModelType is now a proper str enum (backward compatible with string comparisons):
from selectools import ModelType
class ModelType(str, Enum):
CHAT = "chat"
EMBEDDING = "embedding"
IMAGE = "image"
AUDIO = "audio"
MULTIMODAL = "multimodal"
Backward compatible:
ModelType.CHAT == "chat"isTrue, so existing code that compares against string literals continues to work without changes.
# Chat models
OpenAI.GPT_4O.type == "chat" # True
OpenAI.GPT_4O.type == ModelType.CHAT # True
# Embedding models
OpenAI.Embeddings.TEXT_EMBEDDING_3_SMALL.type == "embedding" # True
OpenAI.Embeddings.TEXT_EMBEDDING_3_SMALL.type == ModelType.EMBEDDING # True
# Audio models
OpenAI.GPT_REALTIME.type == ModelType.AUDIO # True
# Multimodal models
OpenAI.GPT_4_1106_VISION_PREVIEW.type == ModelType.MULTIMODAL # True
Implementation¶
Model Definition¶
# In models.py
class OpenAI:
GPT_4O_MINI = ModelInfo(
id="gpt-4o-mini",
provider="openai",
type="chat",
prompt_cost=0.15,
completion_cost=0.60,
max_tokens=16384,
context_window=128000,
)
class Embeddings:
TEXT_EMBEDDING_3_SMALL = ModelInfo(
id="text-embedding-3-small",
provider="openai",
type="embedding",
prompt_cost=0.02,
completion_cost=0.0, # Embeddings don't have completion cost
max_tokens=8191,
context_window=8191,
)
Registry Generation¶
def _collect_all_models() -> List[ModelInfo]:
"""Collect all model definitions from provider classes."""
models = []
for provider_class in [OpenAI, Anthropic, Gemini, Ollama, Cohere]:
for attr_name in dir(provider_class):
if attr_name.startswith("_"):
continue
attr = getattr(provider_class, attr_name)
if isinstance(attr, ModelInfo):
models.append(attr)
elif isinstance(attr, type) and attr_name == "Embeddings":
# Nested Embeddings class
for embed_attr_name in dir(attr):
if embed_attr_name.startswith("_"):
continue
embed_attr = getattr(attr, embed_attr_name)
if isinstance(embed_attr, ModelInfo):
models.append(embed_attr)
return models
ALL_MODELS = _collect_all_models()
MODELS_BY_ID = {model.id: model for model in ALL_MODELS}
Best Practices¶
1. Use Model Constants¶
# ✅ Good - Type-safe, autocomplete
from selectools.models import OpenAI
model = OpenAI.GPT_4O_MINI.id
# ❌ Bad - String literals (typo-prone)
model = "gpt-4o-mini"
2. Check Model Costs Before Using¶
from selectools.models import OpenAI
model = OpenAI.O1 # Expensive reasoning model
print(f"Warning: This model costs ${model.prompt_cost}/${model.completion_cost} per 1M tokens")
if model.prompt_cost > 10.0:
print("Consider using a cheaper alternative")
3. Choose Appropriate Model for Task¶
from selectools.models import OpenAI
# Simple tasks
config = AgentConfig(model=OpenAI.GPT_4O_MINI.id) # $0.15/$0.60
# Complex reasoning
config = AgentConfig(model=OpenAI.O1.id) # $15.00/$60.00
# Embeddings
from selectools.embeddings import OpenAIEmbeddingProvider
embedder = OpenAIEmbeddingProvider(model=OpenAI.Embeddings.TEXT_EMBEDDING_3_SMALL.id)
4. Validate Model IDs¶
from selectools.models import MODELS_BY_ID
user_model = "gpt-4o-super" # User input
if user_model not in MODELS_BY_ID:
raise ValueError(f"Unknown model: {user_model}")
model_info = MODELS_BY_ID[user_model]
Cost Optimization¶
Model Comparison¶
from selectools.models import OpenAI, Anthropic, Gemini
# Budget options
print("Budget chat models:")
print(f" OpenAI GPT-4o-mini: ${OpenAI.GPT_4O_MINI.prompt_cost}/${OpenAI.GPT_4O_MINI.completion_cost}")
print(f" Gemini Flash 2.0: ${Gemini.FLASH_2_0.prompt_cost}/${Gemini.FLASH_2_0.completion_cost}")
print(f" Anthropic Haiku 3.5: ${Anthropic.HAIKU_3_5_20241022.prompt_cost}/${Anthropic.HAIKU_3_5_20241022.completion_cost}")
# Output:
# Budget chat models:
# OpenAI GPT-4o-mini: $0.15/$0.60
# Gemini Flash 2.0: $0.10/$0.40
# Anthropic Haiku 3.5: $0.80/$4.00
Embedding Costs¶
from selectools.models import OpenAI, Anthropic, Gemini, Cohere
print("Embedding costs:")
print(f" Gemini: ${Gemini.Embeddings.EMBEDDING_004.prompt_cost} (FREE)")
print(f" OpenAI small: ${OpenAI.Embeddings.TEXT_EMBEDDING_3_SMALL.prompt_cost}")
print(f" Voyage lite: ${Anthropic.Embeddings.VOYAGE_3_LITE.prompt_cost}")
print(f" Cohere: ${Cohere.Embeddings.EMBED_V3.prompt_cost}")
# Output:
# Embedding costs:
# Gemini: $0.0 (FREE)
# OpenAI small: $0.02
# Voyage lite: $0.02
# Cohere: $0.1
Testing¶
def test_model_registry():
from selectools.models import OpenAI, ALL_MODELS, MODELS_BY_ID
# Test model constant
model = OpenAI.GPT_4O_MINI
assert model.id == "gpt-4o-mini"
assert model.provider == "openai"
assert model.type == "chat"
assert model.prompt_cost > 0
assert model.context_window > 0
# Test registry
assert len(ALL_MODELS) >= 152
assert "gpt-4o-mini" in MODELS_BY_ID
# Test lookup
looked_up = MODELS_BY_ID["gpt-4o-mini"]
assert looked_up.id == model.id
def test_pricing_calculation():
from selectools.models import OpenAI
from selectools.pricing import calculate_cost
model = OpenAI.GPT_4O_MINI
cost = calculate_cost(model.id, prompt_tokens=1000, completion_tokens=500)
# Manual calculation
expected = (1000 / 1_000_000 * model.prompt_cost) + (500 / 1_000_000 * model.completion_cost)
assert abs(cost - expected) < 0.000001
Programmatic Pricing API¶
Look up pricing at runtime — useful for cost estimation, budget alerts, and billing dashboards.
PRICING Dictionary¶
The PRICING dict maps every model ID to its per-million-token costs:
from selectools import PRICING
# Look up GPT-4o pricing
pricing = PRICING["gpt-4o"]
print(pricing)
# {"prompt": 2.50, "completion": 10.00}
# Calculate cost for 1000 prompt + 500 completion tokens
cost = (1000 * pricing["prompt"] + 500 * pricing["completion"]) / 1_000_000
print(f"${cost:.6f}")
get_model_pricing(model_id)¶
Safe lookup that returns None if the model isn't in the registry:
from selectools import get_model_pricing
pricing = get_model_pricing("gpt-4o-mini")
if pricing:
print(f"Prompt: ${pricing['prompt']}/M tokens")
print(f"Completion: ${pricing['completion']}/M tokens")
else:
print("Unknown model")
calculate_cost(model, prompt_tokens, completion_tokens)¶
Direct cost calculation:
from selectools import calculate_cost
cost = calculate_cost("gpt-4o", prompt_tokens=1500, completion_tokens=300)
print(f"${cost:.6f}") # $0.006750
calculate_embedding_cost(model, tokens)¶
For embedding models:
from selectools import calculate_embedding_cost
cost = calculate_embedding_cost("text-embedding-3-small", tokens=10000)
print(f"${cost:.6f}") # $0.000200
Listing All Models¶
from selectools import ALL_MODELS, MODELS_BY_ID
# All 152 ModelInfo objects
for model in ALL_MODELS:
print(f"{model.id:40s} ${model.prompt_cost:>8.2f} / ${model.completion_cost:>8.2f}")
# Look up by ID
model = MODELS_BY_ID.get("claude-sonnet-4-20250514")
if model:
print(f"Context: {model.context_window:,} tokens")
Updating Models¶
When new models are released:
- Add to appropriate class:
class OpenAI:
NEW_MODEL = ModelInfo(
id="gpt-99",
provider="openai",
type="chat",
prompt_cost=1.0,
completion_cost=5.0,
max_tokens=32768,
context_window=256000,
)
-
Update registry (automatic via
_collect_all_models()) -
Update documentation
-
Add tests
Further Reading¶
- Providers Module - Using models with providers
- Usage Module - Cost tracking
- Pricing Module - Cost calculation
Congratulations! You've completed the selectools implementation documentation. Return to ARCHITECTURE.md for the system overview.