Skip to content

Commit 7776dc5

Browse files
authored
More minor cleanup (#77)
1 parent 83be345 commit 7776dc5

File tree

3 files changed

+26
-25
lines changed

3 files changed

+26
-25
lines changed

docs/agents.md

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ Agents are PydanticAI's primary interface for interacting with LLMs.
55
In some use cases a single Agent will control an entire application or component,
66
but multiple agents can also interact to embody more complex workflows.
77

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:
99

1010
* A [system prompt](#system-prompts) — a set of instructions for the LLM written by the developer
1111
* One or more [retrievers](#retrievers) — functions that the LLM may call to get information while generating a response
1212
* An optional structured [result type](results.md) — the structured datatype the LLM must return at the end of a run
1313
* 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
1515

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]]`.
1717

1818
Here's a toy example of an agent that simulates a roulette wheel:
1919

@@ -25,7 +25,7 @@ roulette_agent = Agent( # (1)!
2525
deps_type=int,
2626
result_type=bool,
2727
system_prompt=(
28-
'Use the `roulette_wheel` to see if the '
28+
'Use the `roulette_wheel` function to see if the '
2929
'customer has won based on the number they provide.'
3030
),
3131
)
@@ -48,21 +48,22 @@ print(result.data)
4848
#> False
4949
```
5050

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.
5555

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].
5859

5960
## Running Agents
6061

6162
There are three ways to run an agent:
6263

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 plain function 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
6667

6768
Here's a simple example demonstrating all three:
6869

@@ -114,7 +115,7 @@ print(result2.data)
114115
#> Albert Einstein's most famous equation is (E = mc^2).
115116
```
116117

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.
118119

119120
_(This example is complete, it can be run "as is")_
120121

@@ -125,9 +126,9 @@ System prompts might seem simple at first glance since they're just strings (or
125126
Generally, system prompts fall into two categories:
126127

127128
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].
129130

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.
131132

132133
Here's an example using both types of system prompts:
133134

@@ -169,12 +170,12 @@ _(This example is complete, it can be run "as is")_
169170

170171
Retrievers provide a mechanism for models to request extra information to help them generate a response.
171172

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.
173174

174175
!!! info "Retrievers vs. RAG"
175176
Retrievers are basically the "R" of RAG (Retrieval-Augmented Generation) — they augment what the model can do by letting it request extra information.
176177

177-
The main semantic difference between PydanticAI Retreivers and RAG is RAG is synonymous with vector search, while PydanticAI retrievers are more general purpose. (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))
178179

179180
There are two different decorator functions to register retrievers:
180181

@@ -328,11 +329,11 @@ Under the hood, retrievers use the model's "tools" or "functions" API to let the
328329

329330
Function parameters are extracted from the function signature, and all parameters except `CallContext` are used to build the schema for that tool call.
330331

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.
332333

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).
334335

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:
336337

337338
```py title="retriever_schema.py"
338339
from pydantic_ai import Agent
@@ -385,15 +386,15 @@ agent.run_sync('hello', model=FunctionModel(print_schema))
385386

386387
_(This example is complete, it can be run "as is")_
387388

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.
389390

390391
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)
391392

392393
## Reflection and self-correction
393394

394395
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.
395396

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.
397398

398399
- 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__].
399400
- You can access the current retry count from within a retriever or result validator via [`ctx.retry`][pydantic_ai.dependencies.CallContext].

docs/examples/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ For examples, to run the very simple [`pydantic_model`](./pydantic-model.md) exa
5353
python/uv-run -m pydantic_ai_examples.pydantic_model
5454
```
5555

56-
If you like on-liners and you're using uv, you can run a pydantic-ai example with zero setup:
56+
If you like one-liners and you're using uv, you can run a pydantic-ai example with zero setup:
5757

5858
```bash
5959
OPENAI_API_KEY='your-api-key' \

pydantic_ai_examples/stream_whales.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ async def main():
8585
table.add_row(
8686
str(wid),
8787
whale['name'],
88-
f'{whale['length']:0.0f}',
88+
f'{whale["length"]:0.0f}',
8989
f'{w:0.0f}' if (w := whale.get('weight')) else '…',
9090
whale.get('ocean') or '…',
9191
whale.get('description') or '…',

0 commit comments

Comments
 (0)