结构化输出与契约
本节目标
区分“像 JSON”“可解析 JSON”“符合 schema”和“业务语义正确”,建立从模型输出到业务动作之间的验证层。
四层检查
假设期望输出 {"label":"billing","reason":"重复扣款","evidence":"扣了两次"}:
- 语法:能否被 JSON 解析器读取?单引号、尾逗号和 Markdown 代码围栏都可能导致失败。
- 结构:字段是否存在、类型是否正确、枚举是否合法、是否出现多余字段?JSON Schema 可描述这层。
- 业务规则:
unknown是否必须附带原因;证据引用是否真的来自输入;币种、总额或状态之间是否自洽? - 授权:即使前三层通过,是否允许自动退款、发邮件或删除数据?高影响动作仍需独立授权或人工确认。
供应商的 schema 约束能力、支持的关键字与失败表示会变化。以 2026-07-21 的 OpenAI 文档为例,JSON mode 只保证输出是有效 JSON,不保证匹配你的 schema;Structured Outputs 在受支持的模型、接口与 schema 子集上提供 schema 遵循保证。即便如此,应用仍须处理拒答、输出未完成和“结构合法但语义错误”的值。Google 当前文档同样说明只支持 JSON Schema 子集,并要求应用验证语义值。不能因为两个功能都叫“结构化输出”,就假定同一份 Draft 2020-12 schema 可原样跨供应商使用。
一个最小 schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"label": {"type": "string", "enum": ["billing", "technical", "other"]},
"reason": {"type": "string", "minLength": 1, "maxLength": 160},
"evidence": {"type": ["string", "null"], "maxLength": 120}
},
"required": ["label", "reason", "evidence"],
"additionalProperties": false
}字段阅读(JSON 示例必须保持可解析,因此把解释放在代码块外):
$schema声明这份示例按照哪个 JSON Schema 草案来理解;它不表示所有供应商接口都完整支持该草案。- 根级
type: object要求模型返回一个对象,而不是数组、字符串或裸数字。 properties是允许出现的字段集合;其中label只能取三个枚举分类,reason必须是非空且不超过 160 个字符的解释。evidence允许字符串或null,以便“没有可引用证据”成为显式状态,而不是让模型编造内容。required要求三个字段都出现;即使evidence没有值,也要明确返回null。additionalProperties: false拒绝未经契约声明的额外键,避免下游悄悄消费模型临时新增的字段。
提示中解释字段语义,API 层尽可能启用供应商当前支持的 schema 功能,程序端再解析和校验。三处应从同一契约资产生成或做漂移测试,避免提示、API 参数和代码各自演化。本库版本见 response.schema.json;为了保持标准库零依赖,离线验证器并不是通用 JSON Schema 引擎,而是只接受手写运行时已实现的精确教学子集。根对象、三个字段及 anyOf 分支均有关键字白名单,出现 pattern、allOf 等未实现约束会失败关闭;随后再执行“billing/technical 必须给证据”和“证据必须能在输入中找到”等业务规则。
失败处理
- 解析失败:记录经过脱敏的响应片段、请求 ID 和提示版本;只在策略允许时重试。
- schema 不符:不要在业务代码里“猜着修”;策略允许时可发起次数受限的修复请求,但修复结果必须重新通过全部校验,连续失败应停止而不是无限重试。
- 内容拒绝或安全拦截:作为显式结果处理,不伪装成空成功。
- 输出截断:缩小任务、提高合理的输出上限或改用分步流程;不能直接拼接半个 JSON。
- 语义不可信:降级为人工复核,不把
confidence当校准概率。
练习与自测
为“从发票文本抽取币种和总额”写 schema,并回答:总额为字符串还是数字?千位分隔符如何处理?文本没有币种时是 null、unknown 还是失败?若这些没有明确,schema 还不是完整合同。
掌握检查
- 我能分别解释 JSON 语法、schema、业务规则和授权四层。
- 我不会把 JSON mode 说成 schema 遵循保证。
- 我会显式处理拒答、未完成输出、额外字段和语义错误。
- 我能让提示说明、API schema 与程序验证共同引用同一契约版本。
下一步
进入 模板、变量与版本管理,让合同与提示可以追踪和发布。
参考资料
- OpenAI:Structured Outputs(访问于 2026-07-21)
- Google:Structured output(访问于 2026-07-21)
- JSON Schema Draft 2020-12:Validation(访问于 2026-07-21)