7
7
from datetime import datetime , timezone
8
8
from typing import Any , Literal , Union , cast , overload
9
9
10
- from anthropic .types import ServerToolUseBlock , ToolUnionParam , WebSearchTool20250305Param , WebSearchToolResultBlock
11
- from anthropic .types .web_search_tool_20250305_param import UserLocation
10
+ from anthropic .types .beta import BetaMessage , BetaRawMessageStreamEvent , BetaToolUnionParam
12
11
from typing_extensions import assert_never
13
12
14
- from pydantic_ai .builtin_tools import WebSearchTool
13
+ from pydantic_ai .builtin_tools import CodeExecutionTool , WebSearchTool
15
14
16
15
from .. import ModelHTTPError , UnexpectedModelBehavior , _utils , usage
17
16
from .._utils import guard_tool_call_id as _guard_tool_call_id
61
60
RawMessageStartEvent ,
62
61
RawMessageStopEvent ,
63
62
RawMessageStreamEvent ,
63
+ ServerToolUseBlock ,
64
64
TextBlock ,
65
65
TextBlockParam ,
66
66
TextDelta ,
67
67
ToolChoiceParam ,
68
68
ToolParam ,
69
69
ToolResultBlockParam ,
70
+ ToolUnionParam ,
70
71
ToolUseBlock ,
71
72
ToolUseBlockParam ,
73
+ WebSearchTool20250305Param ,
74
+ WebSearchToolResultBlock ,
72
75
)
76
+ from anthropic .types .beta .beta_code_execution_tool_20250522_param import BetaCodeExecutionTool20250522Param
77
+ from anthropic .types .web_search_tool_20250305_param import UserLocation
73
78
except ImportError as _import_error :
74
79
raise ImportError (
75
80
'Please install `anthropic` to use the Anthropic model, '
@@ -207,10 +212,11 @@ async def _messages_create(
207
212
stream : bool ,
208
213
model_settings : AnthropicModelSettings ,
209
214
model_request_parameters : ModelRequestParameters ,
210
- ) -> AnthropicMessage | AsyncStream [RawMessageStreamEvent ]:
215
+ ) -> AnthropicMessage | AsyncStream [RawMessageStreamEvent ] | BetaMessage | AsyncStream [ BetaRawMessageStreamEvent ] :
211
216
# standalone function to make it easier to override
212
217
tools = self ._get_tools (model_request_parameters )
213
218
tools += self ._get_builtin_tools (model_request_parameters )
219
+ beta_tools = self ._get_beta_tools (model_request_parameters )
214
220
tool_choice : ToolChoiceParam | None
215
221
216
222
if not tools :
@@ -229,22 +235,30 @@ async def _messages_create(
229
235
try :
230
236
extra_headers = model_settings .get ('extra_headers' , {})
231
237
extra_headers .setdefault ('User-Agent' , get_user_agent ())
232
- return await self .client .messages .create (
233
- max_tokens = model_settings .get ('max_tokens' , 1024 ),
234
- system = system_prompt or NOT_GIVEN ,
235
- messages = anthropic_messages ,
236
- model = self ._model_name ,
237
- tools = tools or NOT_GIVEN ,
238
- tool_choice = tool_choice or NOT_GIVEN ,
239
- stream = stream ,
240
- stop_sequences = model_settings .get ('stop_sequences' , NOT_GIVEN ),
241
- temperature = model_settings .get ('temperature' , NOT_GIVEN ),
242
- top_p = model_settings .get ('top_p' , NOT_GIVEN ),
243
- timeout = model_settings .get ('timeout' , NOT_GIVEN ),
244
- metadata = model_settings .get ('anthropic_metadata' , NOT_GIVEN ),
245
- extra_headers = extra_headers ,
246
- extra_body = model_settings .get ('extra_body' ),
247
- )
238
+ if beta_tools :
239
+ return await self .client .beta .messages .create (
240
+ max_tokens = model_settings .get ('max_tokens' , 1024 ),
241
+ system = system_prompt or NOT_GIVEN ,
242
+ messages = anthropic_messages ,
243
+ model = self ._model_name ,
244
+ )
245
+ else :
246
+ return await self .client .messages .create (
247
+ max_tokens = model_settings .get ('max_tokens' , 1024 ),
248
+ system = system_prompt or NOT_GIVEN ,
249
+ messages = anthropic_messages ,
250
+ model = self ._model_name ,
251
+ tools = tools or NOT_GIVEN ,
252
+ tool_choice = tool_choice or NOT_GIVEN ,
253
+ stream = stream ,
254
+ stop_sequences = model_settings .get ('stop_sequences' , NOT_GIVEN ),
255
+ temperature = model_settings .get ('temperature' , NOT_GIVEN ),
256
+ top_p = model_settings .get ('top_p' , NOT_GIVEN ),
257
+ timeout = model_settings .get ('timeout' , NOT_GIVEN ),
258
+ metadata = model_settings .get ('anthropic_metadata' , NOT_GIVEN ),
259
+ extra_headers = extra_headers ,
260
+ extra_body = model_settings .get ('extra_body' ),
261
+ )
248
262
except APIStatusError as e :
249
263
if (status_code := e .status_code ) >= 400 :
250
264
raise ModelHTTPError (status_code = status_code , model_name = self .model_name , body = e .body ) from e
@@ -254,10 +268,12 @@ def _process_response(self, response: AnthropicMessage) -> ModelResponse:
254
268
"""Process a non-streamed response, and prepare a message to return."""
255
269
items : list [ModelResponsePart ] = []
256
270
for item in response .content :
271
+ breakpoint ()
257
272
if isinstance (item , TextBlock ):
258
273
items .append (TextPart (content = item .text ))
259
- if isinstance (item , WebSearchToolResultBlock ):
274
+ elif isinstance (item , WebSearchToolResultBlock ):
260
275
# TODO(Marcelo): We should send something back to the user, because we need to send it back on the next request.
276
+ # Do we need a new part type here? All the content is encrypted anyway - but it needs to go back to Anthropic.
261
277
...
262
278
else :
263
279
assert isinstance (item , (ToolUseBlock , ServerToolUseBlock )), f'unexpected item type { type (item )} '
@@ -305,6 +321,13 @@ def _get_builtin_tools(self, model_request_parameters: ModelRequestParameters) -
305
321
)
306
322
return tools
307
323
324
+ def _get_beta_tools (self , model_request_parameters : ModelRequestParameters ) -> list [BetaToolUnionParam ]:
325
+ tools : list [BetaToolUnionParam ] = []
326
+ for tool in model_request_parameters .builtin_tools :
327
+ if isinstance (tool , CodeExecutionTool ):
328
+ tools .append (BetaCodeExecutionTool20250522Param (name = 'code_execution' , type = 'code_execution_20250522' ))
329
+ return tools
330
+
308
331
async def _map_message (self , messages : list [ModelMessage ]) -> tuple [str , list [MessageParam ]]:
309
332
"""Just maps a `pydantic_ai.Message` to a `anthropic.types.MessageParam`."""
310
333
system_prompt_parts : list [str ] = []
0 commit comments