Skip to content
This repository was archived by the owner on Dec 11, 2025. It is now read-only.

Commit 0b86af2

Browse files
authored
feat(ENG-3109): Add Claude 4 Opus and 4.1 Opus to SDK. (#95)
* feat(ENG-3109): Add Opus 4.1 models to Python SDK. * tests * cassettes * t7 review * fix enum + tests
1 parent 3fa1801 commit 0b86af2

8 files changed

Lines changed: 718 additions & 1 deletion

notdiamond/llms/providers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ class NDLLMProviders(Enum):
4343
CLAUDE_3_5_HAIKU_20241022 (NDLLMProvider): refers to 'claude-3-5-haiku-20241022' model by Anthropic
4444
CLAUDE_3_HAIKU_20240307 (NDLLMProvider): refers to 'claude-3-haiku-20240307' model by Anthropic
4545
CLAUDE_OPUS_4_20250514 (NDLLMProvider): refers to 'claude-opus-4-20250514' model by Anthropic
46+
CLAUDE_OPUS_4_1_20250805 (NDLLMProvider): refers to 'claude-opus-4-1-20250805' model by Anthropic
4647
CLAUDE_SONNET_4_20250514 (NDLLMProvider): refers to 'claude-sonnet-4-20250514' model by Anthropic
4748
CLAUDE_OPUS_4_0 (NDLLMProvider): refers to 'claude-opus-4-0' model by Anthropic
49+
CLAUDE_OPUS_4_1 (NDLLMProvider): refers to 'claude-opus-4-1' model by Anthropic
4850
CLAUDE_SONNET_4_0 (NDLLMProvider): refers to 'claude-sonnet-4-0' model by Anthropic
4951
5052
GEMINI_PRO (NDLLMProvider): refers to 'gemini-pro' model by Google
@@ -132,8 +134,10 @@ class NDLLMProviders(Enum):
132134
CLAUDE_3_5_HAIKU_20241022 = ("anthropic", "claude-3-5-haiku-20241022")
133135
CLAUDE_3_HAIKU_20240307 = ("anthropic", "claude-3-haiku-20240307")
134136
CLAUDE_OPUS_4_20250514 = ("anthropic", "claude-opus-4-20250514")
137+
CLAUDE_OPUS_4_1_20250805 = ("anthropic", "claude-opus-4-1-20250805")
135138
CLAUDE_SONNET_4_20250514 = ("anthropic", "claude-sonnet-4-20250514")
136139
CLAUDE_OPUS_4_0 = ("anthropic", "claude-opus-4-0")
140+
CLAUDE_OPUS_4_1 = ("anthropic", "claude-opus-4-1")
137141
CLAUDE_SONNET_4_0 = ("anthropic", "claude-sonnet-4-0")
138142

139143
GEMINI_PRO = ("google", "gemini-pro")

notdiamond/settings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,10 @@
165165
"claude-3-7-sonnet-latest",
166166
"claude-3-7-sonnet-20250219",
167167
"claude-opus-4-20250514",
168+
"claude-opus-4-1-20250805",
168169
"claude-sonnet-4-20250514",
169170
"claude-opus-4-0",
171+
"claude-opus-4-1",
170172
"claude-sonnet-4-0",
171173
],
172174
"api_key": ANTHROPIC_API_KEY,
@@ -181,8 +183,10 @@
181183
"claude-3-7-sonnet-latest",
182184
"claude-3-7-sonnet-20250219",
183185
"claude-opus-4-20250514",
186+
"claude-opus-4-1-20250805",
184187
"claude-sonnet-4-20250514",
185188
"claude-opus-4-0",
189+
"claude-opus-4-1",
186190
"claude-sonnet-4-0",
187191
],
188192
"support_response_model": [
@@ -200,8 +204,10 @@
200204
"claude-3-7-sonnet-latest": "anthropic/claude-3.7-sonnet",
201205
"claude-3-7-sonnet-20250219": "anthropic/claude-3.7-sonnet",
202206
"claude-opus-4-20250514": "anthropic/claude-opus-4",
207+
"claude-opus-4-1-20250805": "anthropic/claude-opus-4-1-20250805",
203208
"claude-sonnet-4-20250514": "anthropic/claude-sonnet-4",
204209
"claude-opus-4-0": "anthropic/claude-opus-4",
210+
"claude-opus-4-1": "anthropic/claude-opus-4-1",
205211
"claude-sonnet-4-0": "anthropic/claude-sonnet-4",
206212
},
207213
"price": {
@@ -216,8 +222,10 @@
216222
"claude-3-7-sonnet-latest": {"input": 3.0, "output": 15.0},
217223
"claude-3-7-sonnet-20250219": {"input": 3.0, "output": 15.0},
218224
"claude-opus-4-20250514": {"input": 15.0, "output": 75.0},
225+
"claude-opus-4-1-20250805": {"input": 15.0, "output": 75.0},
219226
"claude-sonnet-4-20250514": {"input": 3.0, "output": 15.0},
220227
"claude-opus-4-0": {"input": 15.0, "output": 75.0},
228+
"claude-opus-4-1": {"input": 15.0, "output": 75.0},
221229
"claude-sonnet-4-0": {"input": 3.0, "output": 15.0},
222230
},
223231
},

