Structured Outputs(结构化输出)
Structured Outputs(结构化输出) 是 OpenAI API 中让模型文本回复遵循开发者提供的 JSON Schema 的能力。它解决的不是“模型能不能写出 JSON”,而是“模型输出能不能稳定满足字段、枚举、嵌套对象、必填项等结构约束”。
在工程系统里,结构化输出把模型回复从自然语言字符串推进到可被程序直接消费的数据对象:表单抽取、分步解题、动态 UI、审核结果、分类标签、评估报告等场景,都可以把输出 schema 当成模型与下游代码之间的契约。
与 JSON mode 的区别
JSON mode 只保证输出是合法 JSON;Structured Outputs 进一步要求输出符合指定 schema。因此 JSON mode 适合旧模型或简单兼容场景,而结构化输出更适合生产代码直接解析、展示或入库的路径。
关键差异:
| 维度 | JSON mode | Structured Outputs |
|---|---|---|
| 保证合法 JSON | 是 | 是 |
| 保证符合 schema | 否 | 是 |
| 典型启用方式 | json_object | json_schema + strict: true |
| 失败处理重点 | JSON 是否完整、能否解析 | schema 是否受支持、拒答或内容过滤是否中断 |
如果业务需要特定字段、枚举值或对象层级,不应只靠 prompt 写“请返回 JSON”。更稳的做法是把 schema 放进 API 参数,并在应用侧继续处理拒答、内容过滤、超时和业务校验。
两种入口
Structured Outputs 在 OpenAI API 里主要有两种入口:
- 最终回复结构化:在 Responses API(响应 API) 中通过
text.format,或在 Chat Completions 中通过response_format: { type: "json_schema", ... },约束模型面向用户或下游系统的回复。 - 工具参数结构化:在 Function Calling(函数调用) 中给函数参数 schema 设置
strict: true,约束模型生成的工具调用参数。
两者的边界不同:如果模型要调用应用里的工具、数据库或业务动作,用函数调用;如果模型是在返回一个结构化答案给应用展示或处理,用结构化回复格式。
flowchart LR
A[用户输入] --> B[模型请求]
B --> C{输出用途}
C -->|调用外部能力| D[Function Calling strict schema]
C -->|返回结构化答案| E[text.format / response_format json_schema]
D --> F[应用执行工具并校验权限]
E --> G[应用解析 parsed object]
Schema 设计约束
Structured Outputs 支持 JSON Schema 的一个子集,而不是完整标准。常见约束包括:
- 根对象必须是
object,不能在根层直接使用anyOf - 对象字段必须都列入
required - “可选字段”通常用联合类型加
null表达,例如["string", "null"] - 所有 object 都需要设置
additionalProperties: false - 支持 string、number、boolean、integer、object、array、enum、anyOf 等类型
- 支持
$defs与递归 schema,但有属性总数、嵌套深度、字符串总长度和 enum 数量限制 - 部分 JSON Schema 关键字不支持;开启
strict: true后传入不支持的 schema 会直接报错
这意味着 schema 应该被当成一段生产接口代码维护,而不是临时拼出来的 prompt 附件。实际项目里更推荐从 Pydantic、Zod 等类型定义生成 schema,避免运行时代码类型和模型 schema 漂移。
拒答、无关输入与幻觉
结构化输出不会取消模型的安全拒答。模型可能返回 refusal,而不是符合业务 schema 的普通内容;应用必须把拒答视为一个独立分支处理。
另一个容易忽视的问题是无关输入:模型会尽力满足 schema,如果用户输入和任务完全不匹配,模型可能为了填满必填字段而编造值。因此 schema 约束应配合 prompt 规则,例如要求在无法抽取时返回空数组、null、固定错误状态或特定分类,而不是强迫模型生成看似完整的数据。
这和 Agent Guardrails(Agent 护栏)的边界一致:schema 正确只说明输出形状可解析,不说明内容真实、动作安全或业务上可接受。
流式解析
Structured Outputs 可以和流式输出配合使用。SDK 会在增量事件中逐步解析结构化内容或函数参数,应用可以边生成边展示字段、边收集工具参数,但真正执行工具或写入系统前仍应等待完整对象并做校验。
对 Harness Engineering(驾驭工程)来说,这让“输出解析”从一次性字符串解析变成事件流消费:UI 可以更早响应,日志和 trace 可以记录中间状态,错误处理也需要覆盖 delta、done、refusal、incomplete 等事件分支。
工程意义
结构化输出把 Prompt Engineering(提示工程)里的“请按某格式输出”,变成 API 层的接口约束。它降低了格式漂移和枚举幻觉,但不会替代:
- 业务层数据校验
- 来源与事实核查
- 权限检查和人工审批
- E2E 测试、fixture 和 Evals(评估)
- schema 版本化与兼容性迁移
因此它更像一层强类型边界,而不是可靠性的全部来源。生产系统仍然需要把结构化输出放进完整 harness:请求构造、schema 版本、解析、错误分支、重试、审计和降级策略都要一起设计。
相关概念
- Function Calling(函数调用) — 工具参数 strict schema 依赖结构化输出能力
- Responses API(响应 API) — OpenAI 中使用
text.format获取结构化回复的主要 API - Prompt Engineering(提示工程) — 结构化输出把格式指令从 prompt 迁移到 API 约束
- Harness Engineering(驾驭工程) — 负责解析、校验、错误处理和业务执行边界
- Agent Guardrails(Agent 护栏) — schema 校验之外仍需安全与合规检查