pydantic-ai-examples 0.1.2__py3-none-any.whl → 1.12.0__py3-none-any.whl

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 (42) hide show
  1. pydantic_ai_examples/ag_ui/__init__.py +41 -0
  2. pydantic_ai_examples/ag_ui/__main__.py +9 -0
  3. pydantic_ai_examples/ag_ui/api/__init__.py +19 -0
  4. pydantic_ai_examples/ag_ui/api/agentic_chat.py +28 -0
  5. pydantic_ai_examples/ag_ui/api/agentic_generative_ui.py +120 -0
  6. pydantic_ai_examples/ag_ui/api/human_in_the_loop.py +27 -0
  7. pydantic_ai_examples/ag_ui/api/predictive_state_updates.py +78 -0
  8. pydantic_ai_examples/ag_ui/api/shared_state.py +139 -0
  9. pydantic_ai_examples/ag_ui/api/tool_based_generative_ui.py +12 -0
  10. pydantic_ai_examples/bank_support.py +16 -10
  11. pydantic_ai_examples/chat_app.py +8 -7
  12. pydantic_ai_examples/data_analyst.py +107 -0
  13. pydantic_ai_examples/evals/agent.py +1 -1
  14. pydantic_ai_examples/evals/custom_evaluators.py +5 -6
  15. pydantic_ai_examples/evals/example_01_generate_dataset.py +1 -2
  16. pydantic_ai_examples/evals/example_02_add_custom_evaluators.py +1 -2
  17. pydantic_ai_examples/evals/example_03_unit_testing.py +4 -2
  18. pydantic_ai_examples/evals/example_04_compare_models.py +3 -3
  19. pydantic_ai_examples/flight_booking.py +15 -10
  20. pydantic_ai_examples/py.typed +0 -0
  21. pydantic_ai_examples/pydantic_model.py +4 -3
  22. pydantic_ai_examples/question_graph.py +5 -5
  23. pydantic_ai_examples/rag.py +8 -7
  24. pydantic_ai_examples/roulette_wheel.py +1 -2
  25. pydantic_ai_examples/slack_lead_qualifier/__init__.py +0 -0
  26. pydantic_ai_examples/slack_lead_qualifier/agent.py +47 -0
  27. pydantic_ai_examples/slack_lead_qualifier/app.py +36 -0
  28. pydantic_ai_examples/slack_lead_qualifier/functions.py +85 -0
  29. pydantic_ai_examples/slack_lead_qualifier/modal.py +66 -0
  30. pydantic_ai_examples/slack_lead_qualifier/models.py +46 -0
  31. pydantic_ai_examples/slack_lead_qualifier/slack.py +30 -0
  32. pydantic_ai_examples/slack_lead_qualifier/store.py +31 -0
  33. pydantic_ai_examples/sql_gen.py +6 -7
  34. pydantic_ai_examples/stream_markdown.py +5 -4
  35. pydantic_ai_examples/stream_whales.py +4 -16
  36. pydantic_ai_examples/weather_agent.py +36 -88
  37. pydantic_ai_examples/weather_agent_gradio.py +10 -15
  38. {pydantic_ai_examples-0.1.2.dist-info → pydantic_ai_examples-1.12.0.dist-info}/METADATA +17 -13
  39. pydantic_ai_examples-1.12.0.dist-info/RECORD +50 -0
  40. pydantic_ai_examples-1.12.0.dist-info/licenses/LICENSE +21 -0
  41. pydantic_ai_examples-0.1.2.dist-info/RECORD +0 -30
  42. {pydantic_ai_examples-0.1.2.dist-info → pydantic_ai_examples-1.12.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,46 @@
1
+ from typing import Annotated, Any
2
+
3
+ from annotated_types import Ge, Le
4
+ from pydantic import BaseModel
5
+
6
+ ### [import-format_as_xml]
7
+ from pydantic_ai import format_as_xml ### [/import-format_as_xml]
8
+
9
+
10
+ ### [profile,profile-intro]
11
+ class Profile(BaseModel): ### [/profile-intro]
12
+ first_name: str | None = None
13
+ last_name: str | None = None
14
+ display_name: str | None = None
15
+ email: str ### [/profile]
16
+
17
+ ### [profile-as_prompt]
18
+ def as_prompt(self) -> str:
19
+ return format_as_xml(self, root_tag='profile') ### [/profile-as_prompt]
20
+
21
+
22
+ ### [analysis,analysis-intro]
23
+ class Analysis(BaseModel): ### [/analysis-intro]
24
+ profile: Profile
25
+ organization_name: str
26
+ organization_domain: str
27
+ job_title: str
28
+ relevance: Annotated[int, Ge(1), Le(5)]
29
+ """Estimated fit for Pydantic Logfire: 1 = low, 5 = high"""
30
+ summary: str
31
+ """One-sentence welcome note summarising who they are and how we might help""" ### [/analysis]
32
+
33
+ ### [analysis-as_slack_blocks]
34
+ def as_slack_blocks(self, include_relevance: bool = False) -> list[dict[str, Any]]:
35
+ profile = self.profile
36
+ relevance = f'({self.relevance}/5)' if include_relevance else ''
37
+ return [
38
+ {
39
+ 'type': 'markdown',
40
+ 'text': f'[{profile.display_name}](mailto:{profile.email}), {self.job_title} at [**{self.organization_name}**](https://{self.organization_domain}) {relevance}',
41
+ },
42
+ {
43
+ 'type': 'markdown',
44
+ 'text': self.summary,
45
+ },
46
+ ] ### [/analysis-as_slack_blocks]
@@ -0,0 +1,30 @@
1
+ import os
2
+ from typing import Any
3
+
4
+ import httpx
5
+ import logfire
6
+
7
+ ### [send_slack_message]
8
+ API_KEY = os.getenv('SLACK_API_KEY')
9
+ assert API_KEY, 'SLACK_API_KEY is not set'
10
+
11
+
12
+ @logfire.instrument('Send Slack message')
13
+ async def send_slack_message(channel: str, blocks: list[dict[str, Any]]):
14
+ client = httpx.AsyncClient()
15
+ response = await client.post(
16
+ 'https://slack.com/api/chat.postMessage',
17
+ json={
18
+ 'channel': channel,
19
+ 'blocks': blocks,
20
+ },
21
+ headers={
22
+ 'Authorization': f'Bearer {API_KEY}',
23
+ },
24
+ timeout=5,
25
+ )
26
+ response.raise_for_status()
27
+ result = response.json()
28
+ if not result.get('ok', False):
29
+ error = result.get('error', 'Unknown error')
30
+ raise Exception(f'Failed to send to Slack: {error}') ### [/send_slack_message]
@@ -0,0 +1,31 @@
1
+ import logfire
2
+
3
+ ### [import-modal]
4
+ import modal ### [/import-modal]
5
+
6
+ from .models import Analysis
7
+
8
+
9
+ ### [analysis_store]
10
+ class AnalysisStore:
11
+ @classmethod
12
+ @logfire.instrument('Add analysis to store')
13
+ async def add(cls, analysis: Analysis):
14
+ await cls._get_store().put.aio(analysis.profile.email, analysis.model_dump())
15
+
16
+ @classmethod
17
+ @logfire.instrument('List analyses from store')
18
+ async def list(cls) -> list[Analysis]:
19
+ return [
20
+ Analysis.model_validate(analysis)
21
+ async for analysis in cls._get_store().values.aio()
22
+ ]
23
+
24
+ @classmethod
25
+ @logfire.instrument('Clear analyses from store')
26
+ async def clear(cls):
27
+ await cls._get_store().clear.aio()
28
+
29
+ @classmethod
30
+ def _get_store(cls) -> modal.Dict:
31
+ return modal.Dict.from_name('analyses', create_if_missing=True) # type: ignore ### [/analysis_store]
@@ -1,4 +1,4 @@
1
- """Example demonstrating how to use PydanticAI to generate SQL queries based on user input.
1
+ """Example demonstrating how to use Pydantic AI to generate SQL queries based on user input.
2
2
 
3
3
  Run postgres with:
4
4
 
@@ -16,20 +16,20 @@ from collections.abc import AsyncGenerator
16
16
  from contextlib import asynccontextmanager
17
17
  from dataclasses import dataclass
18
18
  from datetime import date
19
- from typing import Annotated, Any, Union
19
+ from typing import Annotated, Any, TypeAlias
20
20
 
21
21
  import asyncpg
22
22
  import logfire
23
23
  from annotated_types import MinLen
24
24
  from devtools import debug
25
25
  from pydantic import BaseModel, Field
26
- from typing_extensions import TypeAlias
27
26
 
28
27
  from pydantic_ai import Agent, ModelRetry, RunContext, format_as_xml
29
28
 
30
29
  # 'if-token-present' means nothing will be sent (and the example will work) if you don't have logfire configured
31
30
  logfire.configure(send_to_logfire='if-token-present')
32
31
  logfire.instrument_asyncpg()
32
+ logfire.instrument_pydantic_ai()
33
33
 
34
34
  DB_SCHEMA = """
35
35
  CREATE TABLE records (
@@ -90,13 +90,12 @@ class InvalidRequest(BaseModel):
90
90
  error_message: str
91
91
 
92
92
 
93
- Response: TypeAlias = Union[Success, InvalidRequest]
94
- agent: Agent[Deps, Response] = Agent(
95
- 'google-gla:gemini-1.5-flash',
93
+ Response: TypeAlias = Success | InvalidRequest
94
+ agent = Agent[Deps, Response](
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,
99
- instrument=True,
100
99
  )
101
100
 
102
101
 
@@ -20,13 +20,14 @@ from pydantic_ai.models import KnownModelName
20
20
 
21
21
  # 'if-token-present' means nothing will be sent (and the example will work) if you don't have logfire configured
22
22
  logfire.configure(send_to_logfire='if-token-present')
23
+ logfire.instrument_pydantic_ai()
23
24
 
24
- agent = Agent(instrument=True)
25
+ agent = Agent()
25
26
 
26
27
  # models to try, and the appropriate env var
27
28
  models: list[tuple[KnownModelName, str]] = [
28
- ('google-gla:gemini-1.5-flash', 'GEMINI_API_KEY'),
29
- ('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'),
30
31
  ('groq:llama-3.3-70b-versatile', 'GROQ_API_KEY'),
31
32
  ]
32
33
 
@@ -41,7 +42,7 @@ async def main():
41
42
  console.log(f'Using model: {model}')
42
43
  with Live('', console=console, vertical_overflow='visible') as live:
43
44
  async with agent.run_stream(prompt, model=model) as result:
44
- async for message in result.stream():
45
+ async for message in result.stream_output():
45
46
  live.update(Markdown(message))
46
47
  console.log(result.usage())
47
48
  else:
@@ -11,7 +11,7 @@ Run with:
11
11
  from typing import Annotated
12
12
 
13
13
  import logfire
14
- from pydantic import Field, ValidationError
14
+ from pydantic import Field
15
15
  from rich.console import Console
16
16
  from rich.live import Live
17
17
  from rich.table import Table
@@ -21,6 +21,7 @@ from pydantic_ai import Agent
21
21
 
22
22
  # 'if-token-present' means nothing will be sent (and the example will work) if you don't have logfire configured
23
23
  logfire.configure(send_to_logfire='if-token-present')
24
+ logfire.instrument_pydantic_ai()
24
25
 
25
26
 
26
27
  class Whale(TypedDict):
@@ -38,7 +39,7 @@ class Whale(TypedDict):
38
39
  description: NotRequired[Annotated[str, Field(description='Short Description')]]
39
40
 
40
41
 
41
- agent = Agent('openai:gpt-4', output_type=list[Whale], instrument=True)
42
+ agent = Agent('openai:gpt-4', output_type=list[Whale])
42
43
 
43
44
 
44
45
  async def main():
@@ -50,20 +51,7 @@ async def main():
50
51
  ) as result:
51
52
  console.print('Response:', style='green')
52
53
 
53
- async for message, last in result.stream_structured(debounce_by=0.01):
54
- try:
55
- whales = await result.validate_structured_output(
56
- message, allow_partial=not last
57
- )
58
- except ValidationError as exc:
59
- if all(
60
- e['type'] == 'missing' and e['loc'] == ('response',)
61
- for e in exc.errors()
62
- ):
63
- continue
64
- else:
65
- raise
66
-
54
+ async for whales in result.stream_output(debounce_by=0.01):
67
55
  table = Table(
68
56
  title='Species of Whale',
69
57
  caption='Streaming Structured responses from GPT-4',
@@ -1,4 +1,4 @@
1
- """Example of PydanticAI with multiple tools which the LLM needs to call in turn to answer a question.
1
+ """Example of Pydantic AI with multiple tools which the LLM needs to call in turn to answer a question.
2
2
 
3
3
  In this case the idea is a "weather" agent — the user can ask for the weather in multiple cities,
4
4
  the agent will use the `get_lat_lng` tool to get the latitude and longitude of the locations, then use
@@ -12,70 +12,55 @@ Run with:
12
12
  from __future__ import annotations as _annotations
13
13
 
14
14
  import asyncio
15
- import os
16
15
  from dataclasses import dataclass
17
16
  from typing import Any
18
17
 
19
18
  import logfire
20
- from devtools import debug
21
19
  from httpx import AsyncClient
20
+ from pydantic import BaseModel
22
21
 
23
- from pydantic_ai import Agent, ModelRetry, RunContext
22
+ from pydantic_ai import Agent, RunContext
24
23
 
25
24
  # 'if-token-present' means nothing will be sent (and the example will work) if you don't have logfire configured
26
25
  logfire.configure(send_to_logfire='if-token-present')
26
+ logfire.instrument_pydantic_ai()
27
27
 
28
28
 
29
29
  @dataclass
30
30
  class Deps:
31
31
  client: AsyncClient
32
- weather_api_key: str | None
33
- geo_api_key: str | None
34
32
 
35
33
 
36
34
  weather_agent = Agent(
37
- 'openai:gpt-4o',
35
+ 'openai:gpt-5-mini',
38
36
  # 'Be concise, reply with one sentence.' is enough for some models (like openai) to use
39
37
  # the below tools appropriately, but others like anthropic and gemini require a bit more direction.
40
- system_prompt=(
41
- 'Be concise, reply with one sentence.'
42
- 'Use the `get_lat_lng` tool to get the latitude and longitude of the locations, '
43
- 'then use the `get_weather` tool to get the weather.'
44
- ),
38
+ instructions='Be concise, reply with one sentence.',
45
39
  deps_type=Deps,
46
40
  retries=2,
47
- instrument=True,
48
41
  )
49
42
 
50
43
 
44
+ class LatLng(BaseModel):
45
+ lat: float
46
+ lng: float
47
+
48
+
51
49
  @weather_agent.tool
52
- async def get_lat_lng(
53
- ctx: RunContext[Deps], location_description: str
54
- ) -> dict[str, float]:
50
+ async def get_lat_lng(ctx: RunContext[Deps], location_description: str) -> LatLng:
55
51
  """Get the latitude and longitude of a location.
56
52
 
57
53
  Args:
58
54
  ctx: The context.
59
55
  location_description: A description of a location.
60
56
  """
61
- if ctx.deps.geo_api_key is None:
62
- # if no API key is provided, return a dummy response (London)
63
- return {'lat': 51.1, 'lng': -0.1}
64
-
65
- params = {
66
- 'q': location_description,
67
- 'api_key': ctx.deps.geo_api_key,
68
- }
69
- with logfire.span('calling geocode API', params=params) as span:
70
- r = await ctx.deps.client.get('https://geocode.maps.co/search', params=params)
71
- r.raise_for_status()
72
- data = r.json()
73
- span.set_attribute('response', data)
74
-
75
- if data:
76
- return {'lat': data[0]['lat'], 'lng': data[0]['lon']}
77
- else:
78
- raise ModelRetry('Could not find the location')
57
+ # NOTE: the response here will be random, and is not related to the location description.
58
+ r = await ctx.deps.client.get(
59
+ 'https://demo-endpoints.pydantic.workers.dev/latlng',
60
+ params={'location': location_description},
61
+ )
62
+ r.raise_for_status()
63
+ return LatLng.model_validate_json(r.content)
79
64
 
80
65
 
81
66
  @weather_agent.tool
@@ -87,69 +72,32 @@ async def get_weather(ctx: RunContext[Deps], lat: float, lng: float) -> dict[str
87
72
  lat: Latitude of the location.
88
73
  lng: Longitude of the location.
89
74
  """
90
- if ctx.deps.weather_api_key is None:
91
- # if no API key is provided, return a dummy response
92
- return {'temperature': '21 °C', 'description': 'Sunny'}
93
-
94
- params = {
95
- 'apikey': ctx.deps.weather_api_key,
96
- 'location': f'{lat},{lng}',
97
- 'units': 'metric',
98
- }
99
- with logfire.span('calling weather API', params=params) as span:
100
- r = await ctx.deps.client.get(
101
- 'https://api.tomorrow.io/v4/weather/realtime', params=params
102
- )
103
- r.raise_for_status()
104
- data = r.json()
105
- span.set_attribute('response', data)
106
-
107
- values = data['data']['values']
108
- # https://docs.tomorrow.io/reference/data-layers-weather-codes
109
- code_lookup = {
110
- 1000: 'Clear, Sunny',
111
- 1100: 'Mostly Clear',
112
- 1101: 'Partly Cloudy',
113
- 1102: 'Mostly Cloudy',
114
- 1001: 'Cloudy',
115
- 2000: 'Fog',
116
- 2100: 'Light Fog',
117
- 4000: 'Drizzle',
118
- 4001: 'Rain',
119
- 4200: 'Light Rain',
120
- 4201: 'Heavy Rain',
121
- 5000: 'Snow',
122
- 5001: 'Flurries',
123
- 5100: 'Light Snow',
124
- 5101: 'Heavy Snow',
125
- 6000: 'Freezing Drizzle',
126
- 6001: 'Freezing Rain',
127
- 6200: 'Light Freezing Rain',
128
- 6201: 'Heavy Freezing Rain',
129
- 7000: 'Ice Pellets',
130
- 7101: 'Heavy Ice Pellets',
131
- 7102: 'Light Ice Pellets',
132
- 8000: 'Thunderstorm',
133
- }
75
+ # NOTE: the responses here will be random, and are not related to the lat and lng.
76
+ temp_response, descr_response = await asyncio.gather(
77
+ ctx.deps.client.get(
78
+ 'https://demo-endpoints.pydantic.workers.dev/number',
79
+ params={'min': 10, 'max': 30},
80
+ ),
81
+ ctx.deps.client.get(
82
+ 'https://demo-endpoints.pydantic.workers.dev/weather',
83
+ params={'lat': lat, 'lng': lng},
84
+ ),
85
+ )
86
+ temp_response.raise_for_status()
87
+ descr_response.raise_for_status()
134
88
  return {
135
- 'temperature': f'{values["temperatureApparent"]:0.0f}°C',
136
- 'description': code_lookup.get(values['weatherCode'], 'Unknown'),
89
+ 'temperature': f'{temp_response.text} °C',
90
+ 'description': descr_response.text,
137
91
  }
138
92
 
139
93
 
140
94
  async def main():
141
95
  async with AsyncClient() as client:
142
- # create a free API key at https://www.tomorrow.io/weather-api/
143
- weather_api_key = os.getenv('WEATHER_API_KEY')
144
- # create a free API key at https://geocode.maps.co/
145
- geo_api_key = os.getenv('GEO_API_KEY')
146
- deps = Deps(
147
- client=client, weather_api_key=weather_api_key, geo_api_key=geo_api_key
148
- )
96
+ logfire.instrument_httpx(client, capture_all=True)
97
+ deps = Deps(client=client)
149
98
  result = await weather_agent.run(
150
99
  'What is the weather like in London and in Wiltshire?', deps=deps
151
100
  )
152
- debug(result)
153
101
  print('Response:', result.output)
154
102
 
155
103
 
@@ -1,11 +1,11 @@
1
1
  from __future__ import annotations as _annotations
2
2
 
3
3
  import json
4
- import os
5
4
 
6
5
  from httpx import AsyncClient
6
+ from pydantic import BaseModel
7
7
 
8
- from pydantic_ai.messages import ToolCallPart, ToolReturnPart
8
+ from pydantic_ai import ToolCallPart, ToolReturnPart
9
9
  from pydantic_ai_examples.weather_agent import Deps, weather_agent
10
10
 
11
11
  try:
@@ -18,10 +18,7 @@ except ImportError as e:
18
18
  TOOL_TO_DISPLAY_NAME = {'get_lat_lng': 'Geocoding API', 'get_weather': 'Weather API'}
19
19
 
20
20
  client = AsyncClient()
21
- weather_api_key = os.getenv('WEATHER_API_KEY')
22
- # create a free API key at https://geocode.maps.co/
23
- geo_api_key = os.getenv('GEO_API_KEY')
24
- deps = Deps(client=client, weather_api_key=weather_api_key, geo_api_key=geo_api_key)
21
+ deps = Deps(client=client)
25
22
 
26
23
 
27
24
  async def stream_from_agent(prompt: str, chatbot: list[dict], past_messages: list):
@@ -33,16 +30,12 @@ async def stream_from_agent(prompt: str, chatbot: list[dict], past_messages: lis
33
30
  for message in result.new_messages():
34
31
  for call in message.parts:
35
32
  if isinstance(call, ToolCallPart):
36
- call_args = (
37
- call.args.args_json
38
- if hasattr(call.args, 'args_json')
39
- else json.dumps(call.args.args_dict)
40
- )
33
+ call_args = call.args_as_json_str()
41
34
  metadata = {
42
35
  'title': f'🛠️ Using {TOOL_TO_DISPLAY_NAME[call.tool_name]}',
43
36
  }
44
37
  if call.tool_call_id is not None:
45
- metadata['id'] = {call.tool_call_id}
38
+ metadata['id'] = call.tool_call_id
46
39
 
47
40
  gr_message = {
48
41
  'role': 'assistant',
@@ -56,9 +49,11 @@ async def stream_from_agent(prompt: str, chatbot: list[dict], past_messages: lis
56
49
  gr_message.get('metadata', {}).get('id', '')
57
50
  == call.tool_call_id
58
51
  ):
59
- gr_message['content'] += (
60
- f'\nOutput: {json.dumps(call.content)}'
61
- )
52
+ if isinstance(call.content, BaseModel):
53
+ json_content = call.content.model_dump_json()
54
+ else:
55
+ json_content = json.dumps(call.content)
56
+ gr_message['content'] += f'\nOutput: {json_content}'
62
57
  yield gr.skip(), chatbot, gr.skip()
63
58
  chatbot.append({'role': 'assistant', 'content': ''})
64
59
  async for message in result.stream_text():
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-ai-examples
3
- Version: 0.1.2
4
- Summary: Examples of how to use PydanticAI and what it can do.
5
- Author-email: Samuel Colvin <samuel@pydantic.dev>
3
+ Version: 1.12.0
4
+ Summary: Examples of how to use Pydantic AI and what it can do.
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
7
- Classifier: Development Status :: 4 - Beta
7
+ License-File: LICENSE
8
+ Classifier: Development Status :: 5 - Production/Stable
8
9
  Classifier: Environment :: Console
9
10
  Classifier: Environment :: MacOS X
10
11
  Classifier: Intended Audience :: Developers
@@ -16,28 +17,31 @@ Classifier: Operating System :: Unix
16
17
  Classifier: Programming Language :: Python
17
18
  Classifier: Programming Language :: Python :: 3
18
19
  Classifier: Programming Language :: Python :: 3 :: Only
19
- Classifier: Programming Language :: Python :: 3.9
20
20
  Classifier: Programming Language :: Python :: 3.10
21
21
  Classifier: Programming Language :: Python :: 3.11
22
22
  Classifier: Programming Language :: Python :: 3.12
23
23
  Classifier: Programming Language :: Python :: 3.13
24
24
  Classifier: Topic :: Internet
25
25
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
- Requires-Python: >=3.9
26
+ Requires-Python: >=3.10
27
27
  Requires-Dist: asyncpg>=0.30.0
28
+ Requires-Dist: datasets>=4.0.0
28
29
  Requires-Dist: devtools>=0.12.2
30
+ Requires-Dist: duckdb>=1.3.2
29
31
  Requires-Dist: fastapi>=0.115.4
30
- Requires-Dist: gradio>=5.9.0; python_version > '3.9'
31
- Requires-Dist: logfire[asyncpg,fastapi,sqlite3]>=2.6
32
- Requires-Dist: mcp[cli]>=1.4.1; python_version >= '3.10'
33
- Requires-Dist: pydantic-ai-slim[anthropic,groq,openai,vertexai]==0.1.2
34
- Requires-Dist: pydantic-evals==0.1.2
32
+ Requires-Dist: gradio>=5.9.0
33
+ Requires-Dist: logfire[asyncpg,fastapi,httpx,sqlite3]>=3.14.1
34
+ Requires-Dist: mcp[cli]>=1.4.1
35
+ Requires-Dist: modal>=1.0.4
36
+ Requires-Dist: pandas>=2.2.3
37
+ Requires-Dist: pydantic-ai-slim[ag-ui,anthropic,groq,openai,vertexai]==1.12.0
38
+ Requires-Dist: pydantic-evals==1.12.0
35
39
  Requires-Dist: python-multipart>=0.0.17
36
40
  Requires-Dist: rich>=13.9.2
37
41
  Requires-Dist: uvicorn>=0.32.0
38
42
  Description-Content-Type: text/markdown
39
43
 
40
- # PydanticAI Examples
44
+ # Pydantic AI Examples
41
45
 
42
46
  [![CI](https://github.com/pydantic/pydantic-ai/actions/workflows/ci.yml/badge.svg?event=push)](https://github.com/pydantic/pydantic-ai/actions/workflows/ci.yml?query=branch%3Amain)
43
47
  [![Coverage](https://coverage-badge.samuelcolvin.workers.dev/pydantic/pydantic-ai.svg)](https://coverage-badge.samuelcolvin.workers.dev/redirect/pydantic/pydantic-ai)
@@ -45,6 +49,6 @@ Description-Content-Type: text/markdown
45
49
  [![versions](https://img.shields.io/pypi/pyversions/pydantic-ai.svg)](https://github.com/pydantic/pydantic-ai)
46
50
  [![license](https://img.shields.io/github/license/pydantic/pydantic-ai.svg?v)](https://github.com/pydantic/pydantic-ai/blob/main/LICENSE)
47
51
 
48
- Examples of how to use PydanticAI and what it can do.
52
+ Examples of how to use Pydantic AI and what it can do.
49
53
 
50
54
  For full documentation of these examples and how to run them, see [ai.pydantic.dev/examples/](https://ai.pydantic.dev/examples/).
@@ -0,0 +1,50 @@
1
+ pydantic_ai_examples/__main__.py,sha256=i0LEo2JBOZ-gnHED0ou5Bya43gi7KmOyQ_jKN7M5Ces,1647
2
+ pydantic_ai_examples/bank_support.py,sha256=O9r6yQraDRPibWLOC1wyZu0n_Nr7Exg4u7wEHh25czk,2664
3
+ pydantic_ai_examples/chat_app.html,sha256=90XhxrpDAT09mPVTn9edEn8PqAD-tHxWkeeMz9r_okQ,2580
4
+ pydantic_ai_examples/chat_app.py,sha256=AX28rI0TR9lTPLDOd0uEkmirvfIZCRyCGr_VdGiOkHM,7053
5
+ pydantic_ai_examples/chat_app.ts,sha256=2KfZ2rJU2o0iCPjelyqEi5sH6vfemzWaa5Evx_VcAE4,3307
6
+ pydantic_ai_examples/data_analyst.py,sha256=sC6mcgfeWzfj4STB7J_7oAWC7T8Y0NWvlIeQ8XND9zA,3752
7
+ pydantic_ai_examples/flight_booking.py,sha256=x8FbztbAiqNdDACzal1O5M80syjt8UuGm_wqHpybeQM,7415
8
+ pydantic_ai_examples/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ pydantic_ai_examples/pydantic_model.py,sha256=4u_-sdpKSF_lRMLSI-WVYwsyIxgdOpq-8LSCJunoyvA,774
10
+ pydantic_ai_examples/question_graph.py,sha256=ERjlfHxKXswISed6TJtj60SFoTIYe-PyCTZoYR4OJkY,5073
11
+ pydantic_ai_examples/rag.py,sha256=t1um_C3EqX7dhbdopWFqYgHfnKUTyeVWxD3SK7AUdio,8010
12
+ pydantic_ai_examples/roulette_wheel.py,sha256=2YHKbGzYOkLsd98hO3ntjM6pChR1UpmsRrLD36Qh5f0,1654
13
+ pydantic_ai_examples/sql_gen.py,sha256=akgJv4TSImw6O4NRgQZh92QITSmDeEyvoGQcU3oUNFQ,5159
14
+ pydantic_ai_examples/stream_markdown.py,sha256=4uEK6dzC9jVcQTRaYBEDzYfYAJPYHZWfLJ-ZMtmI8y4,2453
15
+ pydantic_ai_examples/stream_whales.py,sha256=Yoa7IuqN_6fowfYSINW39uPCthYu9FKChF-QBmQqWb8,2721
16
+ pydantic_ai_examples/weather_agent.py,sha256=FZF7pgL2U24m-ymFUw6MnqASVpXOfl49ilrYAtZXlOo,3185
17
+ pydantic_ai_examples/weather_agent_gradio.py,sha256=MCoNp5TgWj628ABoZpTUVJYIeSV_C-ig08WfcssDH7A,4719
18
+ pydantic_ai_examples/ag_ui/__init__.py,sha256=ZZs2V-5e9RaLl_7hJAq9-0Juk_f0mk2Vr7a4QT2QB-k,1174
19
+ pydantic_ai_examples/ag_ui/__main__.py,sha256=PMycatJt8Abb-Q8HXRGZoEY6vnOcvRebH7iI9MxLknA,225
20
+ pydantic_ai_examples/ag_ui/api/__init__.py,sha256=Pe307_ET_ERKBP-8Vs4L1yZRkK3ILPpajwxDpeW8YiI,673
21
+ pydantic_ai_examples/ag_ui/api/agentic_chat.py,sha256=QGb7q4AMq5PD1-D-S-71GsMs3wAhH2niUeRryhjL12s,577
22
+ pydantic_ai_examples/ag_ui/api/agentic_generative_ui.py,sha256=RnkSjb8C_J9kXPuB7nFI1knkPF30OkOoSRXoAX2h2Ck,3531
23
+ pydantic_ai_examples/ag_ui/api/human_in_the_loop.py,sha256=Jb_0Sryb4mUOZmr1k9MVTciGUAcC8-tzuyNCaCTWZhc,807
24
+ pydantic_ai_examples/ag_ui/api/predictive_state_updates.py,sha256=PO3SZPCzmWowpEPnqez-oLlMRsPD3MnJArpdwDYThO4,2165
25
+ pydantic_ai_examples/ag_ui/api/shared_state.py,sha256=dr7vCTuZN2tyUrdroD25r69YBPjQFeAPaOt_NbenHyE,3843
26
+ pydantic_ai_examples/ag_ui/api/tool_based_generative_ui.py,sha256=rW0Inzd9_yDqdTE6HmnnF7M-LsR_l4woiwlGbJBHLSM,261
27
+ pydantic_ai_examples/evals/__init__.py,sha256=4f1v2o4F-gnUVtlkZU-dpwwwbLhqRxMcZv676atjNLg,115
28
+ pydantic_ai_examples/evals/agent.py,sha256=o_l6I4DF3HXh7fgsmyz7mViq1ckdFV1Hxq_B7KJPLa0,2041
29
+ pydantic_ai_examples/evals/custom_evaluators.py,sha256=siSpALUMrUGJ1DDrm0Ejniuxhmxhlvee_jubgXjOAeU,2244
30
+ pydantic_ai_examples/evals/example_01_generate_dataset.py,sha256=R-cV9bBHMA8EMIyveP5Yf2p3_VV-g_NSXtDa_zz0ODs,2368
31
+ pydantic_ai_examples/evals/example_02_add_custom_evaluators.py,sha256=pFX0bvVeyfbZGGb0LSajRW-g1ZiVID3e3-sEXZVcjv8,977
32
+ pydantic_ai_examples/evals/example_03_unit_testing.py,sha256=G4Ry7ykJfozaQ9GEXi6cnz0O-6pGBrZIkV4_6RNK194,1207
33
+ pydantic_ai_examples/evals/example_04_compare_models.py,sha256=4oPIeFgbk2vMkN7asN6LjWMYPatMpUFLkKhEzrioqJg,1199
34
+ pydantic_ai_examples/evals/models.py,sha256=QYe_fNv03fmF4ssgSqutHgGx2YX5NLKhhth8-0XFnWo,1776
35
+ pydantic_ai_examples/evals/datasets/time_range_v1.yaml,sha256=pSUawuDen4NQt2RqqJNmrVENgksTWxIFcw-Kkao_yo8,4193
36
+ pydantic_ai_examples/evals/datasets/time_range_v1_schema.json,sha256=xS-wRRSvcoG2FcQZGdL0i332mbjsZh9MOSJAND6VkWU,19932
37
+ pydantic_ai_examples/evals/datasets/time_range_v2.yaml,sha256=zIffxC5bR2l05MrrECJsTHiagFaz8nIPTH-YrmjJz8I,4326
38
+ pydantic_ai_examples/evals/datasets/time_range_v2_schema.json,sha256=GDbDtBH1skdbUzK5Wd_0-SNXTmEWHMTYhhshaLsq_1Q,21309
39
+ pydantic_ai_examples/slack_lead_qualifier/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ pydantic_ai_examples/slack_lead_qualifier/agent.py,sha256=kskE4RjlqeqAT51NDt7FoC1OIyQ47DqFcTDkCOvQS9k,1935
41
+ pydantic_ai_examples/slack_lead_qualifier/app.py,sha256=KALNxIV8hz0lGxFclZHxolqoH4MsiIYga_CmpidzONE,1036
42
+ pydantic_ai_examples/slack_lead_qualifier/functions.py,sha256=4LsYtPH_SBo_rJ7008DXvKq_SOwiGtweW_DfzJh8R0s,2196
43
+ pydantic_ai_examples/slack_lead_qualifier/modal.py,sha256=f464AaeyP-n3UIfvEVVc4DZ7FQQtsEX7-kUP3VqoPYo,1635
44
+ pydantic_ai_examples/slack_lead_qualifier/models.py,sha256=WTp6D2WCASXqrjPVT3vGgTSYATLPBM3_cjq9wvXMRao,1586
45
+ pydantic_ai_examples/slack_lead_qualifier/slack.py,sha256=VJVfMeUXYClWUJBLHNuaW8PB2sxjNzpTC-O_AJwcxQ4,833
46
+ pydantic_ai_examples/slack_lead_qualifier/store.py,sha256=04vB4eZWKk_Tx0b9K4QuVI1U24JEyJyBS4X76cui7OI,896
47
+ pydantic_ai_examples-1.12.0.dist-info/METADATA,sha256=vNTvNoFtwV9hR_ENchwD2xp8RaL6ofm-T-Q98u27mGg,2763
48
+ pydantic_ai_examples-1.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
+ pydantic_ai_examples-1.12.0.dist-info/licenses/LICENSE,sha256=vA6Jc482lEyBBuGUfD1pYx-cM7jxvLYOxPidZ30t_PQ,1100
50
+ pydantic_ai_examples-1.12.0.dist-info/RECORD,,
@@ -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.
@@ -1,30 +0,0 @@
1
- pydantic_ai_examples/__main__.py,sha256=i0LEo2JBOZ-gnHED0ou5Bya43gi7KmOyQ_jKN7M5Ces,1647
2
- pydantic_ai_examples/bank_support.py,sha256=u_mkEPiUt3YDnlVvBgwUp2VShZ33Hdm0AASSL7_ymXY,2661
3
- pydantic_ai_examples/chat_app.html,sha256=90XhxrpDAT09mPVTn9edEn8PqAD-tHxWkeeMz9r_okQ,2580
4
- pydantic_ai_examples/chat_app.py,sha256=OsKy68EHFTKSDMH9Yo53txm7P7b4-b4LJnTvUUY0B78,7089
5
- pydantic_ai_examples/chat_app.ts,sha256=2KfZ2rJU2o0iCPjelyqEi5sH6vfemzWaa5Evx_VcAE4,3307
6
- pydantic_ai_examples/flight_booking.py,sha256=TAlotG4Hiuuaps6Pyfokbte4GXpVLo1TVep_ExaHAB4,7442
7
- pydantic_ai_examples/pydantic_model.py,sha256=fQFPkulep9JQgICpEMrEaj3NpzBiz4OO8WAaeaw4U7c,758
8
- pydantic_ai_examples/question_graph.py,sha256=ZFb1Z2XHLQy-VD5JGUtj8NCGFNQByg7f7YsBpwOCquY,5091
9
- pydantic_ai_examples/rag.py,sha256=LYgJSJYSAYyVuIOvVYSvfzAhxVey0pY--hJ3gCk3Lw4,7989
10
- pydantic_ai_examples/roulette_wheel.py,sha256=TFJAn0hnGSMB_LCAASfc5nKqeN8ImHBYCQStfq5Kp8E,1674
11
- pydantic_ai_examples/sql_gen.py,sha256=rDvN7qm60Sq6J6rP7on8W7yE0x-fQCifC55N-RjQQnk,5195
12
- pydantic_ai_examples/stream_markdown.py,sha256=-uNLQBAU7kpem16aMfLcAxdSG6jnqMFnofqqFc3Qv08,2429
13
- pydantic_ai_examples/stream_whales.py,sha256=EuKdhc0G3kqXAeimpshU0_ThugG5r_ENxe2c0KYBVC4,3213
14
- pydantic_ai_examples/weather_agent.py,sha256=WKljXL_mSbKguNvZmvmBI4SBi5e0qa5dQ28xJSIVZj4,4874
15
- pydantic_ai_examples/weather_agent_gradio.py,sha256=0Of2pYrT1H-qt2NjBXzLovI-1D_nl-afRtIBPJ9xTZM,4893
16
- pydantic_ai_examples/evals/__init__.py,sha256=4f1v2o4F-gnUVtlkZU-dpwwwbLhqRxMcZv676atjNLg,115
17
- pydantic_ai_examples/evals/agent.py,sha256=KjCsUiL28RCNT6NwoQnQCwJ0xRw3EUGdIrYhlIjmVqI,2042
18
- pydantic_ai_examples/evals/custom_evaluators.py,sha256=Uz37_wbT4uA6s9fl46nTsH3NQKyS1KamMPPP860stww,2245
19
- pydantic_ai_examples/evals/example_01_generate_dataset.py,sha256=7fhTY4IMN0xEODGEKtrNlaEIYkqYRauC6w6NRIQnFWY,2369
20
- pydantic_ai_examples/evals/example_02_add_custom_evaluators.py,sha256=mNPEIDnuE3RcfdMtBKhs5aGUdcDtDQD-v7KoSuE1ZDk,978
21
- pydantic_ai_examples/evals/example_03_unit_testing.py,sha256=QNkfMQgBZrN8wWhj0ZRsq9XC46AgtFo9gklgh52e4iE,1151
22
- pydantic_ai_examples/evals/example_04_compare_models.py,sha256=H00BaMEF6etK5497kFjWmdEFbNgVhhq25RDw8KPrLuw,1201
23
- pydantic_ai_examples/evals/models.py,sha256=QYe_fNv03fmF4ssgSqutHgGx2YX5NLKhhth8-0XFnWo,1776
24
- pydantic_ai_examples/evals/datasets/time_range_v1.yaml,sha256=pSUawuDen4NQt2RqqJNmrVENgksTWxIFcw-Kkao_yo8,4193
25
- pydantic_ai_examples/evals/datasets/time_range_v1_schema.json,sha256=xS-wRRSvcoG2FcQZGdL0i332mbjsZh9MOSJAND6VkWU,19932
26
- pydantic_ai_examples/evals/datasets/time_range_v2.yaml,sha256=zIffxC5bR2l05MrrECJsTHiagFaz8nIPTH-YrmjJz8I,4326
27
- pydantic_ai_examples/evals/datasets/time_range_v2_schema.json,sha256=GDbDtBH1skdbUzK5Wd_0-SNXTmEWHMTYhhshaLsq_1Q,21309
28
- pydantic_ai_examples-0.1.2.dist-info/METADATA,sha256=3RDsjVZVRHg7hkiX60r5tkKGYLWGvfcEbJOn9O4N0bM,2542
29
- pydantic_ai_examples-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
- pydantic_ai_examples-0.1.2.dist-info/RECORD,,