GPTMap

OpenAI 结构化输出完全指南:json_schema、strict 模式与常见报错

让模型稳定输出可解析 JSON 的完整路径:Responses API 的 text.format 写法、strict 模式、schema 设计要点,以及只放 schema 不放 name 这类高频报错的排查。

TL;DR
结构化输出(Structured Outputs)让模型按你给的 JSON Schema 返回可解析 JSON。Responses API 的写法是 text={"format": {"type": "json_schema", "name": …, "strict": true, "schema": …}}——schema 必须包在 format 里,name 必填,只放 schema 不放 name 会直接报错;strict: true 让输出严格遵循 schema。本文覆盖 Python / Node 双语言示例、schema 设计要点与高频报错排查表。
结构化输出(Structured Outputs)是 OpenAI API 的约束解码能力:开发者在请求里提供 JSON Schema,模型被约束为按该 schema 输出合法 JSON,从而省掉正则抽取与格式修复,直接 json.loads / JSON.parse 进业务代码。

操作步骤

  1. 定义 JSON Schema

    把想要的输出形状写成 JSON Schema:顶层 type: object,用 properties 定义字段、required 标注必填项,枚举约束用 enum。字段越多,description 越要写清楚。

  2. 包进 text.format 并带 name

    请求里加 text={"format": {"type": "json_schema", "name": 给配置起名, "strict": true, "schema": 你的 schema}}。name 必填——只放 schema 不放 name 会报错。

  3. 用 input 发起请求

    Responses API 的消息字段是 input(数组),不是 messages。把系统指令与用户输入都放进 input。

  4. 解析 output_text 并做防御性校验

    从响应取 output_text 做 json.loads;形状已由 schema 保证,但仍建议保留一层业务语义校验(枚举值是否合法、日期是否在预期范围)。

结构化输出(Structured Outputs)是 OpenAI API 的约束解码能力:开发者在请求里提供 JSON Schema,模型被约束为按该 schema 输出合法 JSON,从而省掉正则抽取与格式修复,直接 json.loads / JSON.parse 进业务代码。本教程以 Responses API 为准讲清完整写法、strict 模式的含义,以及只放 schema 不放 name 这类高频报错的排查。

说明:本文代码按官方 Structured Outputs 指南逐行核对(文档核对版),lastTestedAt 为核对日期;真机运行前建议先在测试环境跑通。

1. 快速上手:最小可用示例

Responses API 的结构化输出挂在 text 参数上,format 里三件套:typenameschema,加上 strict 开关。

from openai import OpenAI

client = OpenAI()

schema = {
    "type": "object",
    "properties": {
        "steps": {
            "type": "array",
            "items": {"type": "string"},
            "description": "按顺序拆解的解题步骤",
        },
        "answer": {"type": "string", "description": "最终答案"},
    },
    "required": ["steps", "answer"],
}

resp = client.responses.create(
    model="gpt-5.6-luna",
    input=[
        {"role": "system", "content": "你是解题助手,严格按 schema 返回。"},
        {"role": "user", "content": "一道题:小明有 3 个苹果,又买了 5 个,一共几个?"},
    ],
    text={
        "format": {
            "type": "json_schema",
            "name": "math_response",
            "strict": True,
            "schema": schema,
        }
    },
)

data = json.loads(resp.output_text)
print(data["answer"], data["steps"])

三个最容易错的位置:消息字段是 input 不是 messages;schema 包在 text.format 里不是顶层;name 必填。官方指南的示例正是 text={"format": {"type": "json_schema", "name": "math_response", "schema": …}} 这个形状。

2. Node.js 等价写法

import OpenAI from "openai";

const client = new OpenAI();

const schema = {
  type: "object",
  properties: {
    sentiment: { type: "string", enum: ["positive", "neutral", "negative"] },
    score: { type: "number" },
  },
  required: ["sentiment", "score"],
};

const resp = await client.responses.create({
  model: "gpt-5.6-luna",
  input: [
    { role: "system", content: "对用户评论做情感分类,严格按 schema 返回。" },
    { role: "user", content: "这耳机续航真行,但佩戴一般。" },
  ],
  text: {
    format: {
      type: "json_schema",
      name: "sentiment_response",
      strict: true,
      schema,
    },
  },
});

const data = JSON.parse(resp.output_text);
console.log(data.sentiment, data.score);

枚举(enum)是结构化输出里最实用的约束:分类任务直接把标签空间写进 schema,模型就不可能输出标签体系之外的值。

3. strict 模式:保证形状,不保证语义

strict: true 的含义是约束解码——模型的输出严格按 schema 生成,字段存在性与类型都有保证。不写或为 false 时,模型"尽量"遵循 schema,在长文本、复杂嵌套下可能偏移出合法 JSON。

但要分清两层保证:

  • 形状保证(strict 给的):字段在、类型对、枚举值在集合内。
  • 语义正确(strict 不给的):answer 是对的答案、sentiment 符合人类判断——这取决于提示词与模型能力。

所以生产姿势是"双保险":strict 保证 json.loads 永远不炸,业务侧再保留一层语义校验(枚举合法性、数值范围、日期格式),校验失败走重试或降级。

data = json.loads(resp.output_text)

# 形状已由 strict 保证;这层校验的是 strict 不保证的语义
assert data["sentiment"] in {"positive", "neutral", "negative"}
if not 0 <= data["score"] <= 1:
    raise ValueError("score 越界,走重试或降级")

