pydantic-ai-examples 1.0.13__tar.gz → 1.49.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/.gitignore +3 -1
  2. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/PKG-INFO +5 -5
  3. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/api/agentic_chat.py +5 -2
  4. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/api/agentic_generative_ui.py +6 -3
  5. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/api/human_in_the_loop.py +3 -2
  6. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/api/predictive_state_updates.py +4 -3
  7. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/api/shared_state.py +11 -10
  8. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/api/tool_based_generative_ui.py +3 -2
  9. pydantic_ai_examples-1.49.0/pydantic_ai_examples/bank_support.py +101 -0
  10. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/chat_app.py +1 -1
  11. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/data_analyst.py +4 -4
  12. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/agent.py +1 -1
  13. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/example_04_compare_models.py +2 -2
  14. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/flight_booking.py +3 -3
  15. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/pydantic_model.py +1 -1
  16. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/question_graph.py +6 -4
  17. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/rag.py +6 -5
  18. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/slack_lead_qualifier/agent.py +1 -1
  19. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/sql_gen.py +1 -1
  20. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/stream_markdown.py +2 -2
  21. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/weather_agent.py +1 -1
  22. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/weather_agent_gradio.py +0 -1
  23. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pyproject.toml +2 -2
  24. pydantic_ai_examples-1.0.13/pydantic_ai_examples/bank_support.py +0 -95
  25. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/LICENSE +0 -0
  26. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/README.md +0 -0
  27. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/__main__.py +0 -0
  28. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/__init__.py +0 -0
  29. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/__main__.py +0 -0
  30. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/ag_ui/api/__init__.py +0 -0
  31. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/chat_app.html +0 -0
  32. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/chat_app.ts +0 -0
  33. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/__init__.py +0 -0
  34. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/custom_evaluators.py +0 -0
  35. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/datasets/time_range_v1.yaml +0 -0
  36. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/datasets/time_range_v1_schema.json +0 -0
  37. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/datasets/time_range_v2.yaml +0 -0
  38. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/datasets/time_range_v2_schema.json +0 -0
  39. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/example_01_generate_dataset.py +0 -0
  40. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/example_02_add_custom_evaluators.py +0 -0
  41. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/example_03_unit_testing.py +0 -0
  42. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/evals/models.py +0 -0
  43. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/py.typed +0 -0
  44. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/roulette_wheel.py +0 -0
  45. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/slack_lead_qualifier/__init__.py +0 -0
  46. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/slack_lead_qualifier/app.py +0 -0
  47. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/slack_lead_qualifier/functions.py +0 -0
  48. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/slack_lead_qualifier/modal.py +0 -0
  49. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/slack_lead_qualifier/models.py +0 -0
  50. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/slack_lead_qualifier/slack.py +0 -0
  51. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/slack_lead_qualifier/store.py +0 -0
  52. {pydantic_ai_examples-1.0.13 → pydantic_ai_examples-1.49.0}/pydantic_ai_examples/stream_whales.py +0 -0
@@ -10,7 +10,7 @@ env*/
10
10
  /TODO.md
11
11
  /postgres-data/
12
12
  .DS_Store
13
- examples/pydantic_ai_examples/.chat_app_messages.sqlite
13
+ .chat_app_messages.sqlite
14
14
  .cache/
15
15
  .vscode/
16
16
  /question_graph_history.json
@@ -21,3 +21,5 @@ node_modules/
21
21
  /test_tmp/
22
22
  .mcp.json
23
23
  .claude/
24
+ /.cursor/
25
+ /.devcontainer/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-ai-examples
3
- Version: 1.0.13
3
+ Version: 1.49.0
4
4
  Summary: Examples of how to use Pydantic AI and what it can do.
5
5
  Author-email: Samuel Colvin <samuel@pydantic.dev>, Marcelo Trylesinski <marcelotryle@gmail.com>, David Montague <david@pydantic.dev>, Alex Hall <alex@pydantic.dev>, Douwe Maan <douwe@pydantic.dev>
6
6
  License-Expression: MIT
