系列目标:30 天从 LangChain 入门到企业级部署
今日任务:理解结构化输出的重要性 → 掌握PydanticOutputParser→ 构建可靠、可解析的 AI 接口!
🎯 一、为什么需要结构化输出?
你可能遇到过这些场景:
- 让 AI 返回用户信息,结果它回了一段话:“张三,男,28岁……”
- 要求返回 JSON,它却多加了注释、用了单引号、字段名拼错
- 后端程序
json.loads()直接报错 ❌
问题根源:大模型是“语言艺术家”,不是“程序员”——它不保证格式正确!
而 PydanticOutputParser 就是 LangChain 提供的“格式守门员” :
- 自动生成格式指令(告诉 AI 要返回什么)
- 自动解析并校验输出
- 若格式错误,可自动重试或抛出异常
✅ 今天,我们就让 AI 成为“靠谱的数据接口”!
🧱 二、核心工具:Pydantic + OutputParser
什么是 Pydantic?
- Python 最流行的数据验证库
- 用类定义数据结构,自动校验类型、必填字段等
LangChain 如何集成?
PydanticOutputParser基于 Pydantic 模型,自动生成 prompt 指令 + 解析逻辑
🛠️ 三、动手实践:让 AI 返回标准用户信息
步骤 1:定义数据结构(Pydantic Model)
# day6_structured_output.py
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
from langchain_core.output_parsers import PydanticOutputParser
# 1. 定义期望的输出结构
class UserInfo(BaseModel):
name: str = Field(description="用户姓名")
age: int = Field(description="用户年龄", ge=0, le=150)
city: str = Field(description="居住城市")
💡
Field可添加描述(用于 prompt)和校验规则(如ge=0表示 ≥0)
步骤 2:创建 OutputParser
# 2. 创建解析器
parser = PydanticOutputParser(pydantic_object=UserInfo)
步骤 3:构建带格式指令的 Prompt
# 3. 构建 Prompt(关键:插入 parser.get_format_instructions())
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个用户信息提取助手。"),
("human", "请从以下描述中提取用户信息:\n{input}\n\n{format_instructions}")
]).partial(format_instructions=parser.get_format_instructions())
🔑
parser.get_format_instructions()会自动生成类似这样的指令:请按以下 JSON 格式回答,不要包含其他内容: { "name": "string", "age": "integer (0-150)", "city": "string" }
步骤 4:组装 Chain 并调用
# 4. 初始化模型
llm = ChatOllama(model="qwen:7b", temperature=0)
# 5. 构建完整 Chain:prompt → llm → parser
chain = prompt | llm | parser
# 6. 调用(输入自然语言描述)
try:
result = chain.invoke({
"input": "我叫李华,今年32岁,住在杭州。"
})
print("✅ 解析成功!")
print(f"姓名:{result.name}")
print(f"年龄:{result.age}")
print(f"城市:{result.city}")
print(f"类型:{type(result)}") # <class 'UserInfo'>
except Exception as e:
print("❌ 解析失败:", e)
▶️ 成功输出示例:
✅ 解析成功!
姓名:李华
年龄:32
城市:杭州
类型:<class '__main__.UserInfo'>
✅ 不仅格式正确,还自动转成了 Python 对象!可直接用于业务逻辑。
🔄 四、自动重试机制(可选增强)
如果模型偶尔输出格式错误,我们可以让 LangChain 自动重试:
from langchain_core.runnables import RunnableLambda
def retry_parse(attempts=3):
def _run(input_str):
for _ in range(attempts):
try:
return parser.parse(input_str)
except:
continue
raise ValueError("多次解析失败")
return RunnableLambda(_run)
# Chain 改为:
chain = prompt | llm | retry_parse()
💡 更高级方案:使用
RetryOutputParser(LangChain 内置),后续进阶篇会讲。
🌐 五、兼容 OpenAI?依然无缝切换!
# from langchain_openai import ChatOpenAI
# llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
from langchain_ollama import ChatOllama
llm = ChatOllama(model="qwen:7b", temperature=0)
✅ 同一套结构化输出逻辑,支持所有模型!
⚠️ 六、注意事项 & 最佳实践
| 问题 | 建议 |
|---|---|
| 中文模型忽略格式指令 | 使用 Qwen、GLM 等中文优化模型;在 system prompt 中强调“严格按格式” |
| 字段缺失或类型错误 | 在 Pydantic 模型中标记 required=True(默认就是) |
| 输出包含 Markdown 或 ```json | 在 prompt 中明确禁止:“不要使用代码块,只返回纯 JSON” |
| 性能要求高 | 设 temperature=0 减少随机性 |
| 需要嵌套结构? | Pydantic 支持嵌套模型(如 Address 类),放心用! |
🔒 生产建议:所有对外 AI 接口都应使用 OutputParser,避免脏数据进入系统!
📦 七、配套代码结构
langchain-30-days/
└── day6/
└── structured_output.py # 结构化输出 + 自动校验
📝 八、今日小结
- ✅ 理解了结构化输出的必要性
- ✅ 学会了用 Pydantic 定义数据模型
- ✅ 掌握了
PydanticOutputParser自动生成指令 + 解析 - ✅ 实现了从自然语言到可靠 Python 对象的转换
- ✅ 知道了如何处理解析失败(重试/异常)