Skip to content

Commit 7bfdc97

Browse files
gn00295120claude
andcommitted
feat: add dynamic model selection utility (#71)
This addresses issue #71 by providing a flexible way to select Claude models without hardcoding version IDs that may become deprecated. Changes: - Add model_utils.py module with: * get_latest_model(client, alias) - Query API for latest model ID * get_model(client, alias) - Convenience wrapper * ModelSelector class with shortcuts (sonnet/haiku/opus) * Comprehensive documentation and examples - Update 01_getting_started.ipynb: * Add demo section explaining dynamic model selection * Show usage examples of get_model() and ModelSelector * Explain benefits: future-proof, maintainable, flexible * Insert after client initialization, before first API call Benefits: - Protects course code from model deprecation - Easier maintenance - no hardcoded model IDs - Educational - shows best practices for model selection Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent f4dbb13 commit 7bfdc97

2 files changed

Lines changed: 207 additions & 1 deletion

File tree

anthropic_api_fundamentals/01_getting_started.ipynb

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,54 @@
186186
")"
187187
]
188188
},
189+
{
190+
"cell_type": "markdown",
191+
"metadata": {},
192+
"source": [
193+
"## Dynamic model selection\n",
194+
"\n",
195+
"**Note**: The model ID used above (`\"claude-3-haiku-20240307\"`) may become deprecated over time as new models are released. Hardcoding model IDs in your code can lead to issues when models are updated.\n",
196+
"\n",
197+
"To avoid this, we've provided a utility module that dynamically selects the latest model version based on aliases (like `'sonnet'`, `'haiku'`, or `'opus'`). This protects your code from model deprecation.\n",
198+
"\n",
199+
"### Example usage:\n",
200+
"\n",
201+
"```python\n",
202+
"from anthropic import Anthropic\n",
203+
"from model_utils import get_model, ModelSelector\n",
204+
"\n",
205+
"client = Anthropic()\n",
206+
"\n",
207+
"# Using the convenience function\n",
208+
"model = get_model(client, 'sonnet') # Returns latest Sonnet model ID\n",
209+
"\n",
210+
"# Using the ModelSelector class\n",
211+
"selector = ModelSelector(client)\n",
212+
"model = selector.sonnet() # Get latest Sonnet\n",
213+
"model = selector.haiku() # Get latest Haiku\n",
214+
"model = selector.opus() # Get latest Opus (if available)\n",
215+
"\n",
216+
"# Use the dynamically-selected model\n",
217+
"response = client.messages.create(\n",
218+
" model=model,\n",
219+
" max_tokens=1000,\n",
220+
" messages=[{\"role\": \"user\", \"content\": \"Hello!\"}]\n",
221+
")\n",
222+
"```\n",
223+
"\n",
224+
"### Why use dynamic selection?\n",
225+
"\n",
226+
"- **Future-proof**: Your code automatically uses the latest model version\n",
227+
"- **Maintainable**: No need to update hardcoded model IDs throughout your codebase\n",
228+
"- **Flexible**: Easily switch between model families (sonnet/haiku/opus)\n",
229+
"\n",
230+
"The `model_utils.py` module is included in this directory and provides:\n",
231+
"- `get_latest_model(client, alias)` - Get the latest model ID for an alias\n",
232+
"- `ModelSelector` class - Convenient shortcuts for model selection\n",
233+
"\n",
234+
"For more details, see the `model_utils.py` file in this directory.\n"
235+
]
236+
},
189237
{
190238
"cell_type": "markdown",
191239
"metadata": {},
@@ -278,4 +326,4 @@
278326
},
279327
"nbformat": 4,
280328
"nbformat_minor": 2
281-
}
329+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
"""
2+
Model utilities for dynamic model selection.
3+
4+
This module provides helper functions to dynamically select Claude models
5+
based on aliases rather than hardcoded version IDs, protecting against model
6+
deprecation and version changes.
7+
"""
8+
9+
from anthropic import Anthropic
10+
from typing import Optional
11+
12+
13+
def get_latest_model(client: Anthropic, model_alias: str) -> str:
14+
"""
15+
Get the latest model ID for a given model alias.
16+
17+
This function queries the Anthropic API to find the latest version of a model
18+
based on its alias (e.g., 'sonnet', 'haiku', 'opus'), protecting against
19+
hardcoded model IDs becoming deprecated.
20+
21+
Args:
22+
client: Anthropic API client instance
23+
model_alias: Model alias ('sonnet', 'haiku', 'opus')
24+
25+
Returns:
26+
Latest model ID (e.g., 'claude-3-5-sonnet-20241022')
27+
28+
Raises:
29+
ValueError: If model_alias is not recognized
30+
31+
Examples:
32+
>>> client = Anthropic()
33+
>>> model = get_latest_model(client, 'sonnet')
34+
>>> print(model)
35+
'claude-3-5-sonnet-20241022'
36+
37+
>>> model = get_latest_model(client, 'haiku')
38+
>>> print(model)
39+
'claude-3-haiku-20240307'
40+
"""
41+
# Map of aliases to model name patterns
42+
alias_patterns = {
43+
'sonnet': 'sonnet',
44+
'haiku': 'haiku',
45+
'opus': 'opus',
46+
'sonnet-large': 'sonnet',
47+
'sonnet-small': 'haiku', # Alias for consistency
48+
}
49+
50+
if model_alias not in alias_patterns:
51+
raise ValueError(
52+
f"Unknown model alias: '{model_alias}'. "
53+
f"Valid options: {list(alias_patterns.keys())}"
54+
)
55+
56+
pattern = alias_patterns[model_alias]
57+
58+
# Get all models from API
59+
models = client.models.list()
60+
61+
# Filter models matching the pattern
62+
matching_models = [
63+
m.id for m in models.data
64+
if pattern in m.id
65+
]
66+
67+
if not matching_models:
68+
raise ValueError(
69+
f"No models found matching alias '{model_alias}' (pattern: '{pattern}')"
70+
)
71+
72+
# Sort by ID (which includes date) to get the latest
73+
# Models are named like claude-3-5-sonnet-YYYYMMDD, so sorting by name
74+
# in reverse order gives us the most recent
75+
latest_model = sorted(matching_models, reverse=True)[0]
76+
77+
return latest_model
78+
79+
80+
def get_model(client: Anthropic, model_alias: str) -> str:
81+
"""
82+
Convenience function to get a model by alias.
83+
84+
This is a shorter alias for get_latest_model().
85+
86+
Args:
87+
client: Anthropic API client instance
88+
model_alias: Model alias ('sonnet', 'haiku', 'opus')
89+
90+
Returns:
91+
Latest model ID
92+
93+
Examples:
94+
>>> client = Anthropic()
95+
>>> model = get_model(client, 'sonnet')
96+
>>> response = client.messages.create(model=model, ...)
97+
"""
98+
return get_latest_model(client, model_alias)
99+
100+
101+
# Predefined model selection shortcuts
102+
class ModelSelector:
103+
"""
104+
Convenience class for model selection with predefined shortcuts.
105+
106+
Examples:
107+
>>> client = Anthropic()
108+
>>> selector = ModelSelector(client)
109+
>>>
110+
>>> # Using shortcuts
111+
>>> model = selector.sonnet()
112+
>>> model = selector.haiku()
113+
>>> model = selector.latest_large()
114+
>>> model = selector.latest_small()
115+
"""
116+
117+
def __init__(self, client: Anthropic):
118+
"""
119+
Initialize ModelSelector with an Anthropic client.
120+
121+
Args:
122+
client: Anthropic API client instance
123+
"""
124+
self.client = client
125+
126+
def sonnet(self) -> str:
127+
"""Get the latest Sonnet model (most capable)."""
128+
return get_latest_model(self.client, 'sonnet')
129+
130+
def haiku(self) -> str:
131+
"""Get the latest Haiku model (fastest)."""
132+
return get_latest_model(self.client, 'haiku')
133+
134+
def opus(self) -> str:
135+
"""Get the latest Opus model (if available)."""
136+
return get_latest_model(self.client, 'opus')
137+
138+
def latest_large(self) -> str:
139+
"""Get the latest large model (Sonnet)."""
140+
return self.sonnet()
141+
142+
def latest_small(self) -> str:
143+
"""Get the latest small model (Haiku)."""
144+
return self.haiku()
145+
146+
147+
# Convenience instance for quick access
148+
# Usage:
149+
# from model_utils import selector
150+
# model = selector.sonnet()
151+
# _selector = None # Will be initialized on first use
152+
#
153+
# def selector():
154+
# global _selector
155+
# if _selector is None:
156+
# from anthropic import Anthropic
157+
# _selector = ModelSelector(Anthropic())
158+
# return _selector

0 commit comments

Comments
 (0)