tests/conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,13 @@ def _before_record_request(request: Any) -> Any:
241241

242242
@pytest.fixture(scope="module")
243243
def vcr_config():
244+
record_mode = os.getenv("RECORD_MODE", "none")
244245
return {
245246
"filter_headers": ["authorization", "x-token"],
246247
"allowed_hosts": ["testserver", "127.0.0.1"],
247248
"before_record_response": _redact_xtoken_response,
248249
"before_record_request": _before_record_request,
249250
"ignore_localhost": True,
250-
"record_mode": "none",
251+
"record_mode": record_mode,
251252
"decode_compressed_response": True,
252253
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
interactions:
2+
- request:
3+
body: '{"messages": [{"role": "user", "content": "How much is 3 + 5?"}], "llm_providers":
4+
[{"provider": "anthropic", "model": "claude-opus-4-1-20250805", "is_custom":
5+
false, "context_length": null, "input_price": null, "output_price": null, "latency":
6+
null}], "metric": "accuracy", "max_model_depth": 1, "hash_content": true, "tools":
7+
[{"type": "function", "function": {"name": "add_fct", "description": "Add two
8+
numbers", "parameters": {"type": "object", "properties": {"a": {"type": "integer",
9+
"description": "The first number"}, "b": {"type": "integer", "description":
10+
"The second number"}}, "required": ["a", "b"]}}}]}'
11+
headers:
12+
Accept:
13+
- '*/*'
14+
Accept-Encoding:
15+
- gzip, deflate, zstd
16+
Connection:
17+
- keep-alive
18+
Content-Length:
19+
- '615'
20+
User-Agent:
21+
- Python-SDK/0.4.4
22+
content-type:
23+
- application/json
24+
method: POST
25+
uri: https://api.notdiamond.ai/v2/modelRouter/modelSelect
26+
response:
27+
body:
28+
string: '{"detail":"Could not find valid API key"}'
29+
headers:
30+
CF-RAY:
31+
- 9713fe676f5c5322-MIA
32+
Connection:
33+
- keep-alive
34+
Content-Type:
35+
- application/json
36+
Date:
37+
- Mon, 18 Aug 2025 19:59:48 GMT
38+
Server:
39+
- cloudflare
40+
Transfer-Encoding:
41+
- chunked
42+
alt-svc:
43+
- h3=":443"; ma=86400
44+
cf-cache-status:
45+
- DYNAMIC
46+
rndr-id:
47+
- 36fbf754-ecf4-4204
48+
vary:
49+
- Accept-Encoding
50+
x-render-origin-server:
51+
- uvicorn
52+
x-request-id:
53+
- 36fbf754-ecf4-4204
54+
status:
55+
code: 401
56+
message: Unauthorized
57+
- request:
58+
body: '{"max_tokens":200,"messages":[{"role":"user","content":"How much is 3 +
59+
5?"}],"model":"claude-opus-4-1-20250805","tools":[{"name":"add_fct","description":"Add
60+
two numbers","input_schema":{"type":"object","properties":{"a":{"type":"integer","description":"The
61+
first number"},"b":{"type":"integer","description":"The second number"}},"required":["a","b"]}}]}'
62+
headers:
63+
accept:
64+
- application/json
65+
accept-encoding:
66+
- gzip, deflate, zstd
67+
anthropic-version:
68+
- '2023-06-01'
69+
connection:
70+
- keep-alive
71+
content-length:
72+
- '356'
73+
content-type:
74+
- application/json
75+
host:
76+
- api.anthropic.com
77+
user-agent:
78+
- Anthropic/Python 0.49.0
79+
x-api-key:
80+
- REDACTED
81+
x-stainless-arch:
82+
- arm64
83+
x-stainless-async:
84+
- 'false'
85+
x-stainless-lang:
86+
- python
87+
x-stainless-os:
88+
- MacOS
89+
x-stainless-package-version:
90+
- 0.49.0
91+
x-stainless-read-timeout:
92+
- '120.0'
93+
x-stainless-retry-count:
94+
- '0'
95+
x-stainless-runtime:
96+
- CPython
97+
x-stainless-runtime-version:
98+
- 3.12.6
99+
x-stainless-timeout:
100+
- NOT_GIVEN
101+
method: POST
102+
uri: https://api.anthropic.com/v1/messages
103+
response:
104+
body:
105+
string: '{"id":"msg_01PpU5WKAqdRmGsdB8wHqPqD","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"I''ll
106+
add those two numbers for you."},{"type":"tool_use","id":"toolu_01527NoTzvK1hZoA274srU7T","name":"add_fct","input":{"a":3,"b":5}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":411,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":81,"service_tier":"standard"}}'
107+
headers:
108+
CF-RAY:
109+
- 9713fe68fdd1336a-MIA
110+
Connection:
111+
- keep-alive
112+
Content-Type:
113+
- application/json
114+
Date:
115+
- Mon, 18 Aug 2025 19:59:51 GMT
116+
Server:
117+
- cloudflare
118+
Transfer-Encoding:
119+
- chunked
120+
X-Robots-Tag:
121+
- none
122+
anthropic-organization-id:
123+
- a2610b2c-742e-455d-9552-6abe105b2a44
124+
anthropic-ratelimit-input-tokens-limit:
125+
- '2000000'
126+
anthropic-ratelimit-input-tokens-remaining:
127+
- '2000000'
128+
anthropic-ratelimit-input-tokens-reset:
129+
- '2025-08-18T19:59:48Z'
130+
anthropic-ratelimit-output-tokens-limit:
131+
- '400000'
132+
anthropic-ratelimit-output-tokens-remaining:
133+
- '400000'
134+
anthropic-ratelimit-output-tokens-reset:
135+
- '2025-08-18T19:59:51Z'
136+
anthropic-ratelimit-requests-limit:
137+
- '4000'
138+
anthropic-ratelimit-requests-remaining:
139+
- '3999'
140+
anthropic-ratelimit-requests-reset:
141+
- '2025-08-18T19:59:48Z'
142+
anthropic-ratelimit-tokens-limit:
143+
- '2400000'
144+
anthropic-ratelimit-tokens-remaining:
145+
- '2400000'
146+
anthropic-ratelimit-tokens-reset:
147+
- '2025-08-18T19:59:48Z'
148+
cf-cache-status:
149+
- DYNAMIC
150+
content-length:
151+
- '537'
152+
request-id:
153+
- req_011CSFmYD9J65w4aM2Ya8Wyu
154+
strict-transport-security:
155+
- max-age=31536000; includeSubDomains; preload
156+
via:
157+
- 1.1 google
158+
x-envoy-upstream-service-time:
159+
- '2919'
160+
status:
161+
code: 200
162+
message: OK
163+
version: 1

0 commit comments

Comments
 (0)