Pydantic AI 教程 · 阶段一

入门基础

读完这篇,你就能用 Pydantic AI 写出自己的第一个 AI 代理程序。

1Pydantic AI 是个啥?

一句话解释

Pydantic AI 是一个 Python 框架,帮你用几行代码就能调用各种大语言模型(ChatGPT、Claude、Gemini 等),而且还能让 AI 返回结构化的数据,而不是一大坨文本。

打个比方

你可以把 Pydantic AI 想象成一个翻译官:

它和直接调 OpenAI API 有啥区别?

直接调 API用 Pydantic AI
要自己拼请求、解析返回框架帮你搞定
换个模型要改一堆代码换模型只改一个字符串
返回的都是纯文本,自己解析直接返回 Python 对象
出错了自己处理自动重试、自动纠错
想让 AI 调函数?自己写一堆 JSON Schema加个装饰器就行

核心概念速览

Pydantic AI 里最重要的就 4 个概念,先混个脸熟,后面会一个个讲:

🤖
Agent(代理)
你的 AI 助手,整个框架的核心入口
📝
Instructions(指令)
告诉 AI "你是谁、该干啥"
🔧
Tool(工具)
让 AI 能调用你写的 Python 函数
📦
Output(输出)
规定 AI 必须返回什么格式的数据

2安装与环境配置

前提条件

第一步:安装 Pydantic AI

# 推荐用 uv(速度快)
uv add pydantic-ai

# 或者用老朋友 pip
pip install pydantic-ai

这条命令会把 Pydantic AI 和所有主流模型的依赖一起装好。

想省空间? 如果你只用 OpenAI,可以装精简版:
uv add "pydantic-ai-slim[openai]"

第二步:配置 API Key

Pydantic AI 支持几乎所有主流模型,你至少需要配一个。最常用的三个:

OpenAI(GPT 系列)

export OPENAI_API_KEY="sk-你的密钥"

Anthropic(Claude 系列)

export ANTHROPIC_API_KEY="你的密钥"

Google(Gemini 系列)

export GEMINI_API_KEY="你的密钥"
提示: 建议把 API Key 写到 ~/.bashrc 或 ~/.zshrc 里,这样每次打开终端就自动生效了。

第三步:验证安装

新建一个 test.py,复制粘贴:

from pydantic_ai import Agent

agent = Agent('openai:gpt-4o')  # 换成你有 API Key 的模型
result = agent.run_sync('说一句你好')
print(result.output)

运行:

python test.py

如果看到 AI 跟你打招呼了,恭喜,环境搭好了!

模型名称怎么写?

格式统一是 提供商:模型名,常用的:

写法说明
openai:gpt-4oOpenAI GPT-4o
openai:gpt-4o-miniOpenAI GPT-4o Mini(便宜)
anthropic:claude-sonnet-4-5Anthropic Claude Sonnet 4.5
google-gla:gemini-2.0-flashGoogle Gemini 2.0 Flash
groq:llama-3.3-70b-versatileGroq 上的 Llama(免费额度)

使用自定义模型 URL(第三方 / 本地模型)

上面那些模型都要花钱调 API。但实际工作中,你可能会遇到这些情况:

好消息:只要服务兼容 OpenAI API 格式(大部分都兼容),Pydantic AI 就能直接用。

方法一:环境变量(最简单,推荐日常使用)

直接改 OPENAI_BASE_URL,代码一行不用动:

# 指向你的自定义服务地址
export OPENAI_BASE_URL="https://api.deepseek.com/v1"
export OPENAI_API_KEY="你的密钥"
from pydantic_ai import Agent

# 代码完全不变!框架会自动读环境变量
agent = Agent('openai:deepseek-chat')
result = agent.run_sync('你好')
print(result.output)

方法二:用 OpenAIProvider 指定 base_url(显式配置,推荐写代码时用)

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider

model = OpenAIChatModel(
    'deepseek-chat',                    # 模型名称
    provider=OpenAIProvider(
        base_url='https://api.deepseek.com/v1',  # 自定义地址
        api_key='你的密钥',
    ),
)
agent = Agent(model)
result = agent.run_sync('用 Python 写一个快速排序')
print(result.output)
为什么要用这种方式? 当你在一个项目里同时用多个不同的模型服务时,环境变量就不够用了,需要在代码里显式指定每个模型的地址。

方法三:用内置 Provider(最省事,如果有的话)

Pydantic AI 为很多第三方服务内置了专门的 Provider,用起来更方便:

from pydantic_ai import Agent

# DeepSeek —— 设好环境变量就行
# export DEEPSEEK_API_KEY="你的密钥"
agent = Agent('deepseek:deepseek-chat')

# Ollama 本地模型
# export OLLAMA_BASE_URL="http://localhost:11434/v1"
agent = Agent('ollama:llama3.2')

# Together AI
# export TOGETHER_API_KEY="你的密钥"
agent = Agent('together:meta-llama/Llama-3.3-70B-Instruct-Turbo-Free')

