Skip to content

Commit 3ad6d38

Browse files
committed
Merge remote-tracking branch 'origin/main' into add-builtin-tools
2 parents e3dda9d + 154fec5 commit 3ad6d38

File tree

136 files changed

+17752
-923
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+17752
-923
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ jobs:
8989
name: site
9090
path: site
9191

92+
# check all docs images are tinified, You'll need an API key from https://tinify.com/ to fix this if it fails
93+
- run: uvx tinicly docs --check
94+
9295
test-live:
9396
runs-on: ubuntu-latest
9497
timeout-minutes: 5
@@ -109,6 +112,7 @@ jobs:
109112
--package pydantic-ai-slim
110113
--extra openai
111114
--extra vertexai
115+
--extra google
112116
--extra groq
113117
--extra anthropic
114118
--extra mistral
@@ -221,7 +225,7 @@ jobs:
221225
name: diff-coverage-html
222226
path: index.html
223227

224-
- run: uv run coverage report --fail-under 95
228+
- run: uv run coverage report --fail-under 100
225229
- run: uv run diff-cover coverage.xml --fail-under 100
226230
- run: uv run strict-no-cover
227231

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ examples/pydantic_ai_examples/.chat_app_messages.sqlite
1717
/docs-site/.wrangler/
1818
/CLAUDE.md
1919
node_modules/
20+
**.idea/
21+
.coverage*

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ test: ## Run tests and collect coverage data
6363
uv run coverage run -m pytest
6464
@uv run coverage report
6565

66+
.PHONY: test-fast
67+
test-fast: ## Same as test except no coverage. ~1/4th the time depending on hardware.
68+
uv run pytest -n auto --dist=loadgroup
69+
6670
.PHONY: test-all-python
6771
test-all-python: ## Run tests on Python 3.9 to 3.13
6872
UV_PROJECT_ENVIRONMENT=.venv39 uv run --python 3.9 --all-extras --all-packages coverage run -p -m pytest

clai/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) Pydantic Services Inc. 2024 to present
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

docs/.cursor/rules.mdc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
Always reference the python code in the docs e.g. `ModelSettings` should link to [`ModelSettings`][pydantic_ai.settings.ModelSettings].

docs/a2a.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ The only dependencies are:
7373
You can install PydanticAI with the `a2a` extra to include **FastA2A**:
7474

7575
```bash
76-
pip/uv-add 'pydantic-ai[a2a]'
76+
pip/uv-add 'pydantic-ai-slim[a2a]'
7777
```
7878

7979
### PydanticAI Agent to A2A Server

docs/agents.md