@@ -29,13 +29,13 @@ Requires-Dist: datasets>=4.0.0
29
29
  Requires-Dist: devtools>=0.12.2
30
30
  Requires-Dist: duckdb>=1.3.2
31
31
  Requires-Dist: fastapi>=0.115.4
32
- Requires-Dist: gradio>=5.9.0
32
+ Requires-Dist: gradio>=5.31.0
33
33
  Requires-Dist: logfire[asyncpg,fastapi,httpx,sqlite3]>=3.14.1
34
- Requires-Dist: mcp[cli]>=1.4.1
34
+ Requires-Dist: mcp[cli]<2.0,>=1.25.0
35
35
  Requires-Dist: modal>=1.0.4
36
36
  Requires-Dist: pandas>=2.2.3
37
- Requires-Dist: pydantic-ai-slim[ag-ui,anthropic,groq,openai,vertexai]==1.0.13
38
- Requires-Dist: pydantic-evals==1.0.13
37
+ Requires-Dist: pydantic-ai-slim[ag-ui,anthropic,groq,openai,vertexai]==1.49.0
38
+ Requires-Dist: pydantic-evals==1.49.0
39
39
  Requires-Dist: python-multipart>=0.0.17
40
40
  Requires-Dist: rich>=13.9.2
41
41
  Requires-Dist: uvicorn>=0.32.0
@@ -6,9 +6,9 @@ from datetime import datetime
6
6
  from zoneinfo import ZoneInfo
7
7
 
8
8
  from pydantic_ai import Agent
9
+ from pydantic_ai.ui.ag_ui.app import AGUIApp
9
10
 
10
- agent = Agent('openai:gpt-4o-mini')
11
- app = agent.to_ag_ui()
11
+ agent = Agent('openai:gpt-5-mini')
12
12
 
13
13
 
14
14
  @agent.tool_plain
@@ -23,3 +23,6 @@ async def current_time(timezone: str = 'UTC') -> str:
23
23
  """
24
24
  tz: ZoneInfo = ZoneInfo(timezone)
25
25
  return datetime.now(tz=tz).isoformat()
26
+
27
+
28
+ app = AGUIApp(agent)
@@ -9,6 +9,7 @@ from pydantic import BaseModel, Field
9
9
 
10
10
  from ag_ui.core import EventType, StateDeltaEvent, StateSnapshotEvent
11
11
  from pydantic_ai import Agent
12
+ from pydantic_ai.ui.ag_ui.app import AGUIApp
12
13
 
13
14
  StepStatus = Literal['pending', 'completed']
14
15
 
@@ -26,7 +27,9 @@ class Step(BaseModel):
26
27
  class Plan(BaseModel):
27
28
  """Represents a plan with multiple steps."""
28
29
 
29
- steps: list[Step] = Field(default_factory=list, description='The steps in the plan')
30
+ steps: list[Step] = Field(
31
+ default_factory=list[Step], description='The steps in the plan'
32
+ )
30
33
 
31
34
 
32
35
  class JSONPatchOp(BaseModel):
@@ -48,7 +51,7 @@ class JSONPatchOp(BaseModel):
48
51
 
49
52
 
50
53
  agent = Agent(
51
- 'openai:gpt-4o-mini',
54
+ 'openai:gpt-5-mini',
52
55
  instructions=dedent(
53
56
  """
54
57
  When planning use tools only, without any other messages.
@@ -116,4 +119,4 @@ async def update_plan_step(
116
119
  )
117
120
 
118
121
 
119
- app = agent.to_ag_ui()
122
+ app = AGUIApp(agent)
@@ -8,9 +8,10 @@ from __future__ import annotations
8
8
  from textwrap import dedent
9
9
 
10
10
  from pydantic_ai import Agent
11
+ from pydantic_ai.ui.ag_ui.app import AGUIApp
11
12
 