4. Schema 设计要点

  • 顶层永远是 object:把所有字段挂在顶层 properties 下,避免顶层裸 array——解析与校验都更简单。
  • required 写全:希望出现的字段全部放进 required;strict 模式下缺失字段的处理不如显式 required + 默认值约定清晰。
  • 枚举优先于自由文本:能枚举的状态(positive/neutral/negativelow/mid/high)都用 enum,把模型的自由度限制在标签空间内。
  • description 写给模型看:每个字段的 description 是模型理解语义约束的第一现场,格式要求(如 "YYYY-MM-DD")直接写在这里。
  • 复杂校验放应用侧:正则、跨字段一致性这类高级约束不要指望 schema 表达,拿到输出后在应用层验证。

5. 常见报错与排查

现象原因修法
只传 schema 就报错format 里缺 namename 字段,这是必填项
报 unknown parameter messages用成了 Chat Completions 字段Responses API 用 input(数组)
输出偶尔不合法 JSON没开 strict: true加上 strict 开关,别依赖"尽量遵循"
枚举值跑出集合schema 里没用 enum 或 strict 未开字段加 enum 并开 strict
解析后字段值语义不对形状对但语义偏加强 description 与系统提示,应用侧加业务校验
长嵌套结构输出被截断达到输出 token 上限精简 schema、拆分任务,或提高输出上限

其中"只放 schema 不放 name"是最常见的翻车点——报错信息不一定直指 name,容易往 schema 语法上找半天。记住三件套:typenameschema,外加 strict 开关。

6. 和 function calling 怎么选

两者共用 JSON Schema 这套描述语言,但解决的问题不同:

维度Function callingStructured outputs
解决什么模型决定调用哪个工具、生成参数约束最终回答的 JSON 形状
触发方模型发起 function_call,你的代码执行你发起请求,直接拿结果
典型场景查数据库、调内部 API、执行动作分类、抽取、打标、生成固定格式内容
返回流function_call → 执行 → function_call_output 回传响应里直接是符合 schema 的文本

一句话:要让模型"做事"用 function calling,要让模型"按格式交作业"用 structured outputs。两者都走 Responses API 的工具与格式机制,字段声明风格一致,学会一个另一个几乎免费。

7. 常见问题

1. structured outputs 和 function calling 什么关系?

两者共用同一套 schema 机制但用途不同:function calling 让模型决定"调用哪个工具并生成参数",结构化输出约束"最终回答的 JSON 形状"。需要把答案交给下游程序消费时用 structured outputs;需要模型触发你这边的能力时用 function calling。同一请求里可以只用其一。

2. 为什么我只传了 schema 还报错?

Responses API 的 schema 必须包在 text.format 里,且 format 里必须带 name 字段——name 是这次输出配置的标识。只放 {"type": "json_schema", "schema": …} 不放 name 会直接报错。完整写法见本文第一个示例。

3. strict: true 和不写 strict 有什么区别?

strict: true 是约束解码:输出严格按 schema 生成,字段与类型都能保证。不写或为 false 时模型"尽量"按 schema 输出,长内容或复杂嵌套下可能偏移。生产代码里凡是拿输出直接 json.loads 的场景都应该开 strict。

4. schema 里能用正则或自定义格式吗?

支持的是 JSON Schema 的常用子集:object、array、string、number、enum、required 这些核心能力最稳。越冷门的特性兼容性越差,设计 schema 时优先用基础类型加 enum 表达约束,复杂校验放到应用侧做二次验证。

5. 输出合法 JSON 但字段值不对怎么办?

结构化输出保证形状不保证语义。把语义约束写进 schema 的 description 与系统提示里(枚举值给注释、日期给格式示例),并在应用侧保留一层业务校验——形状合法 + 语义校验双保险才是生产可用的姿势。

6. Chat Completions 的 response_format 还能用吗?

老项目的 response_format 写法仍然存在,但 Chat Completions 已进入 legacy 阶段,新项目统一用 Responses API(input 字段 + text.format)。本文所有示例以 Responses API 为准。

下一步

关键要点

  • Responses API 用 text={"format": {"type": "json_schema", "name": …, "strict": true, "schema": …}} 传入 schema——schema 包在 format 里,name 必填
  • 只放 schema 不放 name 会直接报错——这是最高频的翻车点
  • strict: true 表示严格遵循 schema 输出;省略或为 false 时模型'尽量'遵循,不保证合法
  • 字段用 input(数组),不是 Chat Completions 的 messages——新项目统一走 Responses API
  • function calling 与 structured outputs 是两件事:前者决定'调哪个工具',后者约束'返回什么形状'
  • 拿到输出后仍要防御性解析:schema 约束的是形状,不保证业务语义正确

常见问题

两者共用同一套 schema 机制但用途不同:function calling 让模型决定'调用哪个工具并生成参数',结构化输出约束'最终回答的 JSON 形状'。需要把答案交给下游程序消费时用 structured outputs;需要模型触发你这边的能力时用 function calling。同一请求里可以只用其一。

官方参考

相关文章

订阅 GPTMap Weekly

每周一封邮件,精选 OpenAI 重要更新、深度解读与最佳实践。无广告,可随时退订。

GPTMap Editorial发布于 2026-08-30 10 分钟阅读
测试环境(EEAT)
最后测试时间:2026-08-30
使用模型:gpt-5.6