Lines changed: 39 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -135,29 +135,21 @@ async def main():
135135
UserPromptPart(
136136
content='What is the capital of France?',
137137
timestamp=datetime.datetime(...),
138-
part_kind='user-prompt',
139138
)
140-
],
141-
instructions=None,
142-
kind='request',
139+
]
143140
)
144141
),
145142
CallToolsNode(
146143
model_response=ModelResponse(
147-
parts=[TextPart(content='Paris', part_kind='text')],
144+
parts=[TextPart(content='Paris')],
148145
usage=Usage(
149-
requests=1,
150-
request_tokens=56,
151-
response_tokens=1,
152-
total_tokens=57,
153-
details=None,
146+
requests=1, request_tokens=56, response_tokens=1, total_tokens=57
154147
),
155148
model_name='gpt-4o',
156149
timestamp=datetime.datetime(...),
157-
kind='response',
158150
)
159151
),
160-
End(data=FinalResult(output='Paris', tool_name=None, tool_call_id=None)),
152+
End(data=FinalResult(output='Paris')),
161153
]
162154
"""
163155
print(agent_run.result.output)
@@ -206,29 +198,24 @@ async def main():
206198
UserPromptPart(
207199
content='What is the capital of France?',
208200
timestamp=datetime.datetime(...),
209-
part_kind='user-prompt',
210201
)
211-
],
212-
instructions=None,
213-
kind='request',
202+
]
214203
)
215204
),
216205
CallToolsNode(
217206
model_response=ModelResponse(
218-
parts=[TextPart(content='Paris', part_kind='text')],
207+
parts=[TextPart(content='Paris')],
219208
usage=Usage(
220209
requests=1,
221210
request_tokens=56,
222211
response_tokens=1,
223212
total_tokens=57,
224-
details=None,
225213
),
226214
model_name='gpt-4o',
227215
timestamp=datetime.datetime(...),
228-
kind='response',
229216
)
230217
),
231-
End(data=FinalResult(output='Paris', tool_name=None, tool_call_id=None)),
218+
End(data=FinalResult(output='Paris')),
232219
]
233220
"""
234221
```
@@ -368,15 +355,16 @@ if __name__ == '__main__':
368355
[
369356
'=== UserPromptNode: What will the weather be like in Paris on Tuesday? ===',
370357
'=== ModelRequestNode: streaming partial request tokens ===',
371-
'[Request] Starting part 0: ToolCallPart(tool_name=\'weather_forecast\', args=\'{"location":"Pa\', tool_call_id=\'0001\', part_kind=\'tool-call\')',
358+
"[Request] Starting part 0: ToolCallPart(tool_name='weather_forecast', tool_call_id='0001')",
359+
'[Request] Part 0 args_delta={"location":"Pa',
372360
'[Request] Part 0 args_delta=ris","forecast_',
373361
'[Request] Part 0 args_delta=date":"2030-01-',
374362
'[Request] Part 0 args_delta=01"}',
375363
'=== CallToolsNode: streaming partial response & tool usage ===',
376364
'[Tools] The LLM calls tool=\'weather_forecast\' with args={"location":"Paris","forecast_date":"2030-01-01"} (tool_call_id=\'0001\')',
377365
"[Tools] Tool call '0001' returned => The forecast in Paris on 2030-01-01 is 24°C and sunny.",
378366
'=== ModelRequestNode: streaming partial request tokens ===',
379-
"[Request] Starting part 0: TextPart(content='It will be ', part_kind='text')",
367+
"[Request] Starting part 0: TextPart(content='It will be ')",
380368
'[Result] The model produced a final output (tool_name=None)',
381369
"[Request] Part 0 text delta: 'warm and sunny '",
382370
"[Request] Part 0 text delta: 'in Paris on '",
@@ -414,9 +402,7 @@ result_sync = agent.run_sync(
414402
print(result_sync.output)
415403
#> Rome
416404
print(result_sync.usage())
417-
"""
418-
Usage(requests=1, request_tokens=62, response_tokens=1, total_tokens=63, details=None)
419-
"""
405+
#> Usage(requests=1, request_tokens=62, response_tokens=1, total_tokens=63)
420406

421407
try:
422408
result_sync = agent.run_sync(
@@ -713,6 +699,30 @@ print(result.output)
713699

714700
_(This example is complete, it can be run "as is")_
715701

702+
You can also dynamically change the instructions for an agent by using the `@agent.instructions` decorator.
703+
704+
```python {title="dynamic_instructions.py"}
705+
from datetime import date
706+
707+
from pydantic_ai import Agent, RunContext
708+
709+
agent = Agent('openai:gpt-4o', deps_type=str)
710+
711+
712+
@agent.instructions
713+
def add_the_users_name(ctx: RunContext[str]) -> str:
714+
return f"The user's name is {ctx.deps}."
715+
716+
717+
@agent.instructions
718+
def add_the_date() -> str:
719+
return f'The date is {date.today()}.'
720+
721+
result = agent.run_sync('What is the date?', deps='Frank')
722+
print(result.output)
723+
#> Hello Frank, the date today is 2032-01-02.
724+
```
725+
716726
## Reflection and self-correction
717727

718728
Validation errors from both function tool parameter validation and [structured output validation](output.md#structured-output) can be passed back to the model with a request to retry.
@@ -804,31 +814,22 @@ with capture_run_messages() as messages: # (2)!
804814
UserPromptPart(
805815
content='Please get me the volume of a box with size 6.',
806816
timestamp=datetime.datetime(...),
807-
part_kind='user-prompt',
808817
)
809-
],
810-
instructions=None,
811-
kind='request',
818+
]
812819
),
813820
ModelResponse(
814821
parts=[
815822
ToolCallPart(
816823
tool_name='calc_volume',
817824
args={'size': 6},
818825
tool_call_id='pyd_ai_tool_call_id',
819-
part_kind='tool-call',
820826
)
821827
],
822828
usage=Usage(
823-
requests=1,
824-
request_tokens=62,
825-
response_tokens=4,
826-
total_tokens=66,
827-
details=None,
829+
requests=1, request_tokens=62, response_tokens=4, total_tokens=66
828830
),
829831
model_name='gpt-4o',
830832
timestamp=datetime.datetime(...),
831-
kind='response',
832833
),
833834
ModelRequest(
834835
parts=[
@@ -837,31 +838,22 @@ with capture_run_messages() as messages: # (2)!
837838
tool_name='calc_volume',
838839
tool_call_id='pyd_ai_tool_call_id',
839840
timestamp=datetime.datetime(...),
840-
part_kind='retry-prompt',
841841
)
842-
],
843-
instructions=None,
844-
kind='request',
842+
]
845843
),
846844
ModelResponse(
847845
parts=[
848846
ToolCallPart(
849847
tool_name='calc_volume',
850848
args={'size': 6},
851849
tool_call_id='pyd_ai_tool_call_id',
852-
part_kind='tool-call',
853850
)
854851
],
855852
usage=Usage(
856-
requests=1,
857-
request_tokens=72,
858-
response_tokens=8,
859-
total_tokens=80,
860-
details=None,
853+
requests=1, request_tokens=72, response_tokens=8, total_tokens=80
861854
),
862855
model_name='gpt-4o',
863856
timestamp=datetime.datetime(...),
864-
kind='response',
865857
),
866858
]
867859
"""

docs/api/models/function.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,8 @@ async def model_function(
2828
UserPromptPart(
2929
content='Testing my agent...',
3030
timestamp=datetime.datetime(...),
31-
part_kind='user-prompt',
3231
)
33-
],
34-
instructions=None,
35-
kind='request',
32+
]
3633
)
3734
]
3835
"""

docs/api/models/google.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `pydantic_ai.models.google`
2+
3+
## Setup
4+
5+
For details on how to set up authentication with this model, see [model configuration for Google](../../models/google.md).
6+
7+
::: pydantic_ai.models.google

docs/api/providers.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
::: pydantic_ai.providers.Provider
44

5+
::: pydantic_ai.providers.google
6+
57
::: pydantic_ai.providers.google_vertex
68

79
::: pydantic_ai.providers.openai

0 commit comments

Comments
 (0)