# OpenRouter(聚合了几百个模型)
# export OPENROUTER_API_KEY="你的密钥"
agent = Agent('openrouter:anthropic/claude-sonnet-4')

# Groq(免费额度,速度快)
# export GROQ_API_KEY="你的密钥"
agent = Agent('groq:llama-3.3-70b-versatile')

方法四:传入自定义 OpenAI 客户端(最灵活)

如果你需要精细控制(比如超时时间、重试次数、代理设置),可以自己创建 OpenAI 客户端:

from openai import AsyncOpenAI
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider

# 完全自定义的客户端
client = AsyncOpenAI(
    base_url='http://localhost:8000/v1',  # 比如本地 vLLM 服务
    api_key='not-needed',                  # 本地服务通常不需要密钥
    timeout=60.0,                          # 超时时间
    max_retries=3,                         # 重试次数
)

model = OpenAIChatModel(
    'Qwen/Qwen2.5-72B-Instruct',
    provider=OpenAIProvider(openai_client=client),
)
agent = Agent(model)

常见场景速查表

场景配置方式
本地 OllamaAgent('ollama:llama3.2') + OLLAMA_BASE_URL
DeepSeek APIAgent('deepseek:deepseek-chat') + DEEPSEEK_API_KEY
本地 vLLMOpenAIProvider(base_url='http://localhost:8000/v1')
硅基流动 / 零一万物等OpenAIProvider(base_url='https://api.xxx.com/v1', api_key='...')
Azure OpenAIAgent('azure:gpt-4o') + AZURE_OPENAI_ENDPOINT
OpenRouterAgent('openrouter:模型名') + OPENROUTER_API_KEY
Together AIAgent('together:模型名') + TOGETHER_API_KEY
LiteLLM 代理LiteLLMProvider(api_base='http://localhost:4000')
小贴士:如果你传了 base_url 但没传 api_key,框架会自动设一个占位符,这样连本地不需要认证的模型服务也能直接用,不会报错。

3Hello World:让 AI 返回结构化数据

纯文本聊天

先看最简单的用法——跟 AI 聊天:

from pydantic_ai import Agent

# 创建一个代理
agent = Agent(
    'openai:gpt-4o',
    instructions='你是一个友好的助手,用中文回答。'
)

# 同步运行
result = agent.run_sync('Python 是什么?一句话解释')
print(result.output)
# 输出类似:Python 是一种简洁易读的高级编程语言,广泛用于 Web 开发、数据分析和人工智能等领域。

这跟直接调 API 差不多,没啥特别的。接下来才是 Pydantic AI 的亮点。

结构化输出:让 AI 返回 Python 对象

想象一个场景:你给 AI 一段文本,让它提取出城市和国家信息。

如果用普通 API,AI 会返回类似 "城市是芝加哥,国家是美国" 这样的文本,你还得自己写正则去解析。

用 Pydantic AI,你只需要定义一个数据模型:

from pydantic import BaseModel
from pydantic_ai import Agent


# 第一步:定义你想要的数据结构
class CityInfo(BaseModel):
    city: str       # 城市名
    country: str    # 国家名


# 第二步:创建代理,指定输出类型
agent = Agent(
    'openai:gpt-4o',
    output_type=CityInfo  # 告诉 AI:你必须返回这个格式
)

# 第三步:运行
result = agent.run_sync('美国的风城是哪里?')

# result.output 直接就是一个 CityInfo 对象!
print(result.output)
# 输出:city='Chicago' country='United States'

# 可以直接用点号访问属性
print(f'城市:{result.output.city}')
print(f'国家:{result.output.country}')

发生了什么?

❶ 你定义了 CityInfo 模型,告诉框架"我要城市和国家"
❷ Pydantic AI 自动把模型转成 JSON Schema,发给 AI
❸ AI 按照 Schema 返回结构化数据
❹ Pydantic AI 自动校验数据,格式不对就让 AI 重试
❺ 你拿到的直接是 Python 对象,不用自己解析

更复杂一点的例子

from pydantic import BaseModel, Field
from pydantic_ai import Agent


class BookInfo(BaseModel):
    title: str = Field(description='书名')
    author: str = Field(description='作者')
    year: int = Field(description='出版年份')
    summary: str = Field(description='一句话简介')


agent = Agent(
    'openai:gpt-4o',
    output_type=BookInfo,
    instructions='你是一个图书信息助手。'
)

result = agent.run_sync('介绍一下《三体》')
book = result.output

print(f'书名:{book.title}')
print(f'作者:{book.author}')
print(f'年份:{book.year}')
print(f'简介:{book.summary}')
Field 里的 description 有什么用? 它会被发给 AI,告诉 AI 这个字段应该填什么内容。相当于给 AI 的提示。

拿到的是真正的 Python 对象

这意味着你可以:

