主题
📋 9.4 结构化输出与容错解析
“在企业级应用中,大模型必须从‘天马行空的文科生’,驯化为‘严谨填表的理科生’。”
无论是将非结构化新闻提炼为财报数据库记录,还是向下游业务系统分发 JSON 消息,结构化输出都是 AI 工程落地的核心命门。
💡 为什么需要结构化输出?(生活比喻篇)
1. 自然语言与业务代码的鸿沟
大模型天然习惯用自然语言说话。如果你让它“输出一个 JSON”,它经常会出现以下问题:
- 在 JSON 外面包裹 ```json 开头和多余的寒暄客套话;
- 字段名写错(如把
user_id拼成userId或id); - 缺少逗号或双引号未闭合,导致 Python
json.loads()直接崩溃报错(Crash)。
2. 生活比喻:海关标准报关单与智能质检机器人
- 自由发散输出:就像旅客口头向海关申报行李:“我带了两双鞋、大概三斤牛肉干,还有送朋友的几瓶酒” —— 计算机系统根本无法自动录入;
- 结构化约束(Pydantic):就像海关递给旅客的标准化中英文报关单,上面每一个空格都有严格的类型限制(如商品名称为字符串、单价为浮点数、数量必须大于 0);
with_structured_output():就像在旅客填表时安排了一位智能海关质检机器人,不仅强制按表格格式填写,还会通过底层 Function Calling 协议确保 100% 符合数据规范!
🏛️ LangChain 1.4 的结构化输出机制对比
在 LangChain 1.4 中,主要推荐使用现代原生 .with_structured_output(),兼顾经典 JsonOutputParser:
| 方案模式 | 底层技术原理 | 优点 | 缺点 / 适用场景 |
|---|---|---|---|
llm.with_structured_output(Model) 🌟 (强烈推荐) | 模型原生 Tool/Function Calling 或 JSON Schema 强制约束 | 格式准确率最高(接近 100%),支持 Pydantic 字段类型与数值范围校验,免除正则清洗。 | 需要大模型本身支持 Function Calling 能力(如 GPT 系列、DeepSeek-V3 系列、Claude 系列)。 |
JsonOutputParser | 在 Prompt 中注入 JSON 格式规范与字段说明,外置解析器容错提取 | 兼容不支持 Function Calling 的轻量或开源端侧小模型。 | 若模型产生幻觉或语法错误,偶尔需要结合 OutputFixingParser 自动重试修复。 |
🆕 1.4 进阶:
create_agent也支持结构化输出。9.9 的create_agent可通过response_format=参数指定 Pydantic 模型,让整个 Agent 的最终答复(而非单次 LLM 调用)都强制符合 Schema,适合“对话结束后自动生成报表/单据”的业务场景。
💻 核心实操:Pydantic 实体建模与信息抽取
1. 定义强类型金融研报 Pydantic Schema
python
# code/s04_structured_output.py
from typing import List
from pydantic import BaseModel, Field
class KeyMetric(BaseModel):
name: str = Field(description="指标名称,如营收、净利润、MAU")
value: str = Field(description="指标数值,如 158.6 亿元、+28.5%")
evaluation: str = Field(description="指标评价:超预期 / 符合预期 / 不及预期")
class FinancialReportAnalysis(BaseModel):
company_name: str = Field(description="企业全称或股票标的")
report_period: str = Field(description="财报所属季度或年份,如 2025Q3")
core_summary: str = Field(description="100 字以内的核心经营亮点与痛点摘要")
sentiment_score: int = Field(description="研报情绪评分,0 到 100 分", ge=0, le=100)
key_metrics: List[KeyMetric] = Field(description="核心财务业务指标清单")
risk_factors: List[str] = Field(description="面临的主要风险清单")
rating: str = Field(description="综合投资评级:买入 / 增持 / 中性 / 卖出")2. 使用 with_structured_output() 一键提取非结构化新闻
python
from langchain_core.prompts import ChatPromptTemplate
from s01_model_io import get_chat_model
llm = get_chat_model()
# 绑定结构化模型
structured_llm = llm.with_structured_output(FinancialReportAnalysis)
news_text = """
【TechStar 2025年第三季度财报公布】
TechStar 智能科技今日公布最新三季度业绩:本季度实现总营业收入 158.6 亿元,同比增长 28.5%,大幅超出市场预期的 140 亿元;
其中云计算与 AI 业务营收占比达 42%,成为第一大支柱。净利润为 24.1 亿元,同比增长 12%,表现稳健符合预期。
然而,公司海外业务受到汇率波动和地缘供应链限制,海外增速放缓至 5%;同时研发投入由于大模型训练增加 45%,给短期毛利带来一定压力。
综合来看,管理层对 AI 全年商业化落地充满信心,券商多数给出'买入'评级。
"""
prompt = ChatPromptTemplate.from_messages([
("system", "你是一名资深金融研报分析师,请从给定文本中提炼标准财报结构。"),
("human", "{text}")
])
chain = prompt | structured_llm
# 运行链:返回的直接就是强类型的 FinancialReportAnalysis 实例!
result: FinancialReportAnalysis = chain.invoke({"text": news_text})
print(f"企业名称: {result.company_name}")
print(f"情绪评分: {result.sentiment_score}/100")
print(f"评级: {result.rating}")
for m in result.key_metrics:
print(f" - {m.name}: {m.value} ({m.evaluation})")📚 权威官方资料直达
- 🔗 结构化输出官方教程:How to return structured data from a model
- 🔗 Pydantic 官方数据验证规范:Pydantic V2 Documentation
- 🔗 输出解析器参考指南:LangChain Output Parsers
结构正确不代表内容正确
Pydantic 可以确认字段存在、类型匹配、数值在允许范围内,却不能证明模型给出的公司营收或产品价格真实。涉及事实的字段仍要附带来源,关键数字应由数据库、检索工具或确定性代码计算。
解析失败时不要无限要求模型“再试一次”。可以限定重试次数,向模型返回精简的验证错误,并保留原始输出用于排查。Schema 发生变化时应增加版本字段,避免旧数据被新代码误读。
🎯 本节小结与思考
- 核心收获:彻底告别手写字符串正则解析,掌握了以 Pydantic Schema 为核心的
with_structured_output强类型提取。 - 下一步探索:大模型拥有了规范输出的能力,但要让它成为能干活的 Agent,还需要给它配备执行工具(如查天气、算贷款、搜网页)。下一节我们学习 9.5 自定义工具生态与参数校验。