- Spec files
pypi-pydantic-ai
Describes: pkg:pypi/pydantic-ai@0.8.x
- Description
- Agent Framework / shim to use Pydantic with LLMs
- Author
- tessl
- Last updated
output.md docs/
1# Output Types and Validation23Flexible output handling supporting structured data validation using Pydantic models, text outputs, tool-based outputs, and native model outputs with comprehensive type safety.45## Capabilities67### Structured Output Types89Output configuration classes that determine how agent responses are processed and validated.1011```python { .api }12class ToolOutput[OutputDataT]:13"""14Tool-based output configuration where tools generate the final result.15"""16def __init__(17self,18tools: list[Tool],19*,20defer: bool = False21):22"""23Configure tool-based output.2425Parameters:26- tools: List of tools that can generate output27- defer: Whether to defer tool execution28"""2930class NativeOutput[OutputDataT]:31"""32Native structured output configuration using model's built-in structured output.33"""34pass3536class PromptedOutput[OutputDataT]:37"""38Prompted output configuration where model is prompted to return structured data.39"""40pass4142class TextOutput[OutputDataT]:43"""44Text output configuration with optional conversion function.45"""46def __init__(47self,48converter: TextOutputFunc[OutputDataT] | None = None49):50"""51Configure text output.5253Parameters:54- converter: Optional function to convert text to desired type55"""56```5758### Deferred Tool Calls5960Container for managing deferred tool execution.6162```python { .api }63class DeferredToolCalls:64"""65Container for deferred tool calls that can be executed later.66"""67def __init__(self, tool_calls: list[ToolCallPart]): ...6869def execute_all(70self,71deps: Any = None72) -> list[Any]:73"""74Execute all deferred tool calls.7576Parameters:77- deps: Dependencies to pass to tools7879Returns:80List of tool execution results81"""82```8384### Structured Dictionary Factory8586Factory function for creating structured dictionary types.8788```python { .api }89def StructuredDict() -> type[dict[str, Any]]:90"""91Create structured dictionary type for flexible output handling.9293Returns:94Dictionary type that can be used as result_type for agents95"""96```9798### Output Type Aliases99100Type definitions for various output configurations and functions.101102```python { .api }103OutputMode = Literal['tools', 'json', 'str']104105StructuredOutputMode = Literal['json', 'str']106107OutputSpec[T_co] = (108type[T_co] |109ToolOutput[T_co] |110NativeOutput[T_co] |111PromptedOutput[T_co] |112TextOutput[T_co]113)114115OutputTypeOrFunction[T_co] = (116OutputSpec[T_co] |117Callable[[str], T_co]118)119120TextOutputFunc[T_co] = Callable[[str], T_co]121```122123### Output Processing124125Internal types and functions for output processing (advanced usage).126127```python { .api }128class OutputTypeWrapper[T]:129"""Internal wrapper for output type processing."""130def __init__(131self,132output_type: OutputSpec[T],133allow_text_output: bool = True134): ...135136def validate_output(self, data: Any) -> T: ...137def get_output_mode(self) -> OutputMode: ...138```139140## Usage Examples141142### Basic Structured Output with Pydantic143144```python145from pydantic_ai import Agent146from pydantic import BaseModel147148class WeatherInfo(BaseModel):149location: str150temperature: float151condition: str152humidity: int153154# Agent with structured output155agent = Agent(156model='gpt-4',157system_prompt='Extract weather information from text.',158result_type=WeatherInfo159)160161result = agent.run_sync(162'The weather in Paris is sunny, 22°C with 65% humidity'163)164165print(result.data.location) # "Paris"166print(result.data.temperature) # 22.0167print(result.data.condition) # "sunny"168print(result.data.humidity) # 65169```170171### Tool-Based Output172173```python174from pydantic_ai import Agent, ToolOutput, tool175176@tool177def calculate_result(numbers: list[float], operation: str) -> float:178"""Perform calculation on numbers."""179if operation == 'sum':180return sum(numbers)181elif operation == 'average':182return sum(numbers) / len(numbers)183elif operation == 'max':184return max(numbers)185else:186raise ValueError(f"Unknown operation: {operation}")187188# Agent with tool-based output189agent = Agent(190model='gpt-4',191system_prompt='Use tools to calculate results.',192result_type=ToolOutput([calculate_result])193)194195result = agent.run_sync('Calculate the average of 10, 20, 30, 40')196print(result.data) # 25.0197```198199### Text Output with Conversion200201```python202from pydantic_ai import Agent, TextOutput203import json204205def parse_json_response(text: str) -> dict:206"""Parse JSON from model response."""207# Extract JSON from text if needed208start = text.find('{')209end = text.rfind('}') + 1210json_str = text[start:end]211return json.loads(json_str)212213# Agent with text output conversion214agent = Agent(215model='gpt-4',216system_prompt='Return responses as JSON.',217result_type=TextOutput(parse_json_response)218)219220result = agent.run_sync('Create a person object with name and age')221print(result.data) # {'name': 'John Doe', 'age': 30}222```223224### Structured Dictionary Output225226```python227from pydantic_ai import Agent, StructuredDict228229# Agent with flexible dictionary output230agent = Agent(231model='gpt-4',232system_prompt='Return structured data as a dictionary.',233result_type=StructuredDict()234)235236result = agent.run_sync('Create a product with name, price, and category')237print(result.data) # {'name': 'Laptop', 'price': 999.99, 'category': 'Electronics'}238```239240### Native vs Prompted Output241242```python243from pydantic_ai import Agent, NativeOutput, PromptedOutput244from pydantic import BaseModel245246class TaskInfo(BaseModel):247title: str248priority: int249completed: bool250251# Native structured output (uses model's built-in structured output)252native_agent = Agent(253model='gpt-4',254system_prompt='Create task information.',255result_type=NativeOutput[TaskInfo]256)257258# Prompted structured output (prompts model to return structured data)259prompted_agent = Agent(260model='gpt-4',261system_prompt='Create task information.',262result_type=PromptedOutput[TaskInfo]263)264265# Both work similarly but use different underlying mechanisms266result1 = native_agent.run_sync('Create a high priority task for code review')267result2 = prompted_agent.run_sync('Create a high priority task for code review')268269print(result1.data.title) # "Code Review"270print(result1.data.priority) # 3271print(result1.data.completed) # False272```273274### Deferred Tool Execution275276```python277from pydantic_ai import Agent, ToolOutput, tool278279@tool280def expensive_calculation(data: list[int]) -> int:281"""Perform expensive calculation."""282# Simulate expensive operation283return sum(x ** 2 for x in data)284285# Agent with deferred tool execution286agent = Agent(287model='gpt-4',288system_prompt='Plan calculations but defer execution.',289result_type=ToolOutput([expensive_calculation], defer=True)290)291292result = agent.run_sync('Plan calculation for numbers 1 through 100')293294# result.data is now DeferredToolCalls295if isinstance(result.data, DeferredToolCalls):296# Execute when ready297actual_results = result.data.execute_all()298print(actual_results[0]) # Result of expensive calculation299```300301### Complex Nested Output302303```python304from pydantic_ai import Agent305from pydantic import BaseModel306from typing import List307308class Address(BaseModel):309street: str310city: str311country: str312postal_code: str313314class Person(BaseModel):315name: str316age: int317email: str318addresses: List[Address]319320class Company(BaseModel):321name: str322employees: List[Person]323headquarters: Address324325# Agent with complex nested output326agent = Agent(327model='gpt-4',328system_prompt='Extract company information.',329result_type=Company330)331332result = agent.run_sync('''333Create a company called TechCorp with headquarters in San Francisco.334Include 2 employees: John (30, john@techcorp.com) and Jane (28, jane@techcorp.com).335''')336337print(result.data.name) # "TechCorp"338print(len(result.data.employees)) # 2339print(result.data.employees[0].name) # "John"340print(result.data.headquarters.city) # "San Francisco"341```342343### Custom Validation344345```python346from pydantic_ai import Agent347from pydantic import BaseModel, validator348349class ValidatedOutput(BaseModel):350score: float351grade: str352353@validator('score')354def score_must_be_valid(cls, v):355if not 0 <= v <= 100:356raise ValueError('Score must be between 0 and 100')357return v358359@validator('grade')360def grade_must_match_score(cls, v, values):361score = values.get('score', 0)362expected_grades = {363(90, 100): 'A',364(80, 89): 'B',365(70, 79): 'C',366(60, 69): 'D',367(0, 59): 'F'368}369370for (min_score, max_score), expected_grade in expected_grades.items():371if min_score <= score <= max_score:372if v != expected_grade:373raise ValueError(f'Grade {v} does not match score {score}')374break375return v376377# Agent with custom validation378agent = Agent(379model='gpt-4',380system_prompt='Grade student performance.',381result_type=ValidatedOutput382)383384result = agent.run_sync('Student scored 85 points on the exam')385print(result.data.score) # 85.0386print(result.data.grade) # "B"387```