神龙快打
91.05M · 2026-04-10
在 Day 6 中,我们用 PydanticOutputParser 让 AI 输出合法 JSON。
但现实是:即使加了格式指令,大模型偶尔仍会“跑偏” :
如果直接解析,程序会崩溃 。
解决方案:
LangChain 会在解析失败时,自动把错误信息反馈给 LLM,让它重新生成,直到成功或达到最大重试次数。
表格
| 组件 | 作用 |
|---|---|
PydanticOutputParser | 定义期望结构 + 生成格式指令 + 解析输出 |
RetryOutputParser | 包装 parser,支持自动重试 |
RunnableParallel / LCEL | 将 parser 集成到 Chain 或 Agent 中 |
# 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")
python
编辑
# 创建基础 parser
base_parser = PydanticOutputParser(pydantic_object=UserIntent)
# 创建支持重试的 parser
retry_parser = base_parser.with_retry(retries=3) # 自动重试 3 次
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个用户意图分析器。"),
("human", "请分析以下用户语句的意图:n{input}nn{format_instructions}")
]).partial(format_instructions=retry_parser.get_format_instructions())
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}")
用户:这个手机我不想要了,怎么退?
成功!action=refund, product=手机, confidence=0.95
Agent 默认返回自由文本,但我们希望它最终输出一个标准对象。
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)
表格
| 问题 | 建议 |
|---|---|
| 重试后仍失败 | 检查 prompt 是否足够清晰;降低 temperature |
| 中文模型忽略格式 | 在 system prompt 中强调:“只返回 JSON,不要任何其他文字” |
| 字段缺失 | 在 Pydantic 模型中标记为必填(默认就是) |
| 性能敏感场景 | 设置 retries=1 或 0,避免延迟过高 |
| 需要兼容旧系统 | 可将 parser 输出转为 dict:result.dict() |
langchain-30-days/
└── day13/
├── structured_output_with_retry.py # 带重试的结构化输出链
└── agent_with_structured_output.py # Agent 返回结构化对象(进阶)
with_retry() 实现自动重试