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-5google-gla:gemini-2.0-flash,看看效果有什么不同
  2. 加字段:在 CityInfo 里加个 population: int 字段,让 AI 顺便返回人口
  3. 写工具:写一个查天气的工具(可以先返回假数据),让 AI 回答"北京今天天气怎么样"

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

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