# 用在 if 判断里
if book.year > 2000:
    print('这是一本21世纪的书')

# 放进列表
books = []
books.append(book)

# 转成字典
print(book.model_dump())
# {'title': '三体', 'author': '刘慈欣', 'year': 2008, 'summary': '...'}

# 转成 JSON
print(book.model_dump_json())

4第一个工具调用:让 AI 调用你的函数

为什么需要工具?

AI 模型有两个天生的短板:

  1. 不知道实时信息——它不知道今天天气怎样、你的数据库里有什么
  2. 会编造信息——问它一个不知道的问题,它可能会瞎说

工具(Tool) 就是解决这个问题的:你写一个 Python 函数,AI 在需要的时候会自动去调用它,拿到真实数据后再回答你。

最简单的工具

from pydantic_ai import Agent

agent = Agent(
    'openai:gpt-4o',
    instructions='你是一个数学助手。需要计算时请使用工具。'
)


@agent.tool_plain
def add(a: float, b: float) -> float:
    """两个数相加。

    Args:
        a: 第一个数
        b: 第二个数
    """
    return a + b


@agent.tool_plain
def multiply(a: float, b: float) -> float:
    """两个数相乘。

    Args:
        a: 第一个数
        b: 第二个数
    """
    return a * b


result = agent.run_sync('请计算 (3 + 5) * 2')
print(result.output)
# 输出:(3 + 5) * 2 = 16

发生了什么?

你 "请计算 (3 + 5) * 2"
↓
AI 思考 我需要先算 3+5,调用 add 工具
↓
框架执行 add(3, 5) → 返回 8
↓
AI 思考 再算 8*2,调用 multiply 工具
↓
框架执行 multiply(8, 2) → 返回 16
↓
AI "(3 + 5) * 2 = 16"

AI 可以自动决定调用哪个工具、调用几次、传什么参数。你只负责把函数写好就行。

两种注册工具的方式

1. @agent.tool_plain —— 简单工具,不需要上下文

@agent.tool_plain
def get_current_time() -> str:
    """获取当前时间。"""
    from datetime import datetime
    return datetime.now().strftime('%Y-%m-%d %H:%M:%S')

2. @agent.tool —— 需要访问上下文的工具

有时候工具需要访问外部传入的数据(比如数据库连接、用户 ID 等),这就要用 RunContext:

from dataclasses import dataclass
from pydantic_ai import Agent, RunContext


# 定义依赖:你想传给工具的数据
@dataclass
class GameDeps:
    winning_number: int   # 中奖号码


agent = Agent(
    'openai:gpt-4o',
    deps_type=GameDeps,    # 声明依赖类型
    output_type=bool,       # 输出是 True/False
    instructions='用 check_number 工具检查用户猜的数字是否正确。'
)


@agent.tool
def check_number(ctx: RunContext[GameDeps], guess: int) -> str:
    """检查猜测的数字是否是中奖号码。

    Args:
        guess: 用户猜测的数字
    """
    if guess == ctx.deps.winning_number:
        return '恭喜,猜对了!'
    else:
        return f'没猜对,不是 {guess}'


# 运行时传入依赖
deps = GameDeps(winning_number=42)
result = agent.run_sync('我猜是 42', deps=deps)
print(result.output)  # True

result = agent.run_sync('我猜是 7', deps=deps)
print(result.output)  # False
关键点:
  • ctx.deps 就是你传进去的 GameDeps 对象
  • AI 看不到 ctx 参数,只看到 guess 参数
  • 这样你的秘密数据(中奖号码)不会暴露给 AI

工具的函数签名就是 AI 的说明书

@agent.tool_plain
def search_product(name: str, max_price: float = 100.0) -> str:
    """在商品库中搜索商品。

    Args:
        name: 商品名称关键词
        max_price: 最高价格,默认 100
    """
    # 你的搜索逻辑
    return f'找到了 {name},价格在 {max_price} 以内'

框架会自动提取:

写好文档字符串非常重要,它直接影响 AI 能不能正确使用你的工具。把函数签名和 docstring 当作给 AI 看的说明书来写。

🎉 阶段一总结

恭喜!你已经掌握了 Pydantic AI 的三大核心用法:

💬
纯文本对话
agent.run_sync('...')
📦
结构化输出
output_type=你的模型
🔧
工具调用
@agent.tool

你现在能做的事:

✍️ 练习建议

  1. 换模型:把 openai:gpt-4o 换成 anthropic:claude-sonnet-4-5 或 google-gla:gemini-2.0-flash,看看效果有什么不同
  2. 加字段:在 CityInfo 里加个 population: int 字段,让 AI 顺便返回人口
  3. 写工具:写一个查天气的工具(可以先返回假数据),让 AI 回答"北京今天天气怎么样"

🚀 下一步:阶段二 · 核心概念

深入讲解 Agent、Tools、Output、Dependencies 四大核心概念,
学会它们你就能应对大部分实际场景了。