🌟 LangChain 30 天保姆级教程 · Day 13|OutputParser 进阶!让 AI 输出自动转为结构化对象,并支持自动重试!

系列目标 :30 天从 LangChain 入门到企业级部署
今日任务 :掌握 PydanticOutputParser + RetryOutputParser → 构建高可靠结构化输出链 → 让 Agent 返回标准 JSON 对象!


🎯 一、为什么需要"带重试的结构化输出"?

在 Day 6 中,我们用 PydanticOutputParser 让 AI 输出合法 JSON。

但现实是:即使加了格式指令,大模型偶尔仍会"跑偏"

  • 多了 Markdown 代码块(```json)
  • 字段名拼错("user_name" 写成 "username")
  • 返回一段解释文字而非纯 JSON

如果直接解析,程序会崩溃 ❌。

解决方案

RetryOutputParser + PydanticOutputParser = 自动重试 + 自动修复

LangChain 会在解析失败时,自动把错误信息反馈给 LLM,让它重新生成,直到成功或达到最大重试次数。


🧱 二、核心组件介绍

表格

组件 作用
PydanticOutputParser 定义期望结构 + 生成格式指令 + 解析输出
RetryOutputParser 包装 parser,支持自动重试
RunnableParallel / LCEL 将 parser 集成到 Chain 或 Agent 中

💡 今天我们将构建一个"用户意图识别器",要求 AI 从自然语言中提取:

python 复制代码
class UserIntent(BaseModel):
    action: Literal["order", "refund", "inquiry"]
    product: str
    confidence: float  # 0.0 ~ 1.0

🛠️ 三、动手实践:构建带自动重试的结构化输出链

步骤 1:定义 Pydantic 模型

python 复制代码
# day13_retry_output_parser.py
from langchain_ollama import ChatOllama
from langchain_core.pydantic_v1 import BaseModel, Field, Literal
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import LLMChain

class UserIntent(BaseModel):
    action: Literal["order", "refund", "inquiry"] = Field(
        description="用户意图:下单(order)、退货(refund)、咨询(inquiry)"
    )
    product: str = Field(description="涉及的产品名称")
    confidence: float = Field(ge=0.0, le=1.0, description="置信度,0.0~1.0")

步骤 2:创建带重试的 OutputParser

python

编辑

ini 复制代码
# 创建基础 parser
base_parser = PydanticOutputParser(pydantic_object=UserIntent)

# 创建支持重试的 parser
retry_parser = base_parser.with_retry(retries=3)  # 自动重试 3 次

🔑 with_retry() 是 LangChain 0.1+ 提供的便捷方法,内部使用 RetryOutputParser


步骤 3:构建 Prompt(关键:插入格式指令)

swift 复制代码
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个用户意图分析器。"),
    ("human", "请分析以下用户语句的意图:\n{input}\n\n{format_instructions}")
]).partial(format_instructions=retry_parser.get_format_instructions())

💡 retry_parser.get_format_instructions() 会返回清晰的 JSON 格式示例。


步骤 4:组装 Chain 并测试

python 复制代码
llm = ChatOllama(model="qwen:7b", temperature=0)

# 使用 LCEL 构建链:prompt → llm → retry_parser
chain = prompt | llm | retry_parser

# 测试用例(故意模糊)
test_inputs = [
    "我想买一副无线耳机",
    "这个手机我不想要了,怎么退?",
    "你们客服电话多少?"  # 不涉及产品,考验鲁棒性
]

for inp in test_inputs:
    print(f"\n👤 用户:{inp}")
    try:
        result = chain.invoke({"input": inp})
        print(f"✅ 成功!action={result.action}, product={result.product}, confidence={result.confidence:.2f}")
    except Exception as e:
        print(f"❌ 最终失败:{e}")

▶️ 成功输出示例:

ini 复制代码
👤 用户:这个手机我不想要了,怎么退?
✅ 成功!action=refund, product=手机, confidence=0.95

✅ 即使第一次输出格式错误,LangChain 也会自动重试,直到成功!


🤖 四、进阶:让 Agent 也返回结构化对象

Agent 默认返回自由文本,但我们希望它最终输出一个标准对象

python 复制代码
from langchain.agents import Tool, AgentExecutor, create_react_agent

# 假设有一个工具
@tool
def dummy_tool(query: str) -> str:
    return "已完成操作"

tools = [dummy_tool]
llm = ChatOllama(model="qwen:7b", temperature=0)

# 创建普通 Agent
agent = create_react_agent(llm, tools, create_react_agent.get_default_prompt())
executor = AgentExecutor(agent=agent, tools=tools, verbose=False)

# 现在,我们想让整个 Agent 的最终输出是结构化的!
# 方案:在 executor 后接一个 parser

final_chain = executor | retry_parser

# 调用(注意:Agent 输入是 {"input": "..."},输出是 {"output": "..."})
try:
    result = final_chain.invoke({"input": "帮我查一下订单状态"})
    print("Agent 结构化结果:", result)
except Exception as e:
    print("解析失败:", e)

⚠️ 注意:Agent 的原始输出是字符串,需确保其内容符合 parser 要求。

更佳实践:在 Agent 的 system prompt 中强调"最终回答必须是合法 JSON"。


⚠️ 五、注意事项 & 最佳实践

表格

问题 建议
重试后仍失败 检查 prompt 是否足够清晰;降低 temperature
中文模型忽略格式 在 system prompt 中强调:"只返回 JSON,不要任何其他文字"
字段缺失 在 Pydantic 模型中标记为必填(默认就是)
性能敏感场景 设置 retries=10,避免延迟过高
需要兼容旧系统 可将 parser 输出转为 dict:result.dict()

💡 生产建议

所有对外 AI 接口都应使用带重试的结构化输出,避免脏数据进入下游系统!


📦 六、配套代码结构

bash 复制代码
langchain-30-days/
└── day13/
    ├── structured_output_with_retry.py   # 带重试的结构化输出链
    └── agent_with_structured_output.py   # Agent 返回结构化对象(进阶)

📝 七、今日小结

  • ✅ 理解了结构化输出在生产环境中的必要性
  • ✅ 学会了用 with_retry() 实现自动重试
  • ✅ 构建了高可靠的用户意图识别器
  • ✅ 掌握了将结构化输出集成到 Agent 的方法
  • ✅ 知道了如何平衡可靠性与性能

🎯 明日预告:Day 14 ------ Callback 机制!监听 Chain/Agent 的每一步,实现日志、监控、审计!

相关推荐
2401_8844541514 小时前
如何管理只读表空间的备份_跳过只读表空间的RMAN优化策略
jvm·数据库·python
果汁华14 小时前
LangChain 深度解析:从 Prompt 调用到 Agent 应用编排框架
人工智能·langchain·prompt
woxihuan12345614 小时前
CSS移动端实现响应式导航菜单_利用媒体查询切换显示隐藏状态
jvm·数据库·python
CCPC不拿奖不改名14 小时前
PostgreSQL数据库部署linux服务器流程
linux·服务器·数据库·windows·python·docker·postgresql
曲幽14 小时前
你的Agent API还在裸奔?从认证到沙箱,我用FastAPI搭了几道防线
python·fastapi·web·security·jwt·oauth2·limit·sandbox·ai agent
donecoding14 小时前
用了多年 nvm,我终于找到 Python 的版本管理「答案」:uv
python·node.js·前端工程化
彳亍10114 小时前
mysql如何通过mysqldump备份视图与触发器_使用相关参数
jvm·数据库·python
深度学习lover14 小时前
<数据集>yolo 缆绳识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·缆绳识别
骑士雄师14 小时前
学生管理系统python版本比对
开发语言·python
William.csj14 小时前
Linux——服务器后台运行程序指南(包含 Python 与 .sh 脚本实战)
linux·服务器·python