结构化输出与Pydantic:让大模型结果可落库可调用
结构化输出与 Pydantic:把大模型结果变成可靠的数据接口
大模型天然输出文本,业务系统天然需要数据。这两者之间存在一条关键鸿沟:模型说得再流畅,如果程序无法解析、校验、存储和执行,它就只能停留在聊天层面。结构化输出的目标,是把模型生成内容转成可被系统消费的数据。
在信息抽取、意图识别、工具调用、RAG 推荐、多 Agent 路由等场景中,结构化输出不是锦上添花,而是应用能否工程化的基础能力。
1. 为什么自然语言输出不够
假设模型回答:
用户应该是想查询北京明天的天气。
这句话对人很好理解,但程序接下来要怎么做?它需要的是:
{
"intent": "weather",
"city": "北京",
"date": "tomorrow"
}
再比如模型说:
这位候选人大约有五年经验,比较适合。
如果系统要按经验过滤、排序、入库或展示,就需要字段:
{
"work_experience": 5,
"matched": true,
"reason": "具备相关经验"
}
结构化输出的意义,就是让模型从“表达判断”变成“提交数据”。
2. JSON 是事实标准,但不是安全保证
JSON 是大模型应用里最常见的结构化格式,因为它轻量、通用、易解析。Prompt 往往会要求:
请严格输出 JSON,不要添加额外解释。
但真实输出经常出现偏差:
- 外层包了 Markdown 代码块。
- JSON 前后加了解释。
- 字段缺失。
- 字段类型错误。
- 枚举值写成近义词。
- 使用中文引号或尾随逗号。
- 把整个 JSON Schema 当成结果输出。
因此,JSON 只是目标格式,不是可靠性保证。真正可靠的结构化输出至少需要三层:
Prompt 约束 -> 输出清洗 -> 类型校验
3. Pydantic 的核心作用
Pydantic 的价值不只是“定义一个类”,而是把模型输出纳入类型系统。它能帮助应用确认:字段是否存在、类型是否正确、默认值是否合理、异常能否捕获。
例如动作模型可以这样定义:
from pydantic import BaseModel, Field
from typing import Any
class Action(BaseModel):
tool_name: str = Field(description="要调用的工具名称")
args: dict[str, Any] = Field(default_factory=dict, description="工具参数")
模型输出通过 JSON 解析成字典后,再交给 Pydantic:
action = Action(**data)
如果模型把 args 输出成 null、列表或字符串,程序就能在校验阶段发现问题,而不是等到工具执行时报错。
4. 解析容错:不要假设模型总是完美
应用层应预设模型会犯格式错误。常见容错策略包括:
- 去掉 Markdown 代码块标记。
- 提取最后一个 JSON 片段。
- 对常见字段类型做兼容转换。
- 对空值设置默认值。
- 对无法解析的输出进入 fallback。
- 必要时使用二次修复模型重新格式化。
例如,工具参数本来应该是字典,但小模型可能输出:
{
"tool_name": "Search",
"args": ["北京天气"]
}
如果业务约定单参数工具使用 query 字段,可以在校验前将其规范化:
{
"tool_name": "Search",
"args": {
"query": "北京天气"
}
}
这种兼容不是纵容模型乱输出,而是在真实系统中提高韧性。
5. Schema 设计要面向演进
结构化输出一旦进入业务流程,就会形成隐式 API。字段名、字段类型和枚举值后续都不应轻易改动。
设计 Schema 时建议:
- 字段名使用英文或统一命名风格。
- 枚举值固定,不要让模型自由创造。
- 数值字段明确单位和类型。
- 可选字段允许
null,但语义要清楚。 - 对无法判断的字段使用统一占位。
- 复杂对象拆成小结构,避免一次输出过深 JSON。
例如参数抽取可以定义:
{
"count": 3,
"gender": null,
"age_min": null,
"age_max": null,
"experience_min": 5,
"experience_max": null
}
这样下游可以直接构造过滤条件,不需要再从自然语言里二次猜测。
6. 结构化输出与业务决策要分离
模型可以帮助提取字段和生成判断,但最终业务动作应该由程序控制。
例如模型可以输出:
{
"status": "input_required",
"message": "请提供具体日期"
}
程序再根据 status 决定是追问用户、调用工具还是结束任务。不要让模型直接决定高风险动作是否执行,尤其是涉及写数据库、下单、删除、发送消息等操作时。
比较稳健的设计是:
模型生成候选决策 -> 程序校验 -> 权限检查 -> 执行动作
模型负责理解,程序负责治理。
7. 结构化输出在 Agent 中的特殊意义
Agent 系统里,结构化输出通常对应“动作”。如果动作格式不稳定,Agent 就无法运行。
常见动作结构包括:
{
"tool_name": "KnowledgeSearch",
"args": {
"query": "用户问题"
}
}
执行器会根据 tool_name 查找工具,根据 args 调用工具,再把 Observation 放回上下文。这里最怕的是模型输出了不存在的工具、参数缺失或把解释混入 JSON。
因此 Agent 场景下应额外加入:
- 工具白名单校验。
- 参数模型校验。
- 最大执行轮数。
- 工具失败反馈。
- 未知动作 fallback。
结构化输出不是为了美观,而是为了让 Agent 循环不断裂。
8. 评估结构化输出质量
结构化输出不能只看几次人工测试。可以从这些指标评估:
- JSON 可解析率。
- Schema 校验通过率。
- 必填字段缺失率。
- 枚举值非法率。
- 业务执行成功率。
- fallback 触发率。
- 修复后二次成功率。
这些指标能帮助判断问题出在 Prompt、模型能力、Schema 复杂度还是后处理逻辑。
9. 小结
结构化输出是大模型应用走向工程系统的分水岭。它把不稳定的自然语言结果变成可验证的数据接口。
完整闭环应是:
定义 Schema
-> Prompt 注入格式要求
-> 模型生成
-> 清洗与提取
-> JSON 解析
-> Pydantic 校验
-> 业务决策
-> 记录失败样例继续优化
当这个闭环建立起来,大模型就不再只是“会说”,而是能稳定参与业务系统的读取、判断、调用和交付。
更多推荐




所有评论(0)