2.4 Pydantic:数据验证的利器
为什么选择 Pydantic?
TypedDict 提供类型提示,但不做运行时验证。Pydantic 提供:
- ✅ 运行时数据验证
- ✅ 自动类型转换
- ✅ 详细的错误信息
- ✅ JSON 序列化/反序列化
LangChain 和 LangGraph 大量使用 Pydantic!
🎯 小白理解指南:TypedDict vs Pydantic 有什么区别?
想象你在开一家餐厅:
TypedDict 就像菜单上写着"价格是数字":
- 顾客看到了知道应该填数字
- 但如果顾客非要写"五十块",系统不会阻止
- 只是一个"提示",不强制执行
Pydantic 就像收银系统:
- 必须是数字才能结账
- 写"五十块"会报错:"请输入数字!"
- 写"50.0"会自动转成 50
- 真正的"验证",确保数据正确
为什么 LangChain/LangGraph 用 Pydantic? 因为 AI 工具需要接收各种用户输入,必须确保数据格式正确才能正常工作。比如:温度必须在 0-2 之间,API Key 不能为空……
基础用法
🎯 小白理解指南:Pydantic 代码怎么读?
pythonclass AgentConfig(BaseModel): temperature: float = Field(default=0.7, ge=0, le=2)这行代码的意思是:
temperature:字段名叫"温度"float:类型是小数default=0.7:如果不填,默认是 0.7ge=0:必须大于等于(greater or equal)0le=2:必须小于等于(less or equal)2所以
temperature必须是 0 到 2 之间的小数,否则报错!
python
from pydantic import BaseModel, Field, validator
from typing import Optional
class AgentConfig(BaseModel):
"""Agent 配置模型"""
model: str = Field(description="模型名称")
temperature: float = Field(default=0.7, ge=0, le=2)
max_tokens: int = Field(default=2000, gt=0)
api_key: Optional[str] = None
@validator("model")
def validate_model(cls, v):
"""验证模型名称"""
allowed = ["gpt-3.5-turbo", "gpt-4", "claude-3-opus"]
if v not in allowed:
raise ValueError(f"模型必须是 {allowed} 之一")
return v
# 创建实例(自动验证)
config = AgentConfig(
model="gpt-4",
temperature=0.5,
max_tokens=3000
)
print(config.model_dump()) # 转为字典
print(config.model_dump_json()) # 转为 JSON字段验证
🎯 小白理解指南:@validator 和 @field_validator 是什么?
这些是自定义验证器——当内置的验证规则不够用时,你可以写自己的验证逻辑。
比如:
Field(ge=0)只能检查"大于等于0"- 但"内容不能是纯空格"这种规则,需要自己写
@field_validator("content")的意思是:"当设置 content 字段时,先执行下面这个函数检查一下"。
python
from pydantic import BaseModel, Field, field_validator
class Message(BaseModel):
role: str = Field(pattern="^(user|assistant|system)$")
content: str = Field(min_length=1, max_length=10000)
timestamp: float = Field(gt=0)
@field_validator("content")
@classmethod
def content_not_empty(cls, v: str) -> str:
if not v.strip():
raise ValueError("内容不能为空白")
return v.strip()
# 使用
msg = Message(
role="user",
content=" Hello ",
timestamp=1234567890.0
)
print(msg.content) # "Hello" (已去除空格)在 LangChain 中的应用
🎯 小白理解指南:为什么 LangChain Tool 需要 Pydantic?
AI Agent 在调用工具时,需要知道:
- 工具需要什么参数?(参数名、类型)
- 参数有什么限制?(最小值、最大值、格式)
Pydantic 的
args_schema帮 AI 理解"这个工具怎么用",同时确保 AI 传入的参数是合法的。比如搜索工具:AI 必须传入一个至少 2 个字符的查询词,最多返回 20 条结果。
Tool 参数验证
python
from langchain.tools import tool
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
"""搜索工具输入"""
query: str = Field(description="搜索查询", min_length=2)
max_results: int = Field(default=5, ge=1, le=20)
language: str = Field(default="zh", pattern="^(zh|en)$")
@tool(args_schema=SearchInput)
def search_web(query: str, max_results: int = 5, language: str = "zh") -> str:
"""搜索网络"""
return f"搜索 '{query}': {max_results} 个结果 ({language})"
# Pydantic 自动验证参数!实战:完整的 Agent 配置系统
python
from pydantic import BaseModel, Field, field_validator
from typing import Optional, Literal
import os
class LLMConfig(BaseModel):
"""LLM 配置"""
provider: Literal["openai", "anthropic"] = "openai"
model: str = Field(description="模型名称")
temperature: float = Field(default=0.7, ge=0, le=2)
max_tokens: int = Field(default=2000, gt=0, le=100000)
api_key: Optional[str] = None
@field_validator("api_key")
@classmethod
def load_api_key(cls, v: Optional[str], info) -> str:
"""从环境变量加载 API 密钥"""
if v:
return v
provider = info.data.get("provider", "openai")
env_var = f"{provider.upper()}_API_KEY"
key = os.getenv(env_var)
if not key:
raise ValueError(f"未找到 {env_var} 环境变量")
return key
class AgentConfig(BaseModel):
"""完整的 Agent 配置"""
name: str = Field(description="Agent 名称")
llm: LLMConfig
system_prompt: str = Field(default="You are a helpful assistant.")
tools: list[str] = Field(default_factory=list)
max_iterations: int = Field(default=10, gt=0, le=50)
class Config:
# 允许从环境变量读取
env_prefix = "AGENT_"
# 使用
config = AgentConfig(
name="ResearchBot",
llm=LLMConfig(
provider="openai",
model="gpt-4",
temperature=0.5
),
tools=["search", "calculator"]
)
print(config.model_dump_json(indent=2))