pydantic-ai-slim 0.6.1__tar.gz → 0.6.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/.gitignore +1 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/PKG-INFO +4 -4
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/__init__.py +5 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_agent_graph.py +7 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_utils.py +7 -1
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/agent.py +9 -0
- pydantic_ai_slim-0.6.2/pydantic_ai/builtin_tools.py +105 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/messages.py +73 -11
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/__init__.py +2 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/anthropic.py +120 -12
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/bedrock.py +8 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/cohere.py +10 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/function.py +9 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/gemini.py +5 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/google.py +36 -2
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/groq.py +36 -3
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/huggingface.py +9 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/mistral.py +16 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/openai.py +73 -12
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/test.py +9 -0
- pydantic_ai_slim-0.6.2/pydantic_ai/profiles/groq.py +23 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/groq.py +2 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pyproject.toml +1 -1
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/LICENSE +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/README.md +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/__main__.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_a2a.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_cli.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_function_schema.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_griffe.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_mcp.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_output.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_parts_manager.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_run_context.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_system_prompt.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_thinking_part.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/_tool_manager.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/ag_ui.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/common_tools/__init__.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/common_tools/duckduckgo.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/common_tools/tavily.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/direct.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/exceptions.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/ext/__init__.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/ext/aci.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/ext/langchain.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/format_prompt.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/mcp.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/fallback.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/instrumented.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/mcp_sampling.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/models/wrapper.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/output.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/__init__.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/_json_schema.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/amazon.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/anthropic.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/cohere.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/deepseek.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/google.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/grok.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/meta.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/mistral.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/moonshotai.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/openai.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/profiles/qwen.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/__init__.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/anthropic.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/azure.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/bedrock.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/cohere.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/deepseek.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/fireworks.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/github.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/google.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/google_gla.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/google_vertex.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/grok.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/heroku.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/huggingface.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/mistral.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/moonshotai.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/openai.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/openrouter.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/together.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/providers/vercel.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/py.typed +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/result.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/retries.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/settings.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/tools.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/__init__.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/abstract.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/combined.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/deferred.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/filtered.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/function.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/prefixed.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/prepared.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/renamed.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/toolsets/wrapper.py +0 -0
- {pydantic_ai_slim-0.6.1 → pydantic_ai_slim-0.6.2}/pydantic_ai/usage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai-slim
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: Agent Framework / shim to use Pydantic with LLMs, slim package
|
|
5
5
|
Author-email: Samuel Colvin <samuel@pydantic.dev>, Marcelo Trylesinski <marcelotryle@gmail.com>, David Montague <david@pydantic.dev>, Alex Hall <alex@pydantic.dev>, Douwe Maan <douwe@pydantic.dev>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -30,7 +30,7 @@ Requires-Dist: exceptiongroup; python_version < '3.11'
|
|
|
30
30
|
Requires-Dist: griffe>=1.3.2
|
|
31
31
|
Requires-Dist: httpx>=0.27
|
|
32
32
|
Requires-Dist: opentelemetry-api>=1.28.0
|
|
33
|
-
Requires-Dist: pydantic-graph==0.6.
|
|
33
|
+
Requires-Dist: pydantic-graph==0.6.2
|
|
34
34
|
Requires-Dist: pydantic>=2.10
|
|
35
35
|
Requires-Dist: typing-inspection>=0.4.0
|
|
36
36
|
Provides-Extra: a2a
|
|
@@ -51,11 +51,11 @@ Requires-Dist: cohere>=5.16.0; (platform_system != 'Emscripten') and extra == 'c
|
|
|
51
51
|
Provides-Extra: duckduckgo
|
|
52
52
|
Requires-Dist: ddgs>=9.0.0; extra == 'duckduckgo'
|
|
53
53
|
Provides-Extra: evals
|
|
54
|
-
Requires-Dist: pydantic-evals==0.6.
|
|
54
|
+
Requires-Dist: pydantic-evals==0.6.2; extra == 'evals'
|
|
55
55
|
Provides-Extra: google
|
|
56
56
|
Requires-Dist: google-genai>=1.28.0; extra == 'google'
|
|
57
57
|
Provides-Extra: groq
|
|
58
|
-
Requires-Dist: groq>=0.
|
|
58
|
+
Requires-Dist: groq>=0.25.0; extra == 'groq'
|
|
59
59
|
Provides-Extra: huggingface
|
|
60
60
|
Requires-Dist: huggingface-hub[inference]>=0.33.5; extra == 'huggingface'
|
|
61
61
|
Provides-Extra: logfire
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from importlib.metadata import version as _metadata_version
|
|
2
2
|
|
|
3
3
|
from .agent import Agent, CallToolsNode, EndStrategy, ModelRequestNode, UserPromptNode, capture_run_messages
|
|
4
|
+
from .builtin_tools import CodeExecutionTool, WebSearchTool, WebSearchUserLocation
|
|
4
5
|
from .exceptions import (
|
|
5
6
|
AgentRunError,
|
|
6
7
|
FallbackExceptionGroup,
|
|
@@ -41,6 +42,10 @@ __all__ = (
|
|
|
41
42
|
# tools
|
|
42
43
|
'Tool',
|
|
43
44
|
'RunContext',
|
|
45
|
+
# builtin_tools
|
|
46
|
+
'WebSearchTool',
|
|
47
|
+
'WebSearchUserLocation',
|
|
48
|
+
'CodeExecutionTool',
|
|
44
49
|
# output
|
|
45
50
|
'ToolOutput',
|
|
46
51
|
'NativeOutput',
|
|
@@ -16,6 +16,7 @@ from typing_extensions import TypeGuard, TypeVar, assert_never
|
|
|
16
16
|
from pydantic_ai._function_schema import _takes_ctx as is_takes_ctx # type: ignore
|
|
17
17
|
from pydantic_ai._tool_manager import ToolManager
|
|
18
18
|
from pydantic_ai._utils import is_async_callable, run_in_executor
|
|
19
|
+
from pydantic_ai.builtin_tools import AbstractBuiltinTool
|
|
19
20
|
from pydantic_graph import BaseNode, Graph, GraphRunContext
|
|
20
21
|
from pydantic_graph.nodes import End, NodeRunEndT
|
|
21
22
|
|
|
@@ -112,6 +113,7 @@ class GraphAgentDeps(Generic[DepsT, OutputDataT]):
|
|
|
112
113
|
|
|
113
114
|
history_processors: Sequence[HistoryProcessor[DepsT]]
|
|
114
115
|
|
|
116
|
+
builtin_tools: list[AbstractBuiltinTool] = dataclasses.field(repr=False)
|
|
115
117
|
tool_manager: ToolManager[DepsT]
|
|
116
118
|
|
|
117
119
|
tracer: Tracer
|
|
@@ -269,6 +271,7 @@ async def _prepare_request_parameters(
|
|
|
269
271
|
|
|
270
272
|
return models.ModelRequestParameters(
|
|
271
273
|
function_tools=function_tools,
|
|
274
|
+
builtin_tools=ctx.deps.builtin_tools,
|
|
272
275
|
output_mode=output_schema.mode,
|
|
273
276
|
output_tools=output_tools,
|
|
274
277
|
output_object=output_object,
|
|
@@ -443,6 +446,10 @@ class CallToolsNode(AgentNode[DepsT, NodeRunEndT]):
|
|
|
443
446
|
texts.append(part.content)
|
|
444
447
|
elif isinstance(part, _messages.ToolCallPart):
|
|
445
448
|
tool_calls.append(part)
|
|
449
|
+
elif isinstance(part, _messages.BuiltinToolCallPart):
|
|
450
|
+
yield _messages.BuiltinToolCallEvent(part)
|
|
451
|
+
elif isinstance(part, _messages.BuiltinToolReturnPart):
|
|
452
|
+
yield _messages.BuiltinToolResultEvent(part)
|
|
446
453
|
elif isinstance(part, _messages.ThinkingPart):
|
|
447
454
|
# We don't need to do anything with thinking parts in this tool-calling node.
|
|
448
455
|
# We need to handle text parts in case there are no tool calls and/or the desired output comes
|
|
@@ -227,7 +227,13 @@ def now_utc() -> datetime:
|
|
|
227
227
|
return datetime.now(tz=timezone.utc)
|
|
228
228
|
|
|
229
229
|
|
|
230
|
-
def guard_tool_call_id(
|
|
230
|
+
def guard_tool_call_id(
|
|
231
|
+
t: _messages.ToolCallPart
|
|
232
|
+
| _messages.ToolReturnPart
|
|
233
|
+
| _messages.RetryPromptPart
|
|
234
|
+
| _messages.BuiltinToolCallPart
|
|
235
|
+
| _messages.BuiltinToolReturnPart,
|
|
236
|
+
) -> str:
|
|
231
237
|
"""Type guard that either returns the tool call id or generates a new one if it's None."""
|
|
232
238
|
return t.tool_call_id or generate_tool_call_id()
|
|
233
239
|
|
|
@@ -16,6 +16,7 @@ from opentelemetry.trace import NoOpTracer, use_span
|
|
|
16
16
|
from pydantic.json_schema import GenerateJsonSchema
|
|
17
17
|
from typing_extensions import Literal, Never, Self, TypeIs, TypeVar, deprecated
|
|
18
18
|
|
|
19
|
+
from pydantic_ai.builtin_tools import AbstractBuiltinTool
|
|
19
20
|
from pydantic_graph import End, Graph, GraphRun, GraphRunContext
|
|
20
21
|
from pydantic_graph._utils import get_event_loop
|
|
21
22
|
|
|
@@ -188,6 +189,7 @@ class Agent(Generic[AgentDepsT, OutputDataT]):
|
|
|
188
189
|
retries: int = 1,
|
|
189
190
|
output_retries: int | None = None,
|
|
190
191
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] = (),
|
|
192
|
+
builtin_tools: Sequence[AbstractBuiltinTool] = (),
|
|
191
193
|
prepare_tools: ToolsPrepareFunc[AgentDepsT] | None = None,
|
|
192
194
|
prepare_output_tools: ToolsPrepareFunc[AgentDepsT] | None = None,
|
|
193
195
|
toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
|
|
@@ -215,6 +217,7 @@ class Agent(Generic[AgentDepsT, OutputDataT]):
|
|
|
215
217
|
retries: int = 1,
|
|
216
218
|
output_retries: int | None = None,
|
|
217
219
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] = (),
|
|
220
|
+
builtin_tools: Sequence[AbstractBuiltinTool] = (),
|
|
218
221
|
prepare_tools: ToolsPrepareFunc[AgentDepsT] | None = None,
|
|
219
222
|
prepare_output_tools: ToolsPrepareFunc[AgentDepsT] | None = None,
|
|
220
223
|
mcp_servers: Sequence[MCPServer] = (),
|
|
@@ -240,6 +243,7 @@ class Agent(Generic[AgentDepsT, OutputDataT]):
|
|
|
240
243
|
retries: int = 1,
|
|
241
244
|
output_retries: int | None = None,
|
|
242
245
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] = (),
|
|
246
|
+
builtin_tools: Sequence[AbstractBuiltinTool] = (),
|
|
243
247
|
prepare_tools: ToolsPrepareFunc[AgentDepsT] | None = None,
|
|
244
248
|
prepare_output_tools: ToolsPrepareFunc[AgentDepsT] | None = None,
|
|
245
249
|
toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
|
|
@@ -271,6 +275,8 @@ class Agent(Generic[AgentDepsT, OutputDataT]):
|
|
|
271
275
|
output_retries: The maximum number of retries to allow for output validation, defaults to `retries`.
|
|
272
276
|
tools: Tools to register with the agent, you can also register tools via the decorators
|
|
273
277
|
[`@agent.tool`][pydantic_ai.Agent.tool] and [`@agent.tool_plain`][pydantic_ai.Agent.tool_plain].
|
|
278
|
+
builtin_tools: The builtin tools that the agent will use. This depends on the model, as some models may not
|
|
279
|
+
support certain tools. If the model doesn't support the builtin tools, an error will be raised.
|
|
274
280
|
prepare_tools: Custom function to prepare the tool definition of all tools for each step, except output tools.
|
|
275
281
|
This is useful if you want to customize the definition of multiple tools or you want to register
|
|
276
282
|
a subset of tools for a given step. See [`ToolsPrepareFunc`][pydantic_ai.tools.ToolsPrepareFunc]
|
|
@@ -340,6 +346,8 @@ class Agent(Generic[AgentDepsT, OutputDataT]):
|
|
|
340
346
|
self._system_prompt_dynamic_functions = {}
|
|
341
347
|
|
|
342
348
|
self._max_result_retries = output_retries if output_retries is not None else retries
|
|
349
|
+
self._builtin_tools = builtin_tools
|
|
350
|
+
|
|
343
351
|
self._prepare_tools = prepare_tools
|
|
344
352
|
self._prepare_output_tools = prepare_output_tools
|
|
345
353
|
|
|
@@ -700,6 +708,7 @@ class Agent(Generic[AgentDepsT, OutputDataT]):
|
|
|
700
708
|
output_schema=output_schema,
|
|
701
709
|
output_validators=output_validators,
|
|
702
710
|
history_processors=self.history_processors,
|
|
711
|
+
builtin_tools=list(self._builtin_tools),
|
|
703
712
|
tool_manager=run_toolset,
|
|
704
713
|
tracer=tracer,
|
|
705
714
|
get_instructions=get_instructions,
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from __future__ import annotations as _annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from typing_extensions import TypedDict
|
|
8
|
+
|
|
9
|
+
__all__ = ('AbstractBuiltinTool', 'WebSearchTool', 'WebSearchUserLocation', 'CodeExecutionTool')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class AbstractBuiltinTool(ABC):
|
|
14
|
+
"""A builtin tool that can be used by an agent.
|
|
15
|
+
|
|
16
|
+
This class is abstract and cannot be instantiated directly.
|
|
17
|
+
|
|
18
|
+
The builtin tools are passed to the model as part of the `ModelRequestParameters`.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class WebSearchTool(AbstractBuiltinTool):
|
|
24
|
+
"""A builtin tool that allows your agent to search the web for information.
|
|
25
|
+
|
|
26
|
+
The parameters that PydanticAI passes depend on the model, as some parameters may not be supported by certain models.
|
|
27
|
+
|
|
28
|
+
Supported by:
|
|
29
|
+
* Anthropic
|
|
30
|
+
* OpenAI
|
|
31
|
+
* Groq
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
search_context_size: Literal['low', 'medium', 'high'] = 'medium'
|
|
35
|
+
"""The `search_context_size` parameter controls how much context is retrieved from the web to help the tool formulate a response.
|
|
36
|
+
|
|
37
|
+
Supported by:
|
|
38
|
+
* OpenAI
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
user_location: WebSearchUserLocation | None = None
|
|
42
|
+
"""The `user_location` parameter allows you to localize search results based on a user's location.
|
|
43
|
+
|
|
44
|
+
Supported by:
|
|
45
|
+
* Anthropic
|
|
46
|
+
* OpenAI
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
blocked_domains: list[str] | None = None
|
|
50
|
+
"""If provided, these domains will never appear in results.
|
|
51
|
+
|
|
52
|
+
With Anthropic, you can only use one of `blocked_domains` or `allowed_domains`, not both.
|
|
53
|
+
|
|
54
|
+
Supported by:
|
|
55
|
+
* Anthropic (https://docs.anthropic.com/en/docs/build-with-claude/tool-use/web-search-tool#domain-filtering)
|
|
56
|
+
* Groq (https://console.groq.com/docs/agentic-tooling#search-settings)
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
allowed_domains: list[str] | None = None
|
|
60
|
+
"""If provided, only these domains will be included in results.
|
|
61
|
+
|
|
62
|
+
With Anthropic, you can only use one of `blocked_domains` or `allowed_domains`, not both.
|
|
63
|
+
|
|
64
|
+
Supported by:
|
|
65
|
+
* Anthropic (https://docs.anthropic.com/en/docs/build-with-claude/tool-use/web-search-tool#domain-filtering)
|
|
66
|
+
* Groq (https://console.groq.com/docs/agentic-tooling#search-settings)
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
max_uses: int | None = None
|
|
70
|
+
"""If provided, the tool will stop searching the web after the given number of uses.
|
|
71
|
+
|
|
72
|
+
Supported by:
|
|
73
|
+
* Anthropic
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class WebSearchUserLocation(TypedDict, total=False):
|
|
78
|
+
"""Allows you to localize search results based on a user's location.
|
|
79
|
+
|
|
80
|
+
Supported by:
|
|
81
|
+
* Anthropic
|
|
82
|
+
* OpenAI
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
city: str
|
|
86
|
+
"""The city where the user is located."""
|
|
87
|
+
|
|
88
|
+
country: str
|
|
89
|
+
"""The country where the user is located. For OpenAI, this must be a 2-letter country code (e.g., 'US', 'GB')."""
|
|
90
|
+
|
|
91
|
+
region: str
|
|
92
|
+
"""The region or state where the user is located."""
|
|
93
|
+
|
|
94
|
+
timezone: str
|
|
95
|
+
"""The timezone of the user's location."""
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class CodeExecutionTool(AbstractBuiltinTool):
|
|
99
|
+
"""A builtin tool that allows your agent to execute code.
|
|
100
|
+
|
|
101
|
+
Supported by:
|
|
102
|
+
* Anthropic
|
|
103
|
+
* OpenAI
|
|
104
|
+
* Google
|
|
105
|
+
"""
|
|
@@ -532,8 +532,8 @@ tool_return_ta: pydantic.TypeAdapter[Any] = pydantic.TypeAdapter(
|
|
|
532
532
|
|
|
533
533
|
|
|
534
534
|
@dataclass(repr=False)
|
|
535
|
-
class
|
|
536
|
-
"""
|
|
535
|
+
class BaseToolReturnPart:
|
|
536
|
+
"""Base class for tool return parts."""
|
|
537
537
|
|
|
538
538
|
tool_name: str
|
|
539
539
|
"""The name of the "tool" was called."""
|
|
@@ -550,9 +550,6 @@ class ToolReturnPart:
|
|
|
550
550
|
timestamp: datetime = field(default_factory=_now_utc)
|
|
551
551
|
"""The timestamp, when the tool returned."""
|
|
552
552
|
|
|
553
|
-
part_kind: Literal['tool-return'] = 'tool-return'
|
|
554
|
-
"""Part type identifier, this is available on all parts as a discriminator."""
|
|
555
|
-
|
|
556
553
|
def model_response_str(self) -> str:
|
|
557
554
|
"""Return a string representation of the content for the model."""
|
|
558
555
|
if isinstance(self.content, str):
|
|
@@ -579,9 +576,32 @@ class ToolReturnPart:
|
|
|
579
576
|
},
|
|
580
577
|
)
|
|
581
578
|
|
|
579
|
+
def has_content(self) -> bool:
|
|
580
|
+
"""Return `True` if the tool return has content."""
|
|
581
|
+
return self.content is not None # pragma: no cover
|
|
582
|
+
|
|
582
583
|
__repr__ = _utils.dataclasses_no_defaults_repr
|
|
583
584
|
|
|
584
585
|
|
|
586
|
+
@dataclass(repr=False)
|
|
587
|
+
class ToolReturnPart(BaseToolReturnPart):
|
|
588
|
+
"""A tool return message, this encodes the result of running a tool."""
|
|
589
|
+
|
|
590
|
+
part_kind: Literal['tool-return'] = 'tool-return'
|
|
591
|
+
"""Part type identifier, this is available on all parts as a discriminator."""
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
@dataclass(repr=False)
|
|
595
|
+
class BuiltinToolReturnPart(BaseToolReturnPart):
|
|
596
|
+
"""A tool return message from a built-in tool."""
|
|
597
|
+
|
|
598
|
+
provider_name: str | None = None
|
|
599
|
+
"""The name of the provider that generated the response."""
|
|
600
|
+
|
|
601
|
+
part_kind: Literal['builtin-tool-return'] = 'builtin-tool-return'
|
|
602
|
+
"""Part type identifier, this is available on all parts as a discriminator."""
|
|
603
|
+
|
|
604
|
+
|
|
585
605
|
error_details_ta = pydantic.TypeAdapter(list[pydantic_core.ErrorDetails], config=pydantic.ConfigDict(defer_build=True))
|
|
586
606
|
|
|
587
607
|
|
|
@@ -723,7 +743,7 @@ class ThinkingPart:
|
|
|
723
743
|
|
|
724
744
|
|
|
725
745
|
@dataclass(repr=False)
|
|
726
|
-
class
|
|
746
|
+
class BaseToolCallPart:
|
|
727
747
|
"""A tool call from a model."""
|
|
728
748
|
|
|
729
749
|
tool_name: str
|
|
@@ -741,9 +761,6 @@ class ToolCallPart:
|
|
|
741
761
|
In case the tool call id is not provided by the model, Pydantic AI will generate a random one.
|
|
742
762
|
"""
|
|
743
763
|
|
|
744
|
-
part_kind: Literal['tool-call'] = 'tool-call'
|
|
745
|
-
"""Part type identifier, this is available on all parts as a discriminator."""
|
|
746
|
-
|
|
747
764
|
def args_as_dict(self) -> dict[str, Any]:
|
|
748
765
|
"""Return the arguments as a Python dictionary.
|
|
749
766
|
|
|
@@ -780,7 +797,29 @@ class ToolCallPart:
|
|
|
780
797
|
__repr__ = _utils.dataclasses_no_defaults_repr
|
|
781
798
|
|
|
782
799
|
|
|
783
|
-
|
|
800
|
+
@dataclass(repr=False)
|
|
801
|
+
class ToolCallPart(BaseToolCallPart):
|
|
802
|
+
"""A tool call from a model."""
|
|
803
|
+
|
|
804
|
+
part_kind: Literal['tool-call'] = 'tool-call'
|
|
805
|
+
"""Part type identifier, this is available on all parts as a discriminator."""
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
@dataclass(repr=False)
|
|
809
|
+
class BuiltinToolCallPart(BaseToolCallPart):
|
|
810
|
+
"""A tool call to a built-in tool."""
|
|
811
|
+
|
|
812
|
+
provider_name: str | None = None
|
|
813
|
+
"""The name of the provider that generated the response."""
|
|
814
|
+
|
|
815
|
+
part_kind: Literal['builtin-tool-call'] = 'builtin-tool-call'
|
|
816
|
+
"""Part type identifier, this is available on all parts as a discriminator."""
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
ModelResponsePart = Annotated[
|
|
820
|
+
Union[TextPart, ToolCallPart, BuiltinToolCallPart, BuiltinToolReturnPart, ThinkingPart],
|
|
821
|
+
pydantic.Discriminator('part_kind'),
|
|
822
|
+
]
|
|
784
823
|
"""A message part returned by a model."""
|
|
785
824
|
|
|
786
825
|
|
|
@@ -1172,6 +1211,29 @@ class FunctionToolResultEvent:
|
|
|
1172
1211
|
__repr__ = _utils.dataclasses_no_defaults_repr
|
|
1173
1212
|
|
|
1174
1213
|
|
|
1214
|
+
@dataclass(repr=False)
|
|
1215
|
+
class BuiltinToolCallEvent:
|
|
1216
|
+
"""An event indicating the start to a call to a built-in tool."""
|
|
1217
|
+
|
|
1218
|
+
part: BuiltinToolCallPart
|
|
1219
|
+
"""The built-in tool call to make."""
|
|
1220
|
+
|
|
1221
|
+
event_kind: Literal['builtin_tool_call'] = 'builtin_tool_call'
|
|
1222
|
+
"""Event type identifier, used as a discriminator."""
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
@dataclass(repr=False)
|
|
1226
|
+
class BuiltinToolResultEvent:
|
|
1227
|
+
"""An event indicating the result of a built-in tool call."""
|
|
1228
|
+
|
|
1229
|
+
result: BuiltinToolReturnPart
|
|
1230
|
+
"""The result of the call to the built-in tool."""
|
|
1231
|
+
|
|
1232
|
+
event_kind: Literal['builtin_tool_result'] = 'builtin_tool_result'
|
|
1233
|
+
"""Event type identifier, used as a discriminator."""
|
|
1234
|
+
|
|
1235
|
+
|
|
1175
1236
|
HandleResponseEvent = Annotated[
|
|
1176
|
-
Union[FunctionToolCallEvent, FunctionToolResultEvent],
|
|
1237
|
+
Union[FunctionToolCallEvent, FunctionToolResultEvent, BuiltinToolCallEvent, BuiltinToolResultEvent],
|
|
1238
|
+
pydantic.Discriminator('event_kind'),
|
|
1177
1239
|
]
|
|
@@ -18,6 +18,7 @@ from typing import Generic, TypeVar, overload
|
|
|
18
18
|
import httpx
|
|
19
19
|
from typing_extensions import Literal, TypeAliasType, TypedDict
|
|
20
20
|
|
|
21
|
+
from pydantic_ai.builtin_tools import AbstractBuiltinTool
|
|
21
22
|
from pydantic_ai.profiles import DEFAULT_PROFILE, ModelProfile, ModelProfileSpec
|
|
22
23
|
|
|
23
24
|
from .. import _utils
|
|
@@ -336,6 +337,7 @@ class ModelRequestParameters:
|
|
|
336
337
|
"""Configuration for an agent's request to a model, specifically related to tools and output handling."""
|
|
337
338
|
|
|
338
339
|
function_tools: list[ToolDefinition] = field(default_factory=list)
|
|
340
|
+
builtin_tools: list[AbstractBuiltinTool] = field(default_factory=list)
|
|
339
341
|
|
|
340
342
|
output_mode: OutputMode = 'text'
|
|
341
343
|
output_object: OutputObjectDefinition | None = None
|
|
@@ -8,12 +8,24 @@ from dataclasses import dataclass, field
|
|
|
8
8
|
from datetime import datetime, timezone
|
|
9
9
|
from typing import Any, Literal, Union, cast, overload
|
|
10
10
|
|
|
11
|
+
from anthropic.types.beta import (
|
|
12
|
+
BetaCitationsDelta,
|
|
13
|
+
BetaCodeExecutionToolResultBlock,
|
|
14
|
+
BetaCodeExecutionToolResultBlockParam,
|
|
15
|
+
BetaInputJSONDelta,
|
|
16
|
+
BetaServerToolUseBlockParam,
|
|
17
|
+
BetaWebSearchToolResultBlockParam,
|
|
18
|
+
)
|
|
11
19
|
from typing_extensions import assert_never
|
|
12
20
|
|
|
21
|
+
from pydantic_ai.builtin_tools import CodeExecutionTool, WebSearchTool
|
|
22
|
+
|
|
13
23
|
from .. import ModelHTTPError, UnexpectedModelBehavior, _utils, usage
|
|
14
24
|
from .._utils import guard_tool_call_id as _guard_tool_call_id
|
|
15
25
|
from ..messages import (
|
|
16
26
|
BinaryContent,
|
|
27
|
+
BuiltinToolCallPart,
|
|
28
|
+
BuiltinToolReturnPart,
|
|
17
29
|
DocumentUrl,
|
|
18
30
|
ImageUrl,
|
|
19
31
|
ModelMessage,
|
|
@@ -33,13 +45,21 @@ from ..profiles import ModelProfileSpec
|
|
|
33
45
|
from ..providers import Provider, infer_provider
|
|
34
46
|
from ..settings import ModelSettings
|
|
35
47
|
from ..tools import ToolDefinition
|
|
36
|
-
from . import
|
|
48
|
+
from . import (
|
|
49
|
+
Model,
|
|
50
|
+
ModelRequestParameters,
|
|
51
|
+
StreamedResponse,
|
|
52
|
+
check_allow_model_requests,
|
|
53
|
+
download_item,
|
|
54
|
+
get_user_agent,
|
|
55
|
+
)
|
|
37
56
|
|
|
38
57
|
try:
|
|
39
58
|
from anthropic import NOT_GIVEN, APIStatusError, AsyncAnthropic, AsyncStream
|
|
40
59
|
from anthropic.types.beta import (
|
|
41
60
|
BetaBase64PDFBlockParam,
|
|
42
61
|
BetaBase64PDFSourceParam,
|
|
62
|
+
BetaCodeExecutionTool20250522Param,
|
|
43
63
|
BetaContentBlock,
|
|
44
64
|
BetaContentBlockParam,
|
|
45
65
|
BetaImageBlockParam,
|
|
@@ -55,6 +75,7 @@ try:
|
|
|
55
75
|
BetaRawMessageStopEvent,
|
|
56
76
|
BetaRawMessageStreamEvent,
|
|
57
77
|
BetaRedactedThinkingBlock,
|
|
78
|
+
BetaServerToolUseBlock,
|
|
58
79
|
BetaSignatureDelta,
|
|
59
80
|
BetaTextBlock,
|
|
60
81
|
BetaTextBlockParam,
|
|
@@ -66,9 +87,13 @@ try:
|
|
|
66
87
|
BetaToolChoiceParam,
|
|
67
88
|
BetaToolParam,
|
|
68
89
|
BetaToolResultBlockParam,
|
|
90
|
+
BetaToolUnionParam,
|
|
69
91
|
BetaToolUseBlock,
|
|
70
92
|
BetaToolUseBlockParam,
|
|
93
|
+
BetaWebSearchTool20250305Param,
|
|
94
|
+
BetaWebSearchToolResultBlock,
|
|
71
95
|
)
|
|
96
|
+
from anthropic.types.beta.beta_web_search_tool_20250305_param import UserLocation
|
|
72
97
|
from anthropic.types.model_param import ModelParam
|
|
73
98
|
|
|
74
99
|
except ImportError as _import_error:
|
|
@@ -218,6 +243,7 @@ class AnthropicModel(Model):
|
|
|
218
243
|
) -> BetaMessage | AsyncStream[BetaRawMessageStreamEvent]:
|
|
219
244
|
# standalone function to make it easier to override
|
|
220
245
|
tools = self._get_tools(model_request_parameters)
|
|
246
|
+
tools += self._get_builtin_tools(model_request_parameters)
|
|
221
247
|
tool_choice: BetaToolChoiceParam | None
|
|
222
248
|
|
|
223
249
|
if not tools:
|
|
@@ -236,6 +262,7 @@ class AnthropicModel(Model):
|
|
|
236
262
|
try:
|
|
237
263
|
extra_headers = model_settings.get('extra_headers', {})
|
|
238
264
|
extra_headers.setdefault('User-Agent', get_user_agent())
|
|
265
|
+
extra_headers.setdefault('anthropic-beta', 'code-execution-2025-05-22')
|
|
239
266
|
return await self.client.beta.messages.create(
|
|
240
267
|
max_tokens=model_settings.get('max_tokens', 4096),
|
|
241
268
|
system=system_prompt or NOT_GIVEN,
|
|
@@ -264,6 +291,24 @@ class AnthropicModel(Model):
|
|
|
264
291
|
for item in response.content:
|
|
265
292
|
if isinstance(item, BetaTextBlock):
|
|
266
293
|
items.append(TextPart(content=item.text))
|
|
294
|
+
elif isinstance(item, (BetaWebSearchToolResultBlock, BetaCodeExecutionToolResultBlock)):
|
|
295
|
+
items.append(
|
|
296
|
+
BuiltinToolReturnPart(
|
|
297
|
+
provider_name='anthropic',
|
|
298
|
+
tool_name=item.type,
|
|
299
|
+
content=item.content,
|
|
300
|
+
tool_call_id=item.tool_use_id,
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
elif isinstance(item, BetaServerToolUseBlock):
|
|
304
|
+
items.append(
|
|
305
|
+
BuiltinToolCallPart(
|
|
306
|
+
provider_name='anthropic',
|
|
307
|
+
tool_name=item.name,
|
|
308
|
+
args=cast(dict[str, Any], item.input),
|
|
309
|
+
tool_call_id=item.id,
|
|
310
|
+
)
|
|
311
|
+
)
|
|
267
312
|
elif isinstance(item, BetaRedactedThinkingBlock): # pragma: no cover
|
|
268
313
|
warnings.warn(
|
|
269
314
|
'Pydantic AI currently does not handle redacted thinking blocks. '
|
|
@@ -302,6 +347,24 @@ class AnthropicModel(Model):
|
|
|
302
347
|
tools += [self._map_tool_definition(r) for r in model_request_parameters.output_tools]
|
|
303
348
|
return tools
|
|
304
349
|
|
|
350
|
+
def _get_builtin_tools(self, model_request_parameters: ModelRequestParameters) -> list[BetaToolUnionParam]:
|
|
351
|
+
tools: list[BetaToolUnionParam] = []
|
|
352
|
+
for tool in model_request_parameters.builtin_tools:
|
|
353
|
+
if isinstance(tool, WebSearchTool):
|
|
354
|
+
user_location = UserLocation(type='approximate', **tool.user_location) if tool.user_location else None
|
|
355
|
+
tools.append(
|
|
356
|
+
BetaWebSearchTool20250305Param(
|
|
357
|
+
name='web_search',
|
|
358
|
+
type='web_search_20250305',
|
|
359
|
+
allowed_domains=tool.allowed_domains,
|
|
360
|
+
blocked_domains=tool.blocked_domains,
|
|
361
|
+
user_location=user_location,
|
|
362
|
+
)
|
|
363
|
+
)
|
|
364
|
+
elif isinstance(tool, CodeExecutionTool): # pragma: no branch
|
|
365
|
+
tools.append(BetaCodeExecutionTool20250522Param(name='code_execution', type='code_execution_20250522'))
|
|
366
|
+
return tools
|
|
367
|
+
|
|
305
368
|
async def _map_message(self, messages: list[ModelMessage]) -> tuple[str, list[BetaMessageParam]]: # noqa: C901
|
|
306
369
|
"""Just maps a `pydantic_ai.Message` to a `anthropic.types.MessageParam`."""
|
|
307
370
|
system_prompt_parts: list[str] = []
|
|
@@ -338,11 +401,26 @@ class AnthropicModel(Model):
|
|
|
338
401
|
if len(user_content_params) > 0:
|
|
339
402
|
anthropic_messages.append(BetaMessageParam(role='user', content=user_content_params))
|
|
340
403
|
elif isinstance(m, ModelResponse):
|
|
341
|
-
assistant_content_params: list[
|
|
404
|
+
assistant_content_params: list[
|
|
405
|
+
BetaTextBlockParam
|
|
406
|
+
| BetaToolUseBlockParam
|
|
407
|
+
| BetaServerToolUseBlockParam
|
|
408
|
+
| BetaWebSearchToolResultBlockParam
|
|
409
|
+
| BetaCodeExecutionToolResultBlockParam
|
|
410
|
+
| BetaThinkingBlockParam
|
|
411
|
+
] = []
|
|
342
412
|
for response_part in m.parts:
|
|
343
413
|
if isinstance(response_part, TextPart):
|
|
344
|
-
if response_part.content:
|
|
414
|
+
if response_part.content:
|
|
345
415
|
assistant_content_params.append(BetaTextBlockParam(text=response_part.content, type='text'))
|
|
416
|
+
elif isinstance(response_part, ToolCallPart):
|
|
417
|
+
tool_use_block_param = BetaToolUseBlockParam(
|
|
418
|
+
id=_guard_tool_call_id(t=response_part),
|
|
419
|
+
type='tool_use',
|
|
420
|
+
name=response_part.tool_name,
|
|
421
|
+
input=response_part.args_as_dict(),
|
|
422
|
+
)
|
|
423
|
+
assistant_content_params.append(tool_use_block_param)
|
|
346
424
|
elif isinstance(response_part, ThinkingPart):
|
|
347
425
|
# NOTE: We only send thinking part back for Anthropic, otherwise they raise an error.
|
|
348
426
|
if response_part.signature is not None: # pragma: no branch
|
|
@@ -351,14 +429,31 @@ class AnthropicModel(Model):
|
|
|
351
429
|
thinking=response_part.content, signature=response_part.signature, type='thinking'
|
|
352
430
|
)
|
|
353
431
|
)
|
|
432
|
+
elif isinstance(response_part, BuiltinToolCallPart):
|
|
433
|
+
if response_part.provider_name == 'anthropic':
|
|
434
|
+
server_tool_use_block_param = BetaServerToolUseBlockParam(
|
|
435
|
+
id=_guard_tool_call_id(t=response_part),
|
|
436
|
+
type='server_tool_use',
|
|
437
|
+
name=cast(Literal['web_search', 'code_execution'], response_part.tool_name),
|
|
438
|
+
input=response_part.args_as_dict(),
|
|
439
|
+
)
|
|
440
|
+
assistant_content_params.append(server_tool_use_block_param)
|
|
441
|
+
elif isinstance(response_part, BuiltinToolReturnPart):
|
|
442
|
+
if response_part.provider_name == 'anthropic':
|
|
443
|
+
tool_use_id = _guard_tool_call_id(t=response_part)
|
|
444
|
+
if response_part.tool_name == 'web_search_tool_result':
|
|
445
|
+
server_tool_result_block_param = BetaWebSearchToolResultBlockParam(
|
|
446
|
+
tool_use_id=tool_use_id, type=response_part.tool_name, content=response_part.content
|
|
447
|
+
)
|
|
448
|
+
elif response_part.tool_name == 'code_execution_tool_result':
|
|
449
|
+
server_tool_result_block_param = BetaCodeExecutionToolResultBlockParam(
|
|
450
|
+
tool_use_id=tool_use_id, type=response_part.tool_name, content=response_part.content
|
|
451
|
+
)
|
|
452
|
+
else:
|
|
453
|
+
raise ValueError(f'Unsupported tool name: {response_part.tool_name}')
|
|
454
|
+
assistant_content_params.append(server_tool_result_block_param)
|
|
354
455
|
else:
|
|
355
|
-
|
|
356
|
-
id=_guard_tool_call_id(t=response_part),
|
|
357
|
-
type='tool_use',
|
|
358
|
-
name=response_part.tool_name,
|
|
359
|
-
input=response_part.args_as_dict(),
|
|
360
|
-
)
|
|
361
|
-
assistant_content_params.append(tool_use_block_param)
|
|
456
|
+
assert_never(response_part)
|
|
362
457
|
if len(assistant_content_params) > 0:
|
|
363
458
|
anthropic_messages.append(BetaMessageParam(role='assistant', content=assistant_content_params))
|
|
364
459
|
else:
|
|
@@ -476,7 +571,10 @@ class AnthropicStreamedResponse(StreamedResponse):
|
|
|
476
571
|
async for event in self._response:
|
|
477
572
|
self._usage += _map_usage(event)
|
|
478
573
|
|
|
479
|
-
if isinstance(event,
|
|
574
|
+
if isinstance(event, BetaRawMessageStartEvent):
|
|
575
|
+
pass
|
|
576
|
+
|
|
577
|
+
elif isinstance(event, BetaRawContentBlockStartEvent):
|
|
480
578
|
current_block = event.content_block
|
|
481
579
|
if isinstance(current_block, BetaTextBlock) and current_block.text:
|
|
482
580
|
maybe_event = self._parts_manager.handle_text_delta(
|
|
@@ -499,6 +597,8 @@ class AnthropicStreamedResponse(StreamedResponse):
|
|
|
499
597
|
)
|
|
500
598
|
if maybe_event is not None: # pragma: no branch
|
|
501
599
|
yield maybe_event
|
|
600
|
+
elif isinstance(current_block, BetaServerToolUseBlock):
|
|
601
|
+
pass
|
|
502
602
|
|
|
503
603
|
elif isinstance(event, BetaRawContentBlockDeltaEvent):
|
|
504
604
|
if isinstance(event.delta, BetaTextDelta):
|
|
@@ -528,8 +628,16 @@ class AnthropicStreamedResponse(StreamedResponse):
|
|
|
528
628
|
)
|
|
529
629
|
if maybe_event is not None: # pragma: no branch
|
|
530
630
|
yield maybe_event
|
|
631
|
+
elif isinstance(event.delta, BetaInputJSONDelta):
|
|
632
|
+
pass
|
|
633
|
+
# TODO(Marcelo): We need to handle citations.
|
|
634
|
+
elif isinstance(event.delta, BetaCitationsDelta):
|
|
635
|
+
pass
|
|
636
|
+
|
|
637
|
+
elif isinstance(event, BetaRawMessageDeltaEvent):
|
|
638
|
+
pass
|
|
531
639
|
|
|
532
|
-
elif isinstance(event, (BetaRawContentBlockStopEvent, BetaRawMessageStopEvent)):
|
|
640
|
+
elif isinstance(event, (BetaRawContentBlockStopEvent, BetaRawMessageStopEvent)): # pragma: no branch
|
|
533
641
|
current_block = None
|
|
534
642
|
|
|
535
643
|
@property
|