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
+24-23Lines changed: 24 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,15 +5,15 @@ Agents are PydanticAI's primary interface for interacting with LLMs.
5
5
In some use cases a single Agent will control an entire application or component,
6
6
but multiple agents can also interact to embody more complex workflows.
7
7
8
-
The [`Agent`][pydantic_ai.Agent] class is well documented, but in essence you can think of an agent as a container for:
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
11
* One or more [retrievers](#retrievers) — 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
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 defined when running the agent
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
15
15
16
-
In typing terms, agents are generic in their dependency and result types, e.g. an agent which required `#!python Foobar`dependencies and returned data of type `#!python list[str]` results would have type `#!python Agent[Foobar, list[str]]`.
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]]`.
17
17
18
18
Here's a toy example of an agent that simulates a roulette wheel:
19
19
@@ -25,7 +25,7 @@ roulette_agent = Agent( # (1)!
25
25
deps_type=int,
26
26
result_type=bool,
27
27
system_prompt=(
28
-
'Use the `roulette_wheel` to see if the '
28
+
'Use the `roulette_wheel` function to see if the '
29
29
'customer has won based on the number they provide.'
30
30
),
31
31
)
@@ -48,21 +48,22 @@ print(result.data)
48
48
#> False
49
49
```
50
50
51
-
1. Create an agent, which expects an integer dependency and returns a boolean result, this agent will ahve type of`#!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.
53
-
3. In reality, you might want to use a random number here e.g. `random.randint(0, 36)` here.
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.
51
+
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.
53
+
3. In reality, you might want to use a random number here e.g. `random.randint(0, 36)`.
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
56
-
!!! tip "Agents are Singletons, like FastAPI"
57
-
Agents are a singleton instance, you can think of them as similar to a small [`FastAPI`][fastapi.FastAPI] app or an [`APIRouter`][fastapi.APIRouter].
56
+
57
+
!!! tip "Agents are designed for reuse, like FastAPI Apps"
58
+
Agents are intended to be instantiated once (frequently as module globals) and reused throughout your application, similar to a small [FastAPI][fastapi.FastAPI] app or an [APIRouter][fastapi.APIRouter].
58
59
59
60
## Running Agents
60
61
61
62
There are three ways to run an agent:
62
63
63
-
1.[`agent.run()`][pydantic_ai.Agent.run] — a coroutine which returns a result containing a completed response, returns a [`RunResult`][pydantic_ai.result.RunResult]
64
-
2.[`agent.run_sync()`][pydantic_ai.Agent.run_sync] — a plainfunction which returns a result containing a completed response (internally, this just calls `asyncio.run(self.run())`), returns a [`RunResult`][pydantic_ai.result.RunResult]
65
-
3.[`agent.run_stream()`][pydantic_ai.Agent.run_stream] — a coroutine which returns a result containing methods to stream a response as an async iterable, returns a [`StreamedRunResult`][pydantic_ai.result.StreamedRunResult]
64
+
1.[`agent.run()`][pydantic_ai.Agent.run] — a coroutine which returns a [`RunResult`][pydantic_ai.result.RunResult] containing a completed response
65
+
2.[`agent.run_sync()`][pydantic_ai.Agent.run_sync] — a plain, synchronous function which returns a [`RunResult`][pydantic_ai.result.RunResult] containing a completed response (internally, this just calls `asyncio.run(self.run())`)
66
+
3.[`agent.run_stream()`][pydantic_ai.Agent.run_stream] — a coroutine which returns a [`StreamedRunResult`][pydantic_ai.result.StreamedRunResult], which contains methods to stream a response as an async iterable
66
67
67
68
Here's a simple example demonstrating all three:
68
69
@@ -114,7 +115,7 @@ print(result2.data)
114
115
#> Albert Einstein's most famous equation is (E = mc^2).
115
116
```
116
117
117
-
1. Continue the conversation, without `message_history` the model would not know who "his" was referring to.
118
+
1. Continue the conversation; without `message_history` the model would not know who "his" was referring to.
118
119
119
120
_(This example is complete, it can be run "as is")_
120
121
@@ -125,9 +126,9 @@ System prompts might seem simple at first glance since they're just strings (or
125
126
Generally, system prompts fall into two categories:
126
127
127
128
1.**Static system prompts**: These are known when writing the code and can be defined via the `system_prompt` parameter of the [`Agent` constructor][pydantic_ai.Agent.__init__].
128
-
2.**Dynamic system prompts**: These aren't known until runtime and should be defined via functions decorated with [`@agent.system_prompt`][pydantic_ai.Agent.system_prompt].
129
+
2.**Dynamic system prompts**: These depend in some way on context that isn't known until runtime, and should be defined via functions decorated with [`@agent.system_prompt`][pydantic_ai.Agent.system_prompt].
129
130
130
-
You can add both to a single agent; they're concatenated in the order they're defined at runtime.
131
+
You can add both to a single agent; they're appended in the order they're defined at runtime.
131
132
132
133
Here's an example using both types of system prompts:
133
134
@@ -169,12 +170,12 @@ _(This example is complete, it can be run "as is")_
169
170
170
171
Retrievers provide a mechanism for models to request extra information to help them generate a response.
171
172
172
-
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 by deferring some of the logic required to generate a response to another tool.
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.
173
174
174
175
!!! info "Retrievers vs. RAG"
175
176
Retrievers are basically the "R" of RAG (Retrieval-Augmented Generation) — they augment what the model can do by letting it request extra information.
176
177
177
-
The main semantic difference between PydanticAI Retreivers and RAG is RAG is synonymous with vector search, while PydanticAI retrievers are more generalpurpose. (Note: we might add support for some vector search functionality in the future, particuarly an API for generating embeddings, see [#58](https://github.com/pydantic/pydantic-ai/issues/58))
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
179
179
180
There are two different decorator functions to register retrievers:
180
181
@@ -328,11 +329,11 @@ Under the hood, retrievers use the model's "tools" or "functions" API to let the
328
329
329
330
Function parameters are extracted from the function signature, and all parameters except `CallContext` are used to build the schema for that tool call.
330
331
331
-
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 add them to the schema.
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.
332
333
333
-
[Griffe supports](https://mkdocstrings.github.io/griffe/reference/docstrings/#docstrings) extracting parameter descriptions from `google`, `numpy` and `sphinx` style docstrings, PydanticAI will infer the format to use based on the docstring. We'll add support in 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).
334
+
[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).
334
335
335
-
To demonstrate retriever schema, here we use [`FunctionModel`][pydantic_ai.models.function.FunctionModel] to print the schema a model would receive:
336
+
To demonstrate a retriever's schema, here we use [`FunctionModel`][pydantic_ai.models.function.FunctionModel] to print the schema a model would receive:
_(This example is complete, it can be run "as is")_
387
388
388
-
The return type of retriever can 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 is returned and the model expects a string, the value will be serialized to JSON.
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.
389
390
390
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)
391
392
392
393
## Reflection and self-correction
393
394
394
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.
395
396
396
-
You can also raise [`ModelRetry`][pydantic_ai.exceptions.ModelRetry] from within a [retriever](#retrievers) or [result validator functions](results.md#result-validators-functions) to tell the model it should retry.
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.
397
398
398
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__].
399
400
- You can access the current retry count from within a retriever or result validator via [`ctx.retry`][pydantic_ai.dependencies.CallContext].
0 commit comments