Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit490c3b4

Browse files
authored
Toolsets public interface and docs tweaks (#2241)
1 parent0b3bf86 commit490c3b4

File tree

7 files changed

+27
-31
lines changed

7 files changed

+27
-31
lines changed

‎docs/toolsets.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,7 @@ print(test_model.last_model_request_parameters.function_tools)
334334

335335
[`WrapperToolset`][pydantic_ai.toolsets.WrapperToolset] wraps another toolset and delegates all responsibility to it.
336336

337-
To easily chain different modifications, you can also call[`wrap()`][pydantic_ai.toolsets.AbstractToolset.wrap] on any toolset instead of directly constructing an instance of (a subclass of)`WrapperToolset`.
338-
339-
`WrapperToolset` is a no-op by default, but enables some useful abilities:
337+
It is is a no-op by default, but enables some useful abilities:
340338

341339
####Changing Tool Execution
342340

@@ -367,7 +365,7 @@ class LoggingToolset(WrapperToolset):
367365
return result
368366

369367

370-
logging_toolset=prepared_toolset.wrap(LoggingToolset)
368+
logging_toolset= LoggingToolset(prepared_toolset)
371369

372370
agent= Agent(TestModel(),toolsets=[logging_toolset])# (1)!
373371
result= agent.run_sync('Call all the tools')
@@ -438,14 +436,17 @@ If you want to reuse a network connection or session across tool listings and ca
438436

439437
###Deferred Toolset
440438

441-
A deferred tool is one that will be executed not by Pydantic AI, but by the upstream service that called the agent, such as a web application that supports frontend-defined tools provided to Pydantic AI via a protocol like[AG-UI](https://docs.ag-ui.com/concepts/tools#frontend-defined-tools).
439+
A deferred tool is one whose result will be produced outside of the Pydantic AI agent run in which it was called, because it depends on an upstream service (or user) or could take longer to generate than it's reasonable to keep the agent process running.
440+
441+
Deferred tools enable various use cases:
442442

443-
!!! note
444-
This is not typically something you need to bother with, unless you are implementing support for such a protocol between an upstream tool provider and Pydantic AI.
443+
- Support client-side tools implemented by a web or app frontend
444+
- Implement a Human-in-the-Loop flow where the user needs to explicitly provide an "answer" before the run can continue
445+
- Pass slow tasks off to a background worker or external service that will send a (webhook) notification when the result is ready and the agent run can be continued.
445446

446-
When the model calls a deferred tool, the agent run ends with a[`DeferredToolCalls`][pydantic_ai.output.DeferredToolCalls] object containing the deferred tool call names and arguments, whichis expected to be returned to theupstream tool provider. This upstreamserviceis then expected to generate a response for each tool call and starta new Pydantic AI agent run with the message historyand new[`ToolReturnPart`s][pydantic_ai.messages.ToolReturnPart] corresponding to each deferred call, after which the run will continue.
447+
When the model calls a deferred tool, the agent run ends with a[`DeferredToolCalls`][pydantic_ai.output.DeferredToolCalls] object containing the deferred tool call names and arguments, whichare expected to be returned to the servicethat will (eventually) produce the result(s). Once all the results are ready,a new Pydantic AI agent runcan then be startedwith theoriginal run'smessage historyplus new[`ToolReturnPart`s][pydantic_ai.messages.ToolReturnPart] (or[`RetryPromptPart`s][pydantic_ai.messages.RetryPromptPart] in case of failure) corresponding to each deferred call, after which the run will continue.
447448

448-
To enable an agent to call deferred tools, you create a[`DeferredToolset`][pydantic_ai.toolsets.DeferredToolset], pass it a list of[`ToolDefinition`s][pydantic_ai.tools.ToolDefinition], and provide it to the agent using one of the methods described above. Additionally, you need to add`DeferredToolCalls` to the`Agent`'s[output types](output.md#structured-output) so that the agent run's outputtype iscorrectly inferred. Finally, you should handle the possible`DeferredToolCalls`result byreturning it to theupstream tool provider.
449+
To enable an agent to call deferred tools, you create a[`DeferredToolset`][pydantic_ai.toolsets.DeferredToolset], pass it a list of[`ToolDefinition`s][pydantic_ai.tools.ToolDefinition], and provide it to the agent using one of the methods described above. Additionally, you need to add`DeferredToolCalls` to the`Agent`'s[`output_type`](output.md#structured-output) so that thepossible types of theagent run outputarecorrectly inferred. Finally, you should handle the possible`DeferredToolCalls`output bypassing it to theservice that will produce the results.
449450

450451
If your agent can also be used in a context where no deferred tools are available, you will not want to include`DeferredToolCalls` in the`output_type` passed to the`Agent` constructor as you'd have to deal with that type everywhere you use the agent. Instead, you can pass the`toolsets` and`output_type` keyword arguments when you run the agent using[`agent.run()`][pydantic_ai.Agent.run],[`agent.run_sync()`][pydantic_ai.Agent.run_sync],[`agent.run_stream()`][pydantic_ai.Agent.run_stream], or[`agent.iter()`][pydantic_ai.Agent.iter]. Note that while`toolsets` provided at this stage are additional to the toolsets provided to the constructor, the`output_type` overrides the one specified at construction time (for type inference reasons), so you'll need to include the original output types explicitly.
451452

@@ -482,7 +483,7 @@ print(repr(result.output))
482483
#> PersonalizedGreeting(greeting='Hello, David!', language_code='en-US')
483484
```
484485

485-
Next, let's definean functionfora hypothetical "run agent" API endpoint that can be called by the frontend and takes a list of messages to send to the model plus adict of frontend toolnames and descriptions. This is where`DeferredToolset` and`DeferredToolCalls` come in:
486+
Next, let's definea functionthat representsa hypothetical "run agent" API endpoint that can be called by the frontend and takes a list of messages to send to the model plus alist of frontend tooldefinitions. This is where`DeferredToolset` and`DeferredToolCalls` come in:
486487

487488
```python {title="deferred_toolset_api.py" requires="deferred_toolset_agent.py"}
488489
from deferred_toolset_agentimport agent, PersonalizedGreeting
@@ -526,8 +527,10 @@ frontend_tool_definitions = [
526527
description="Get the user's preferred language from their browser",
527528
)
528529
]
530+
529531
defget_preferred_language(default_language:str) ->str:
530532
return'es-MX'# (1)!
533+
531534
frontend_tool_functions= {'get_preferred_language': get_preferred_language}
532535

533536
messages: list[ModelMessage]= [
@@ -578,7 +581,7 @@ PersonalizedGreeting(greeting='Hola, David! Espero que tengas un gran día!', la
578581
"""
579582
```
580583

581-
1. Imagine that this returns[`navigator.language`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language)
584+
1. Imagine that this returnsthe frontend[`navigator.language`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language).
582585

583586
_(This example is complete, it can be run "as is")_
584587

‎pydantic_ai_slim/pydantic_ai/output.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,10 @@ def __get_pydantic_json_schema__(
361361

362362
@dataclass
363363
classDeferredToolCalls:
364-
"""Container for calls of deferred tools. This can be used as an agent's `output_type` and will be used as the output of the agent run if the model called any deferred tools."""
364+
"""Container for calls of deferred tools. This can be used as an agent's `output_type` and will be used as the output of the agent run if the model called any deferred tools.
365+
366+
See [deferred toolset docs](../toolsets.md#deferred-toolset) for more information.
367+
"""
365368

366369
tool_calls:list[ToolCallPart]
367370
tool_defs:dict[str,ToolDefinition]

‎pydantic_ai_slim/pydantic_ai/tools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,9 +365,9 @@ class ToolDefinition:
365365
kind:ToolKind=field(default='function')
366366
"""The kind of tool:
367367
368-
- `'function'`: a tool thatcan be executed by Pydantic AI and has its result returned to the model
368+
- `'function'`: a tool thatwill be executed by Pydantic AI during an agent run and has its result returned to the model
369369
- `'output'`: a tool that passes through an output value that ends the run
370-
- `'deferred'`: a toolthatwill beexecuted not byPydantic AI, but by the upstream service that called the agent, such as a web application that supports frontend-defined tools providedtoPydantic AI via e.g. [AG-UI](https://docs.ag-ui.com/concepts/tools#frontend-defined-tools).
370+
- `'deferred'`: a toolwhose resultwill beproduced outside of thePydantic AI agent run in which it was called, because it depends on an upstream service (or user) or could take longertogenerate than it's reasonable to keep the agent process running.
371371
When the model calls a deferred tool, the agent run ends with a `DeferredToolCalls` object and a new run is expected to be started at a later point with the message history and new `ToolReturnPart`s corresponding to each deferred call.
372372
"""
373373

‎pydantic_ai_slim/pydantic_ai/toolsets/abstract.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
fromabcimportABC,abstractmethod
44
fromdataclassesimportdataclass
5-
fromtypingimportTYPE_CHECKING,Any,Callable,Generic,Literal,Protocol,TypeVar
5+
fromtypingimportTYPE_CHECKING,Any,Callable,Generic,Literal,Protocol
66

77
frompydantic_coreimportSchemaValidator
88
fromtyping_extensionsimportSelf
@@ -15,9 +15,6 @@
1515
from .prefixedimportPrefixedToolset
1616
from .preparedimportPreparedToolset
1717
from .renamedimportRenamedToolset
18-
from .wrapperimportWrapperToolset
19-
20-
WrapperT=TypeVar('WrapperT',bound='WrapperToolset[Any]')
2118

2219

2320
classSchemaValidatorProt(Protocol):
@@ -115,9 +112,9 @@ async def call_tool(
115112
"""
116113
raiseNotImplementedError()
117114

118-
defapply(self,visitor:Callable[[AbstractToolset[AgentDepsT]],Any])->Any:
115+
defapply(self,visitor:Callable[[AbstractToolset[AgentDepsT]],None])->None:
119116
"""Run a visitor function on all concrete toolsets that are not wrappers (i.e. they implement their own tool listing and calling)."""
120-
returnvisitor(self)
117+
visitor(self)
121118

122119
deffiltered(
123120
self,filter_func:Callable[[RunContext[AgentDepsT],ToolDefinition],bool]
@@ -156,10 +153,3 @@ def renamed(self, name_map: dict[str, str]) -> RenamedToolset[AgentDepsT]:
156153
from .renamedimportRenamedToolset
157154

158155
returnRenamedToolset(self,name_map)
159-
160-
defwrap(self,wrapper_cls:type[WrapperT],*args:Any,**kwargs:Any)->WrapperT:
161-
"""Returns an instance of the provided wrapper class wrapping this toolset, with all arguments passed to the wrapper class constructor.
162-
163-
See [toolset docs](../toolsets.md#wrapping-a-toolset) for more information.
164-
"""
165-
returnwrapper_cls(self,*args,**kwargs)

‎pydantic_ai_slim/pydantic_ai/toolsets/combined.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,6 @@ async def call_tool(
8383
assertisinstance(tool,_CombinedToolsetTool)
8484
returnawaittool.source_toolset.call_tool(name,tool_args,ctx,tool.source_tool)
8585

86-
defapply(self,visitor:Callable[[AbstractToolset[AgentDepsT]],Any])->Any:
86+
defapply(self,visitor:Callable[[AbstractToolset[AgentDepsT]],None])->None:
8787
fortoolsetinself.toolsets:
8888
toolset.apply(visitor)

‎pydantic_ai_slim/pydantic_ai/toolsets/deferred.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
@dataclass
1616
classDeferredToolset(AbstractToolset[AgentDepsT]):
17-
"""A toolset that holds deferred toolsthatwill becalled bytheupstream service that called the agent.
17+
"""A toolset that holds deferred toolswhose resultswill beproduced outside ofthePydantic AI agent run in which they were called.
1818
1919
See [toolset docs](../toolsets.md#deferred-toolset), [`ToolDefinition.kind`][pydantic_ai.tools.ToolDefinition.kind], and [`DeferredToolCalls`][pydantic_ai.output.DeferredToolCalls] for more information.
2020
"""

‎pydantic_ai_slim/pydantic_ai/toolsets/wrapper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ async def call_tool(
3333
)->Any:
3434
returnawaitself.wrapped.call_tool(name,tool_args,ctx,tool)
3535

36-
defapply(self,visitor:Callable[[AbstractToolset[AgentDepsT]],Any])->Any:
37-
returnself.wrapped.apply(visitor)
36+
defapply(self,visitor:Callable[[AbstractToolset[AgentDepsT]],None])->None:
37+
self.wrapped.apply(visitor)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp