You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/agents.md
+44-42Lines changed: 44 additions & 42 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,10 +8,10 @@ but multiple agents can also interact to embody more complex workflows.
8
8
The [`Agent`][pydantic_ai.Agent] class has full API documentation, but conceptually you can think of an agent as a container for:
9
9
10
10
* A [system prompt](#system-prompts) — a set of instructions for the LLM written by the developer
11
-
* One or more [retrievers](#retrievers) — functions that the LLM may call to get information while generating a response
11
+
* One or more [retrieval tool](#tools) — functions that the LLM may call to get information while generating a response
12
12
* An optional structured [result type](results.md) — the structured datatype the LLM must return at the end of a run
13
-
* A [dependency](dependencies.md) type constraint — system prompt functions, retrievers and result validators may all use dependencies when they're run
14
-
* Agents may optionally also have a default [model](api/models/base.md) associated with them; the model to use can also be specified when running the agent
13
+
* A [dependency](dependencies.md) type constraint — system prompt functions, tools and result validators may all use dependencies when they're run
14
+
* Agents may optionally also have a default [LLM model](api/models/base.md) associated with them; the model to use can also be specified when running the agent
15
15
16
16
In typing terms, agents are generic in their dependency and result types, e.g., an agent which required dependencies of type `#!python Foobar` and returned results of type `#!python list[str]` would have type `#!python Agent[Foobar, list[str]]`.
1. Create an agent, which expects an integer dependency and returns a boolean result. This agent will have type `#!python Agent[int, bool]`.
52
-
2. Define a retriever that checks if the square is a winner. Here [`CallContext`][pydantic_ai.dependencies.CallContext] is parameterized with the dependency type `int`; if you got the dependency type wrong you'd get a typing error.
52
+
2. Define a tool that checks if the square is a winner. Here [`CallContext`][pydantic_ai.dependencies.CallContext] is parameterized with the dependency type `int`; if you got the dependency type wrong you'd get a typing error.
53
53
3. In reality, you might want to use a random number here e.g. `random.randint(0, 36)`.
54
54
4.`result.data` will be a boolean indicating if the square is a winner. Pydantic performs the result validation, it'll be typed as a `bool` since its type is derived from the `result_type` generic parameter of the agent.
55
55
@@ -166,23 +166,23 @@ print(result.data)
166
166
167
167
_(This example is complete, it can be run "as is")_
168
168
169
-
## Retrievers
169
+
## Function Tools
170
170
171
-
Retrievers provide a mechanism for models to request extra information to help them generate a response.
171
+
Function tools provide a mechanism for models to retrieve extra information to help them generate a response.
172
172
173
173
They're useful when it is impractical or impossible to put all the context an agent might need into the system prompt, or when you want to make agents' behavior more deterministic or reliable by deferring some of the logic required to generate a response to another (not necessarily AI-powered) tool.
174
174
175
-
!!! info "Retrievers vs. RAG"
176
-
Retrievers are basically the "R" of RAG (Retrieval-Augmented Generation) — they augment what the model can do by letting it request extra information.
175
+
!!! info "Function tools vs. RAG"
176
+
Function tools are basically the "R" of RAG (Retrieval-Augmented Generation) — they augment what the model can do by letting it request extra information.
177
177
178
-
The main semantic difference between PydanticAI Retrievers and RAG is RAG is synonymous with vector search, while PydanticAI retrievers are more general-purpose. (Note: we may add support for vector search functionality in the future, particularly an API for generating embeddings. See [#58](https://github.com/pydantic/pydantic-ai/issues/58))
178
+
The main semantic difference between PydanticAI Tools and RAG is RAG is synonymous with vector search, while PydanticAI tools are more general-purpose. (Note: we may add support for vector search functionality in the future, particularly an API for generating embeddings. See [#58](https://github.com/pydantic/pydantic-ai/issues/58))
179
179
180
-
There are two different decorator functions to register retrievers:
180
+
There are two different decorator functions to register tools:
181
181
182
-
1.[`@agent.retriever_plain`][pydantic_ai.Agent.retriever_plain] — for retrievers that don't need access to the agent [context][pydantic_ai.dependencies.CallContext]
183
-
2.[`@agent.retriever`][pydantic_ai.Agent.retriever] — for retrievers that do need access to the agent [context][pydantic_ai.dependencies.CallContext]
182
+
1.[`@agent.tool`][pydantic_ai.Agent.tool] — for tools that need access to the agent [context][pydantic_ai.dependencies.CallContext]
183
+
2.[`@agent.tool_plain`][pydantic_ai.Agent.tool_plain] — for tools that do not need access to the agent [context][pydantic_ai.dependencies.CallContext]
184
184
185
-
`@agent.retriever` is the default since in the majority of cases retrievers will need access to the agent context.
185
+
`@agent.tool` is the default since in the majority of cases tools will need access to the agent context.
186
186
187
187
Here's an example using both:
188
188
@@ -202,13 +202,13 @@ agent = Agent(
202
202
)
203
203
204
204
205
-
@agent.retriever_plain# (3)!
205
+
@agent.tool_plain# (3)!
206
206
defroll_die() -> str:
207
207
"""Roll a six-sided die and return the result."""
208
208
returnstr(random.randint(1, 6))
209
209
210
210
211
-
@agent.retriever# (4)!
211
+
@agent.tool# (4)!
212
212
defget_player_name(ctx: CallContext[str]) -> str:
213
213
"""Get the player's name."""
214
214
return ctx.deps
@@ -221,8 +221,8 @@ print(dice_result.data)
221
221
222
222
1. This is a pretty simple task, so we can use the fast and cheap Gemini flash model.
223
223
2. We pass the user's name as the dependency, to keep things simple we use just the name as a string as the dependency.
224
-
3. This retriever doesn't need any context, it just returns a random number. You could probably use a dynamic system prompt in this case.
225
-
4. This retriever needs the player's name, so it uses `CallContext` to access dependencies which are just the player's name in this case.
224
+
3. This tool doesn't need any context, it just returns a random number. You could probably use a dynamic system prompt in this case.
225
+
4. This tool needs the player's name, so it uses `CallContext` to access dependencies which are just the player's name in this case.
226
226
5. Run the agent, passing the player's name as the dependency.
227
227
228
228
_(This example is complete, it can be run "as is")_
@@ -297,19 +297,19 @@ sequenceDiagram
297
297
Note over Agent: Send prompts
298
298
Agent ->> LLM: System: "You're a dice game..."<br>User: "My guess is 4"
299
299
activate LLM
300
-
Note over LLM: LLM decides to use<br>a retriever
300
+
Note over LLM: LLM decides to use<br>a tool
301
301
302
-
LLM ->> Agent: Call retriever<br>roll_die()
302
+
LLM ->> Agent: Call tool<br>roll_die()
303
303
deactivate LLM
304
304
activate Agent
305
305
Note over Agent: Rolls a six-sided die
306
306
307
307
Agent -->> LLM: ToolReturn<br>"4"
308
308
deactivate Agent
309
309
activate LLM
310
-
Note over LLM: LLM decides to use<br>another retriever
Under the hood, retrievers use the model's "tools" or "functions" API to let the model know what retrievers are available to call. Tools or functions are also used to define the schema(s) for structured responses, thus a model might have access to many tools, some of which call retrievers while others end the run and return a result.
328
+
As the name suggests, function tools use the model's "tools" or "functions" API to let the model know what is available to call. Tools or functions are also used to define the schema(s) for structured responses, thus a model might have access to many tools, some of which call function tools while others end the run and return a result.
329
+
330
+
### Function tools and schema
329
331
330
332
Function parameters are extracted from the function signature, and all parameters except `CallContext` are used to build the schema for that tool call.
331
333
332
-
Even better, PydanticAI extracts the docstring from retriever functions and (thanks to [griffe](https://mkdocstrings.github.io/griffe/)) extracts parameter descriptions from the docstring and adds them to the schema.
334
+
Even better, PydanticAI extracts the docstring from functions and (thanks to [griffe](https://mkdocstrings.github.io/griffe/)) extracts parameter descriptions from the docstring and adds them to the schema.
333
335
334
336
[Griffe supports](https://mkdocstrings.github.io/griffe/reference/docstrings/#docstrings) extracting parameter descriptions from `google`, `numpy` and `sphinx` style docstrings, and PydanticAI will infer the format to use based on the docstring. We plan to add support in the future to explicitly set the style to use, and warn/error if not all parameters are documented; see [#59](https://github.com/pydantic/pydantic-ai/issues/59).
335
337
336
-
To demonstrate a retriever's schema, here we use [`FunctionModel`][pydantic_ai.models.function.FunctionModel] to print the schema a model would receive:
338
+
To demonstrate a tool's schema, here we use [`FunctionModel`][pydantic_ai.models.function.FunctionModel] to print the schema a model would receive:
337
339
338
-
```py title="retriever_schema.py"
340
+
```py title="tool_schema.py"
339
341
from pydantic_ai import Agent
340
342
from pydantic_ai.messages import Message, ModelAnyResponse, ModelTextResponse
341
343
from pydantic_ai.models.function import AgentInfo, FunctionModel
_(This example is complete, it can be run "as is")_
388
390
389
-
The return type of retriever can be any valid JSON object ([`JsonData`][pydantic_ai.dependencies.JsonData]) as some models (e.g. Gemini) support semi-structured return values, some expect text (OpenAI) but seem to be just as good at extracting meaning from the data. If a Python object is returned and the model expects a string, the value will be serialized to JSON.
391
+
The return type of tool can be any valid JSON object ([`JsonData`][pydantic_ai.dependencies.JsonData]) as some models (e.g. Gemini) support semi-structured return values, some expect text (OpenAI) but seem to be just as good at extracting meaning from the data. If a Python object is returned and the model expects a string, the value will be serialized to JSON.
390
392
391
-
If a retriever has a single parameter that can be represented as an object in JSON schema (e.g. dataclass, TypedDict, pydantic model), the schema for the retriever is simplified to be just that object. (TODO example)
393
+
If a tool has a single parameter that can be represented as an object in JSON schema (e.g. dataclass, TypedDict, pydantic model), the schema for the tool is simplified to be just that object. (TODO example)
392
394
393
395
## Reflection and self-correction
394
396
395
-
Validation errors from both retriever parameter validation and [structured result validation](results.md#structured-result-validation) can be passed back to the model with a request to retry.
397
+
Validation errors from both tool parameter validation and [structured result validation](results.md#structured-result-validation) can be passed back to the model with a request to retry.
396
398
397
-
You can also raise [`ModelRetry`][pydantic_ai.exceptions.ModelRetry] from within a [retriever](#retrievers) or [result validator function](results.md#result-validators-functions) to tell the model it should retry generating a response.
399
+
You can also raise [`ModelRetry`][pydantic_ai.exceptions.ModelRetry] from within a [tool](#tools) or [result validator function](results.md#result-validators-functions) to tell the model it should retry generating a response.
398
400
399
-
- The default retry count is **1** but can be altered for the [entire agent][pydantic_ai.Agent.__init__], a [specific retriever][pydantic_ai.Agent.retriever], or a [result validator][pydantic_ai.Agent.__init__].
400
-
- You can access the current retry count from within a retriever or result validator via [`ctx.retry`][pydantic_ai.dependencies.CallContext].
401
+
- The default retry count is **1** but can be altered for the [entire agent][pydantic_ai.Agent.__init__], a [specific tool][pydantic_ai.Agent.tool], or a [result validator][pydantic_ai.Agent.__init__].
402
+
- You can access the current retry count from within a tool or result validator via [`ctx.retry`][pydantic_ai.dependencies.CallContext].
Copy file name to clipboardExpand all lines: docs/dependencies.md
+7-8Lines changed: 7 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,13 +1,12 @@
1
1
# Dependencies
2
2
3
-
PydanticAI uses a dependency injection system to provide data and services to your agent's [system prompts](agents.md#system-prompts), [retrievers](agents.md#retrievers) and [result validators](results.md#result-validators-functions).
3
+
PydanticAI uses a dependency injection system to provide data and services to your agent's [system prompts](agents.md#system-prompts), [tools](agents.md#tools) and [result validators](results.md#result-validators-functions).
4
4
5
5
Matching PydanticAI's design philosophy, our dependency system tries to use existing best practice in Python development rather than inventing esoteric "magic", this should make dependencies type-safe, understandable easier to test and ultimately easier to deploy in production.
6
6
7
7
## Defining Dependencies
8
8
9
-
Dependencies can be any python type. While in simple cases you might be able to pass a single object
10
-
as a dependency (e.g. an HTTP connection), [dataclasses][] are generally a convenient container when your dependencies included multiple objects.
9
+
Dependencies can be any python type. While in simple cases you might be able to pass a single object as a dependency (e.g. an HTTP connection), [dataclasses][] are generally a convenient container when your dependencies included multiple objects.
11
10
12
11
Here's an example of defining an agent that requires dependencies.
13
12
@@ -102,7 +101,7 @@ _(This example is complete, it can be run "as is")_
102
101
103
102
### Asynchronous vs. Synchronous dependencies
104
103
105
-
System prompt functions, retriever functions and result validator are all run in the async context of an agent run.
104
+
[System prompt functions](agents.md#system-prompts), [function tools](agents.md#function-tools) and [result validators](results.md#result-validators-functions) are all run in the async context of an agent run.
106
105
107
106
If these functions are not coroutines (e.g. `async def`) they are called with
108
107
[`run_in_executor`][asyncio.loop.run_in_executor] in a thread pool, it's therefore marginally preferable
@@ -159,7 +158,7 @@ _(This example is complete, it can be run "as is")_
159
158
160
159
## Full Example
161
160
162
-
As well as system prompts, dependencies can be used in [retrievers](agents.md#retrievers) and [result validators](results.md#result-validators-functions).
161
+
As well as system prompts, dependencies can be used in [tools](agents.md#tools) and [result validators](results.md#result-validators-functions).
0 commit comments