12
13
  agent = Agent(
13
- 'openai:gpt-4o-mini',
14
+ 'openai:gpt-5-mini',
14
15
  instructions=dedent(
15
16
  """
16
17
  When planning tasks use tools only, without any other messages.
@@ -23,4 +24,4 @@ agent = Agent(
23
24
  ),
24
25
  )
25
26
 
26
- app = agent.to_ag_ui()
27
+ app = AGUIApp(agent)
@@ -8,7 +8,8 @@ from pydantic import BaseModel
8
8
 
9
9
  from ag_ui.core import CustomEvent, EventType
10
10
  from pydantic_ai import Agent, RunContext
11
- from pydantic_ai.ag_ui import StateDeps
11
+ from pydantic_ai.ui import StateDeps
12
+ from pydantic_ai.ui.ag_ui.app import AGUIApp
12
13
 
13
14
 
14
15
  class DocumentState(BaseModel):
@@ -17,7 +18,7 @@ class DocumentState(BaseModel):
17
18
  document: str = ''
18
19
 
19
20
 
20
- agent = Agent('openai:gpt-4o-mini', deps_type=StateDeps[DocumentState])
21
+ agent = Agent('openai:gpt-5-mini', deps_type=StateDeps[DocumentState])
21
22
 
22
23
 
23
24
  # Tools which return AG-UI events will be sent to the client as part of the
@@ -74,4 +75,4 @@ async def story_instructions(ctx: RunContext[StateDeps[DocumentState]]) -> str:
74
75
  )
75
76
 
76
77
 
77
- app = agent.to_ag_ui(deps=StateDeps(DocumentState()))
78
+ app = AGUIApp(agent, deps=StateDeps(DocumentState()))
@@ -2,17 +2,18 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from enum import StrEnum
5
+ from enum import Enum
6
6
  from textwrap import dedent
7
7
 
8
8
  from pydantic import BaseModel, Field
9
9
 
10
10
  from ag_ui.core import EventType, StateSnapshotEvent
11
11
  from pydantic_ai import Agent, RunContext
12
- from pydantic_ai.ag_ui import StateDeps
12
+ from pydantic_ai.ui import StateDeps
13
+ from pydantic_ai.ui.ag_ui.app import AGUIApp
13
14
 
14
15
 
15
- class SkillLevel(StrEnum):
16
+ class SkillLevel(str, Enum):
16
17
  """The level of skill required for the recipe."""
17
18
 
18
19
  BEGINNER = 'Beginner'
@@ -20,7 +21,7 @@ class SkillLevel(StrEnum):
20
21
  ADVANCED = 'Advanced'
21
22
 
22
23
 
23
- class SpecialPreferences(StrEnum):
24
+ class SpecialPreferences(str, Enum):
24
25
  """Special preferences for the recipe."""
25
26
 
26
27
  HIGH_PROTEIN = 'High Protein'
@@ -32,7 +33,7 @@ class SpecialPreferences(StrEnum):
32
33
  VEGAN = 'Vegan'
33
34
 
34
35
 
35
- class CookingTime(StrEnum):
36
+ class CookingTime(str, Enum):
36
37
  """The cooking time of the recipe."""
37
38
 
38
39
  FIVE_MIN = '5 min'
@@ -61,18 +62,18 @@ class Recipe(BaseModel):
61
62
  description='The skill level required for the recipe',
62
63
  )
63
64
  special_preferences: list[SpecialPreferences] = Field(
64
- default_factory=list,
65
+ default_factory=list[SpecialPreferences],
65
66
  description='Any special preferences for the recipe',
66
67
  )
67
68
  cooking_time: CookingTime = Field(
68
69
  default=CookingTime.FIVE_MIN, description='The cooking time of the recipe'
69
70
  )
70
71
  ingredients: list[Ingredient] = Field(
71
- default_factory=list,
72
+ default_factory=list[Ingredient],
72
73
  description='Ingredients for the recipe',
73
74
  )
74
75
  instructions: list[str] = Field(
75
- default_factory=list, description='Instructions for the recipe'
76
+ default_factory=list[str], description='Instructions for the recipe'
76
77
  )
77
78
 
78
79
 
@@ -84,7 +85,7 @@ class RecipeSnapshot(BaseModel):
84
85
  )
85
86
 
86
87
 
87
- agent = Agent('openai:gpt-4o-mini', deps_type=StateDeps[RecipeSnapshot])
88
+ agent = Agent('openai:gpt-5-mini', deps_type=StateDeps[RecipeSnapshot])
88
89
 
89
90
 
90
91
  @agent.tool_plain
@@ -135,4 +136,4 @@ async def recipe_instructions(ctx: RunContext[StateDeps[RecipeSnapshot]]) -> str
135
136
  )
136
137
 
137
138
 
138
- app = agent.to_ag_ui(deps=StateDeps(RecipeSnapshot()))
139
+ app = AGUIApp(agent, deps=StateDeps(RecipeSnapshot()))
@@ -6,6 +6,7 @@ No special handling is required for this feature.
6
6
  from __future__ import annotations
7
7
 
8
8
  from pydantic_ai import Agent
9
+ from pydantic_ai.ui.ag_ui.app import AGUIApp
9
10
 
10
- agent = Agent('openai:gpt-4o-mini')
11
- app = agent.to_ag_ui()
11
+ agent = Agent('openai:gpt-5-mini')
12
+ app = AGUIApp(agent)
@@ -0,0 +1,101 @@
1
+ """Small but complete example of using Pydantic AI to build a support agent for a bank.
2
+
3
+ Run with:
4
+
5
+ uv run -m pydantic_ai_examples.bank_support
6
+ """
7
+
8
+ import sqlite3
9
+ from dataclasses import dataclass
10
+
11
+ from pydantic import BaseModel
12
+
13
+ from pydantic_ai import Agent, RunContext
14
+
15
+
16
+ @dataclass
17
+ class DatabaseConn:
18
+ """A wrapper over the SQLite connection."""
19
+
20
+ sqlite_conn: sqlite3.Connection
21
+
22
+ async def customer_name(self, *, id: int) -> str | None:
23
+ res = cur.execute('SELECT name FROM customers WHERE id=?', (id,))
24
+ row = res.fetchone()
25
+ if row:
26
+ return row[0]
27
+ return None
28
+
29
+ async def customer_balance(self, *, id: int) -> float:
30
+ res = cur.execute('SELECT balance FROM customers WHERE id=?', (id,))
31
+ row = res.fetchone()
32
+ if row:
33
+ return row[0]
34
+ else:
35
+ raise ValueError('Customer not found')
36
+
37
+
38
+ @dataclass
39
+ class SupportDependencies:
40
+ customer_id: int
41
+ db: DatabaseConn
42
+
43
+
44
+ class SupportOutput(BaseModel):
45
+ support_advice: str
46
+ """Advice returned to the customer"""
47
+ block_card: bool
48
+ """Whether to block their card or not"""
49
+ risk: int
50
+ """Risk level of query"""
51
+
52
+
53
+ support_agent = Agent(
54
+ 'openai:gpt-5',
55
+ deps_type=SupportDependencies,
56
+ output_type=SupportOutput,
57
+ instructions=(
58
+ 'You are a support agent in our bank, give the '
59
+ 'customer support and judge the risk level of their query. '
60
+ "Reply using the customer's name."
61
+ ),
62
+ )
63
+
64
+
65
+ @support_agent.instructions
66
+ async def add_customer_name(ctx: RunContext[SupportDependencies]) -> str:
67
+ customer_name = await ctx.deps.db.customer_name(id=ctx.deps.customer_id)
68
+ return f"The customer's name is {customer_name!r}"
69
+
70
+
71
+ @support_agent.tool
72
+ async def customer_balance(ctx: RunContext[SupportDependencies]) -> str:
73
+ """Returns the customer's current account balance."""
74
+ balance = await ctx.deps.db.customer_balance(
75
+ id=ctx.deps.customer_id,
76
+ )
77
+ return f'${balance:.2f}'
78
+
79
+
80
+ if __name__ == '__main__':
81
+ with sqlite3.connect(':memory:') as con:
82
+ cur = con.cursor()
83
+ cur.execute('CREATE TABLE customers(id, name, balance)')
84
+ cur.execute("""
85
+ INSERT INTO customers VALUES
86
+ (123, 'John', 123.45)
87
+ """)
88
+ con.commit()
89
+
90
+ deps = SupportDependencies(customer_id=123, db=DatabaseConn(sqlite_conn=con))
91
+ result = support_agent.run_sync('What is my balance?', deps=deps)
92
+ print(result.output)
93
+ """
94
+ support_advice='Hello John, your current account balance, including pending transactions, is $123.45.' block_card=False risk=1
95
+ """
96
+
97
+ result = support_agent.run_sync('I just lost my card!', deps=deps)
98
+ print(result.output)
99
+ """
100
+ support_advice="I'm sorry to hear that, John. We are temporarily blocking your card to prevent unauthorized transactions." block_card=True risk=8
101
+ """
@@ -40,7 +40,7 @@ from pydantic_ai import (
40
40
  logfire.configure(send_to_logfire='if-token-present')
41
41
  logfire.instrument_pydantic_ai()
42
42
 
43
- agent = Agent('openai:gpt-4o')
43
+ agent = Agent('openai:gpt-5')
44
44
  THIS_DIR = Path(__file__).parent
45
45
 
46
46
 
@@ -9,7 +9,7 @@ from pydantic_ai import Agent, ModelRetry, RunContext
9
9
 
10
10
  @dataclass
11
11
  class AnalystAgentDeps:
12
- output: dict[str, pd.DataFrame] = field(default_factory=dict)
12
+ output: dict[str, pd.DataFrame] = field(default_factory=dict[str, pd.DataFrame])
13
13
 
14
14
  def store(self, value: pd.DataFrame) -> str:
15
15
  """Store the output in deps and return the reference such as Out[1] to be used by the LLM."""
@@ -26,7 +26,7 @@ class AnalystAgentDeps:
26
26
 
27
27
 
28
28
  analyst_agent = Agent(
29
- 'openai:gpt-4o',
29
+ 'openai:gpt-5',
30
30
  deps_type=AnalystAgentDeps,
31
31
  instructions='You are a data analyst and your job is to analyze the data according to the user request.',
32
32
  )
@@ -47,7 +47,7 @@ def load_dataset(
47
47
  """
48
48
  # begin load data from hf
49
49
  builder = datasets.load_dataset_builder(path) # pyright: ignore[reportUnknownMemberType]
50
- splits: dict[str, datasets.SplitInfo] = builder.info.splits or {} # pyright: ignore[reportUnknownMemberType]
50
+ splits: dict[str, datasets.SplitInfo] = builder.info.splits or {}
51
51
  if split not in splits:
52
52
  raise ModelRetry(
53
53
  f'{split} is not valid for dataset {path}. Valid splits are {",".join(splits.keys())}'
@@ -87,7 +87,7 @@ def run_duckdb(ctx: RunContext[AnalystAgentDeps], dataset: str, sql: str) -> str
87
87
  data = ctx.deps.get(dataset)
88
88
  result = duckdb.query_df(df=data, virtual_table_name='dataset', sql_query=sql)
89
89
  # pass the result as ref (because DuckDB SQL can select many rows, creating another huge dataframe)
90
- ref = ctx.deps.store(result.df()) # pyright: ignore[reportUnknownMemberType]
90
+ ref = ctx.deps.store(result.df())
91
91
  return f'Executed SQL, result is `{ref}`'
92
92
 
93
93
 
@@ -21,7 +21,7 @@ class TimeRangeDeps:
21
21
 
22
22
 
23
23
  time_range_agent = Agent[TimeRangeDeps, TimeRangeResponse](
24
- 'gpt-4o',
24
+ 'gpt-5',
25
25
  output_type=TimeRangeResponse, # type: ignore # we can't yet annotate something as receiving a TypeForm
26
26
  deps_type=TimeRangeDeps,
27
27
  system_prompt="Convert the user's request into a structured time range.",
@@ -28,8 +28,8 @@ def compare_models():
28
28
  dataset_path, custom_evaluator_types=CUSTOM_EVALUATOR_TYPES
29
29
  )
30
30
  with logfire.span('Comparing different models for time_range_agent'):
31
- with time_range_agent.override(model='openai:gpt-4o'):
32
- dataset.evaluate_sync(infer_time_range, name='openai:gpt-4o')
31
+ with time_range_agent.override(model='openai:gpt-5'):
32
+ dataset.evaluate_sync(infer_time_range, name='openai:gpt-5')
33
33
  with time_range_agent.override(model='openai:o1'):
34
34
  dataset.evaluate_sync(infer_time_range, name='openai:o1')
35
35
 
@@ -49,7 +49,7 @@ class Deps:
49
49
 
50
50
  # This agent is responsible for controlling the flow of the conversation.
51
51
  search_agent = Agent[Deps, FlightDetails | NoFlightFound](
52
- 'openai:gpt-4o',
52
+ 'openai:gpt-5',
53
53
  output_type=FlightDetails | NoFlightFound, # type: ignore
54
54
  retries=4,
55
55
  system_prompt=(
@@ -60,7 +60,7 @@ search_agent = Agent[Deps, FlightDetails | NoFlightFound](
60
60
 
61
61
  # This agent is responsible for extracting flight details from web page text.
62
62
  extraction_agent = Agent(
63
- 'openai:gpt-4o',
63
+ 'openai:gpt-5',
64
64
  output_type=list[FlightDetails],
65
65
  system_prompt='Extract all the flight details from the given text.',
66
66
  )
@@ -112,7 +112,7 @@ class Failed(BaseModel):
112
112
 
113
113
  # This agent is responsible for extracting the user's seat selection
114
114
  seat_preference_agent = Agent[None, SeatPreference | Failed](
115
- 'openai:gpt-4o',
115
+ 'openai:gpt-5',
116
116
  output_type=SeatPreference | Failed,
117
117
  system_prompt=(
118
118
  "Extract the user's seat preference. "
@@ -22,7 +22,7 @@ class MyModel(BaseModel):
22
22
  country: str
23
23
 
24
24
 
25
- model = os.getenv('PYDANTIC_AI_MODEL', 'openai:gpt-4o')
25
+ model = os.getenv('PYDANTIC_AI_MODEL', 'openai:gpt-5')
26
26
  print(f'Using model: {model}')
27
27
  agent = Agent(model, output_type=MyModel)
28
28
 
@@ -26,14 +26,16 @@ from pydantic_graph.persistence.file import FileStatePersistence
26
26
  logfire.configure(send_to_logfire='if-token-present')
27
27
  logfire.instrument_pydantic_ai()
28
28
 
29
- ask_agent = Agent('openai:gpt-4o', output_type=str)
29
+ ask_agent = Agent('openai:gpt-5', output_type=str)
30
30
 
31
31
 
32
32
  @dataclass
33
33
  class QuestionState:
34
34
  question: str | None = None
35
- ask_agent_messages: list[ModelMessage] = field(default_factory=list)
36
- evaluate_agent_messages: list[ModelMessage] = field(default_factory=list)
35
+ ask_agent_messages: list[ModelMessage] = field(default_factory=list[ModelMessage])
36
+ evaluate_agent_messages: list[ModelMessage] = field(
37
+ default_factory=list[ModelMessage]
38
+ )
37
39
 
38
40
 
39
41
  @dataclass
@@ -65,7 +67,7 @@ class EvaluationOutput(BaseModel, use_attribute_docstrings=True):
65
67
 
66
68
 
67
69
  evaluate_agent = Agent(
68
- 'openai:gpt-4o',
70
+ 'openai:gpt-5',
69
71
  output_type=EvaluationOutput,
70
72
  system_prompt='Given a question and answer, evaluate if the answer is correct.',
71
73
  )
@@ -30,6 +30,7 @@ import asyncpg
30
30
  import httpx
31
31
  import logfire
32
32
  import pydantic_core
33
+ from anyio import create_task_group
33
34
  from openai import AsyncOpenAI
34
35
  from pydantic import TypeAdapter
35
36
  from typing_extensions import AsyncGenerator
@@ -48,7 +49,7 @@ class Deps:
48
49
  pool: asyncpg.Pool
49
50
 
50
51
 
51
- agent = Agent('openai:gpt-4o', deps_type=Deps)
52
+ agent = Agent('openai:gpt-5', deps_type=Deps)
52
53
 
53
54
 
54
55
  @agent.tool
@@ -114,7 +115,7 @@ async def build_search_db():
114
115
  async with httpx.AsyncClient() as client:
115
116
  response = await client.get(DOCS_JSON)
116
117
  response.raise_for_status()
117
- sections = sessions_ta.validate_json(response.content)
118
+ sections = sections_ta.validate_json(response.content)
118
119
 
119
120
  openai = AsyncOpenAI()
120
121
  logfire.instrument_openai(openai)
@@ -126,9 +127,9 @@ async def build_search_db():
126
127
  await conn.execute(DB_SCHEMA)
127
128
 
128
129
  sem = asyncio.Semaphore(10)
129
- async with asyncio.TaskGroup() as tg:
130
+ async with create_task_group() as tg:
130
131
  for section in sections:
131
- tg.create_task(insert_doc_section(sem, openai, pool, section))
132
+ tg.start_soon(insert_doc_section, sem, openai, pool, section)
132
133
 
133
134
 
134
135
  async def insert_doc_section(
@@ -182,7 +183,7 @@ class DocsSection:
182
183
  return '\n\n'.join((f'path: {self.path}', f'title: {self.title}', self.content))
183
184
 
184
185
 
185
- sessions_ta = TypeAdapter(list[DocsSection])
186
+ sections_ta = TypeAdapter(list[DocsSection])
186
187
 
187
188
 
188
189
  # pyright: reportUnknownMemberType=false
@@ -11,7 +11,7 @@ from .models import Analysis, Profile
11
11
 
12
12
  ### [agent]
13
13
  agent = Agent(
14
- 'openai:gpt-4o',
14
+ 'openai:gpt-5',
15
15
  instructions=dedent(
16
16
  """
17
17
  When a new person joins our public Slack, please put together a brief snapshot so we can be most useful to them.
@@ -92,7 +92,7 @@ class InvalidRequest(BaseModel):
92
92
 
93
93
  Response: TypeAlias = Success | InvalidRequest
94
94
  agent = Agent[Deps, Response](
95
- 'google-gla:gemini-1.5-flash',
95
+ 'google-gla:gemini-2.5-flash',
96
96
  # Type ignore while we wait for PEP-0747, nonetheless unions will work fine everywhere else
97
97
  output_type=Response, # type: ignore
98
98
  deps_type=Deps,
@@ -26,8 +26,8 @@ agent = Agent()
26
26
 
27
27
  # models to try, and the appropriate env var
28
28
  models: list[tuple[KnownModelName, str]] = [
29
- ('google-gla:gemini-2.0-flash', 'GEMINI_API_KEY'),
30
- ('openai:gpt-4o-mini', 'OPENAI_API_KEY'),
29
+ ('google-gla:gemini-2.5-flash', 'GEMINI_API_KEY'),
30
+ ('openai:gpt-5-mini', 'OPENAI_API_KEY'),
31
31
  ('groq:llama-3.3-70b-versatile', 'GROQ_API_KEY'),
32
32
  ]
33
33
 
@@ -32,7 +32,7 @@ class Deps:
32
32
 
33
33
 
34
34
  weather_agent = Agent(
35
- 'openai:gpt-4.1-mini',
35
+ 'openai:gpt-5-mini',
36
36
  # 'Be concise, reply with one sentence.' is enough for some models (like openai) to use
37
37
  # the below tools appropriately, but others like anthropic and gemini require a bit more direction.
38
38
  instructions='Be concise, reply with one sentence.',
@@ -99,7 +99,6 @@ with gr.Blocks() as demo:
99
99
  past_messages = gr.State([])
100
100
  chatbot = gr.Chatbot(
101
101
  label='Packing Assistant',
102
- type='messages',
103
102
  avatar_images=(None, 'https://ai.pydantic.dev/img/logo-white.svg'),
104
103
  examples=[
105
104
  {'text': 'What is the weather like in Miami?'},
@@ -56,8 +56,8 @@ dependencies = [
56
56
  "rich>=13.9.2",
57
57
  "uvicorn>=0.32.0",
58
58
  "devtools>=0.12.2",
59
- "gradio>=5.9.0",
60
- "mcp[cli]>=1.4.1",
59
+ "gradio>=5.31.0",
60
+ "mcp[cli]>=1.25.0,<2.0",
61
61
  "modal>=1.0.4",
62
62
  "duckdb>=1.3.2",
63
63
  "datasets>=4.0.0",
@@ -1,95 +0,0 @@
1
- """Small but complete example of using Pydantic AI to build a support agent for a bank.
2
-
3
- Run with:
4
-
5
- uv run -m pydantic_ai_examples.bank_support
6
- """
7
-
8
- from dataclasses import dataclass
9
-
10
- from pydantic import BaseModel
11
-
12
- from pydantic_ai import Agent, RunContext
13
-
14
-
15
- class DatabaseConn:
16
- """This is a fake database for example purposes.
17
-
18
- In reality, you'd be connecting to an external database
19
- (e.g. PostgreSQL) to get information about customers.
20
- """
21
-
22
- @classmethod
23
- async def customer_name(cls, *, id: int) -> str | None:
24
- if id == 123:
25
- return 'John'
26
-
27
- @classmethod
28
- async def customer_balance(cls, *, id: int, include_pending: bool) -> float:
29
- if id == 123:
30
- if include_pending:
31
- return 123.45
32
- else:
33
- return 100.00
34
- else:
35
- raise ValueError('Customer not found')
36
-
37
-
38
- @dataclass
39
- class SupportDependencies:
40
- customer_id: int
41
- db: DatabaseConn
42
-
43
-
44
- class SupportOutput(BaseModel):
45
- support_advice: str
46
- """Advice returned to the customer"""
47
- block_card: bool
48
- """Whether to block their card or not"""
49
- risk: int
50
- """Risk level of query"""
51
-
52
-
53
- support_agent = Agent(
54
- 'openai:gpt-4o',
55
- deps_type=SupportDependencies,
56
- output_type=SupportOutput,
57
- instructions=(
58
- 'You are a support agent in our bank, give the '
59
- 'customer support and judge the risk level of their query. '
60
- "Reply using the customer's name."
61
- ),
62
- )
63
-
64
-
65
- @support_agent.instructions
66
- async def add_customer_name(ctx: RunContext[SupportDependencies]) -> str:
67
- customer_name = await ctx.deps.db.customer_name(id=ctx.deps.customer_id)
68
- return f"The customer's name is {customer_name!r}"
69
-
70
-
71
- @support_agent.tool
72
- async def customer_balance(
73
- ctx: RunContext[SupportDependencies], include_pending: bool
74
- ) -> str:
75
- """Returns the customer's current account balance."""
76
- balance = await ctx.deps.db.customer_balance(
77
- id=ctx.deps.customer_id,
78
- include_pending=include_pending,
79
- )
80
- return f'${balance:.2f}'
81
-
82
-
83
- if __name__ == '__main__':
84
- deps = SupportDependencies(customer_id=123, db=DatabaseConn())
85
- result = support_agent.run_sync('What is my balance?', deps=deps)
86
- print(result.output)
87
- """
88
- support_advice='Hello John, your current account balance, including pending transactions, is $123.45.' block_card=False risk=1
89
- """
90
-
91
- result = support_agent.run_sync('I just lost my card!', deps=deps)
92
- print(result.output)
93
- """
94
- support_advice="I'm sorry to hear that, John. We are temporarily blocking your card to prevent unauthorized transactions." block_card=True risk=8
95
- """