跳到主内容

智能体结构化输出怎么做:JSON Schema 约束加校验重试的三道关

100%
智能体结构化输出怎么做:JSON Schema 约束加校验重试的三道关

结论先说:想让智能体稳定吐出能被程序直接消费的数据,靠的不是”请返回 JSON”这句提示,而是三道关——先用 schema 做硬性约束,再在服务端做校验与拒答识别,最后才是带错误回传的有限重试。三道关缺任何一道,线上都会出现偶发的解析失败。

第一关:把约束交给解码层,别交给提示词

提示词里写”只输出 JSON”,模型仍有小概率输出多余说明或漏字段。可靠的做法是在请求里开启严格模式:开启后,模型输出会被约束到给定的 JSON Schema 上。相应地,schema 必须满足几条硬性要求:

  • 每个对象都要显式声明 "additionalProperties": false;
  • properties 里的字段必须全部列入 required;
  • 可选字段用联合类型表示,例如 "type": ["string", "null"],而不是直接省略。
{
  "type": "object",
  "properties": {
    "city": { "type": "string" },
    "unit": { "type": ["string", "null"], "enum": ["celsius", "fahrenheit"] }
  },
  "required": ["city", "unit"],
  "additionalProperties": false
}

schema 不满足约束时请求会被直接拒绝并给出原因,这反而是好事——问题暴露在编码阶段,而不是凌晨的线上日志里。

推荐做法:始终开启严格模式

官方的建议是只要能用就开启。它的实现方式是约束解码:在生成过程中就屏蔽掉不符合 schema 的候选,因此与”提示词里反复强调格式”有本质区别。可用但无法兼容时,接口会退回尽力而为的模式,并在响应里标明并未生效——生产环境应把这一项当作监控指标,发现降级立即报警。

第二关:服务端校验与拒答识别

约束解决的是”格式一定对”,解决不了”语义对不对”和”模型拒绝回答”。服务端要检查三件事:

  • 结构校验:类型、必填、枚举值、数值区间,用成熟的校验库跑一遍,不要手写 if 。
  • 拒答识别:模型出于安全策略可能返回拒绝而不是数据,响应里有专门的拒答字段可以被程序读到,必须显式判断,否则会被当成空数据处理。
  • 截断识别:输出被长度限制截断时,JSON 一定不完整。检查结束原因,截断的请求要么提高上限重发,要么拆分任务,不要试图修补半截 JSON 。
把语义规则写进 schema,而不是写进提示词:取值范围用 minimum/maximum,字符串长度用 minLength,可选集合用 enum。能被 schema 表达的规则,就不要指望模型自觉遵守。

第三关:重试要有信息量,还要有上限

无脑重试是最常见的反模式。正确的重试是把校验失败的具体原因回传给模型:哪个字段不合法、期望什么、实际给了什么,让它带着错误信息重来一次。这样第二次的成功率远高于原样重发。

上限建议设为两次,第三次就该走降级:返回结构化错误、转人工,或改用确定性解析兜底。无限重试只会把延迟和成本放大,最终仍可能失败。重试与降级的整体分层见智能体工具调用失败的四层设计。

四个高发坑

  • 嵌套过深:三层以上的嵌套对象会明显降低遵循率。把深层结构拆成多个平级字段,或拆成两次调用。
  • 滥用枚举:几十个取值的枚举既占上下文又容易选错,超过十几个就考虑改成自由字符串加服务端映射。
  • 流式输出直接解析:流式传输过程中数据是不完整的,必须等结束事件再解析,或者用 SDK 提供的增量聚合能力。
  • 把推理过程和结果混在一个字段:给思考留一个独立字段,最终答案字段保持纯净,下游解析会简单很多。

和输出侧其他防线的关系

结构化约束只是输出侧的第一道防线,完整的输出治理还包括内容审核与权限校验,整体框架见智能体护栏实现;工具参数本身该怎么设计、描述写到什么程度,见智能体工具设计实践。本文的严格模式要求与字段写法依据 OpenAI 官方结构化输出与函数调用文档。


开启严格模式后,schema 报不兼容怎么办?
按报错逐条改:补 additionalProperties: false、把所有字段放进 required、可选字段改成联合类型加 null 。这三条覆盖了绝大多数不兼容场景,改完即可开启。

JSON 模式和结构化输出有什么区别?
JSON 模式只保证输出是合法 JSON,不保证符合你的结构;结构化输出会把输出约束到你给的 schema 上。需要被程序消费时,应该用后者。

重试几次合适?
两次。第一次带上具体校验错误,第二次仍未通过就降级。重试前先确认失败原因是格式还是任务本身超纲——后者重试多少次都不会成功。

模型拒答时该怎么处理?
读响应里的拒答字段,走专门的分支记录与提示用户,不要当成解析失败去重试。拒答通常是请求内容触发了策略,重试只会得到同样的结果。

这篇有帮助吗?
云上的幻象
云上的幻象查看主页

七彩云博客,分享 WordPress 建站实战与 AI 工具测评,覆盖服务器运维、站长工具、软件资源与电商运营干货,专注原创实用的主题插件、网站加速与安全优化教程。

921文章4评论

相关文章

评论 (0)

欢迎你,新朋友,感谢参与互动!文明发言,理性交流 · 首次评论将在审核后展示