OpenAIAPILLMAIJavaScriptResponses APIStructured Outputs

OpenAI API:Responses API 与结构化输出规范及实现指南

Sloth255
Sloth255
·8 min read·1,639 words

介绍

进入 2025 年,OpenAI API 迎来了重大转折点。2025 年 3 月,Responses API 正式发布(GA),将 Chat Completions API 的对话能力与 Assistants API 的工具集成功能整合到单一端点。旧版 Assistants API 计划于 2026 年 8 月 26 日停用。

此外,Structured Outputs(结构化输出)能确保模型输出严格遵循 JSON Schema,与 Responses API 结合时展现出最大价值。自 2024 年 8 月发布以来,它大幅提升了智能体工作流和数据提取管道的可靠性。

本文首先概述 2025 年 OpenAI API 的整体格局,然后深入介绍这两个核心主题的规范与实现细节。

信息来源
本文中的规范和性能数据参考自 OpenAI 官方文档(developers.openai.com/api)、官方迁移指南(developers.openai.com/api/docs/guides/migrate-to-responses)以及官方博客(openai.com/index/introducing-structured-outputs-in-the-api)。


1. API 整体概览

2025 年 OpenAI API 的主要分类如下:

分类 端点 定位
Responses API POST /v1/responses 新项目推荐使用。统一的智能体接口。
Chat Completions API POST /v1/chat/completions 继续支持(无计划废弃)。
Realtime API WebRTC / WebSocket / SIP 实时双向语音和文本。
Embeddings POST /v1/embeddings 向量搜索和 RAG。
Images POST /v1/images/generations 图像生成和编辑。
Audio POST /v1/audio/transcriptions 语音识别和 TTS。

OpenAI 将 Responses API 定位为新功能的主要目标,并官方确认 Assistants API 将于 2026 年 8 月 26 日停用(来源:官方迁移指南)。虽然 Chat Completions API 将继续支持且无废弃日期,但 Responses API 是当前新项目的推荐选择。

Structured Outputs 不是上表中那样独立的端点,而是 Responses API 和 Chat Completions API 均可使用的输出格式控制选项。在 Responses API 中通过 text.format 参数指定,在 Chat Completions API 中通过 response_format 参数指定。本文尤其关注其与 Responses API 的组合使用。


2. Responses API

2.1 概述

Responses API 是继承 Chat Completions API 并整合 Assistants API 功能的新 Primitive,于 2025 年 3 月正式发布(GA)。

最重要的变化是能够在服务端持久化对话状态。与传统 Chat Completions 每次请求都需要包含完整对话历史不同,Responses API 只需传入 previous_response_id 即可继续对话。

2.2 基本请求

import OpenAI from "openai";

const client = new OpenAI();

const response = await client.responses.create({
  model: "gpt-4o",
  input: "告诉我东京的天气。",
});

console.log(response.output_text); // 使用 output_text 助手直接获取文本

2.3 output_text 助手属性

output_text 是 OpenAI SDK 提供的便捷属性,并非 API 规范本身的一部分。

在 Responses API 的原始响应中,文本嵌套在以下结构中:

response.output[0].content[0].text

output_text 简化了遍历此路径的过程。内部实现是返回 output 数组中第一个 type: "message"content 块为 type: "output_text" 的元素的文本。

// 两者结果相同
console.log(response.output_text);
console.log(response.output[0].content[0].text);

但是,如果 output 数组的第一项不是文本消息(例如发生工具调用时),则可能无法按预期工作。对于使用工具的健壮智能体代码,最好遍历 output 数组并检查 type

for (const item of response.output) {
  if (item.type === "message") {
    for (const block of item.content) {
      if (block.type === "output_text") {
        console.log(block.text);
      }
    }
  }
}

2.4 输入消息中的 role

input 传入数组时,可以为每条消息指定 rolerole 告诉模型"这是谁说的话",共有三种类型。

role 含义 典型用法
system 来自系统(开发者)的指令 定义模型的行为、语气和约束。通常在对话开始时放置一次。
user 来自终端用户的输入 表示用户的陈述或问题。
assistant 模型自身的之前陈述 在多轮对话中,用于将之前的响应作为历史记录提供。
const response = await client.responses.create({
  model: "gpt-4o",
  input: [
    {
      role: "system",
      content: "你是一个有帮助的助手。请简洁地回答。",
    },
    {
      role: "user",
      content: "告诉我 JavaScript 数组方法。",
    },
  ],
});

如果直接向 input 传入字符串(如 2.2 中的示例),该字符串将被视为 role: "user" 的消息。如果想精细控制模型行为或提供 system 指令,请使用数组格式。

2.5 响应结构

与 Chat Completions 的 choices 不同,结果在 output 数组中返回。

{
  "id": "resp_68af4030...",
  "object": "response",
  "created_at": 1756315696,
  "model": "gpt-4o",
  "output": [
    {
      "id": "msg_68af4033...",
      "type": "message",
      "status": "completed",
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "东京天气晴朗。"
        }
      ]
    }
  ],
  "usage": {
    "input_tokens": 15,
    "output_tokens": 12,
    "total_tokens": 27
  }
}

2.6 多轮对话

Responses API 实现多轮对话有两种方式。

1. 在 input 中以数组形式传入历史记录

这是 Chat Completions API 的传统方法。在客户端维护并管理对话历史,在每次请求中包含所有消息。

const history = [
  { role: "system", content: "你是一个有帮助的助手。" },
  { role: "user", content: "告诉我东京的天气。" },
  { role: "assistant", content: "东京今天天气晴朗。" },
];

const response = await client.responses.create({
  model: "gpt-4o",
  input: [...history, { role: "user", content: "明天呢?" }],
});

由于状态不保存在服务器上,其优势在于可以自由操作历史记录,例如删除或总结特定消息。但随着对话增长,输入 token 数量增加,会影响成本和延迟。

2. 传入 previous_response_id(Responses API 专有)

这是 Responses API 新引入的服务端状态管理方法。只需传入上一个响应 ID,OpenAI 服务器即可继承对话历史。

// 第一轮
const response1 = await client.responses.create({
  model: "gpt-4o",
  input: "告诉我东京的天气。",
});

// 第二轮:仅使用 previous_response_id 继承上下文
const response2 = await client.responses.create({
  model: "gpt-4o",
  input: "明天呢?",
  previous_response_id: response1.id,
});

客户端无需维护或发送完整历史记录,请求大小保持小巧。此外,使用 o1 或 o3 等推理模型时,思考 token 在轮次间得以保留,这是一个重大优势,能提升需要持续推理任务的准确性。

使用此方法需要在服务器上保存响应。注意虽然 store 参数默认为 true,但设置为 store: false 将无法通过 ID 引用。

选择标准

情况 推荐方法
需要中途修改/编辑历史记录(RAG 注入、删除旧消息等) ① 数组方式
使用推理模型(o1、o3 等)解决复杂多轮问题 previous_response_id
简单聊天,希望避免手动管理历史记录 previous_response_id
使用 Chat Completions API ① 数组方式(previous_response_id 仅适用于 Responses API)

如需持久化对话管理,也可以集成 Conversations API。

2.7 内置工具

Responses API 的最大优势之一是无需额外基础设施即可使用的内置工具集。

const response = await client.responses.create({
  model: "gpt-4o",
  input: "搜索最新的 OpenAI 新闻并进行总结。",
  tools: [
    { type: "web_search_preview" },
    { type: "file_search" },
    { type: "code_interpreter" },
  ],
});
工具 用途
web_search_preview 相当于 ChatGPT 的网络搜索。
file_search 对上传文件进行 RAG 搜索。
code_interpreter 代码执行和数据分析。
computer_use 计算机操作智能体。
mcp 连接第三方 MCP 服务器。

MCP(模型上下文协议)集成

Connectors 是 OpenAI 为 Google Workspace 或 Dropbox 等流行服务维护的 MCP 封装,而远程 MCP 服务器是公共互联网上任何实现了远程 MCP 协议的服务器(来源:OpenAI Connectors and MCP Guide)。

Responses API 可以集成支持 Streamable HTTP 或 HTTP/SSE 传输协议的远程 MCP 服务器。指定工具时,API 首先从服务器获取可用工具列表(mcp_list_tools),然后模型从该列表中调用所需工具。

基本连接示例(来源:OpenAI Using tools Guide

const response = await client.responses.create({
  model: "gpt-4o",
  input: "投 2d6 并告诉我结果。",
  tools: [
    {
      type: "mcp",
      server_label: "dice_server",           // 服务器标识符(任意)
      server_url: "https://example.com/mcp", // MCP 服务器 URL
      require_approval: "never",             // 自动批准工具调用
    },
  ],
});

console.log(response.output_text);

通过 require_approval 控制审批

默认情况下,所有工具调用都需要开发者明确批准。可以通过 require_approval 控制此行为(来源:OpenAI Connectors and MCP Guide)。

const response = await client.responses.create({
  model: "gpt-4o",
  input: "告诉我 MCP 规范的传输协议。",
  tools: [
    {
      type: "mcp",
      server_label: "deepwiki",
      server_url: "https://mcp.deepwiki.com/mcp",
      require_approval: {
        never: {
          // 这两个工具无需审批;其他工具需要审批
          tool_names: ["ask_question", "read_wiki_structure"],
        },
      },
    },
  ],
});
require_approval 行为
"never" 自动批准所有工具调用。
{ never: { tool_names: [...] } } 自动批准指定工具;其他工具需要审批。
省略(默认) 所有工具调用都需要审批。

连接需要身份验证的服务器

如果 MCP 服务器需要身份验证,使用 headers 参数传入 token。

const response = await client.responses.create({
  model: "gpt-4o",
  input: "获取一些数据。",
  tools: [
    {
      type: "mcp",
      server_label: "my_server",
      server_url: "https://my-mcp-server.example.com/mcp",
      require_approval: "never",
      headers: {
        Authorization: `Bearer ${process.env.MCP_ACCESS_TOKEN}`,
      },
    },
  ],
});

工具列表缓存:虽然从 MCP 服务器获取工具列表(mcp_list_tools)会在每次请求时发生,但在使用 previous_response_id 的多轮对话中,工具列表包含在上一个响应中,因此会跳过重新获取(来源:OpenAI Cookbook: MCP Tool Guide)。

2.8 关键请求参数

参数 类型 说明
model string 模型名称(例如 gpt-4o)。
input string / array 文本或多模态输入。
previous_response_id string 用于多轮对话的上一个响应 ID。
tools array 要使用的工具定义。
text.format object 结构化输出规范(见下文)。
stream boolean 启用流式传输。
store boolean 是否在服务器上保存响应(默认:true)。
reasoning_effort string 调整推理深度(low / medium / high)。
background boolean 在后台模式下异步执行。

2.9 与 Chat Completions 的比较

功能 Chat Completions Responses API
对话状态 客户端(需要完整历史) 服务端(previous_response_id
网络搜索 需要手动实现 内置(web_search_preview
文件搜索 / RAG 需要手动实现 内置(file_search
代码执行 需要手动实现 内置(code_interpreter
MCP 连接 不支持 原生支持远程 MCP
推理 Token 持久化 轮次间丢弃 可以持久化
output_text 助手
格式规范 response_format text.format
新功能交付 有限 主要目标

2.10 推理模型(o 系列)

GPT 系列不同,OpenAI 提供了名为推理模型的一组模型。这些模型在生成答案前执行内部逐步思考过程(思维链)。这种内部思考被计为推理 token,不包含在最终输出中。

对于需要多步推理的任务(如数学、编程、逻辑推理和复杂分析),它们比 GPT-4o 展现出显著更高的准确性。另一方面,由于思考需要时间,延迟和成本也更高。

2025 年的主要模型包括:

模型 特点
o1 / o1-mini 第一代推理模型。
o3 / o3-mini 高精度、高性能的后继系列。
o4-mini 兼顾成本和性能的模型。

推理深度可以通过 reasoning_effort 参数调整(见 2.8)。low 是减少延迟和成本的轻量推理,而 high 是追求最高精度的深度推理。

const response = await client.responses.create({
  model: "o3",
  input: "找出这个数列的通项公式:1, 1, 2, 3, 5, 8, 13, ...",
  reasoning_effort: "high",
});

此外,在使用 previous_response_id 的多轮对话中(见 2.6,方法 2),推理 token 会在轮次间持久化。在多轮中深入挖掘同一问题时,由于模型继承了上一轮的推理而不是从头开始,准确性和效率都会提升。


3. 结构化输出

3.1 概述与背景

可靠地将 LLM 输出强制转换为 JSON 格式是应用集成的关键挑战。OpenAI 通过渐进式改进解决了这个问题:

**JSON 模式(旧版功能)**确保语法正确的 JSON,但不保证遵循 Schema。存在缺少必填字段或出现多余字段的风险。

Structured Outputs(2024 年 8 月发布)保证 100% 遵循开发者指定的 JSON Schema(来源:OpenAI 官方博客)。

OpenAI 的内部评估(evals)显示,使用 Structured Outputs 时,gpt-4o-2024-08-06 对复杂 JSON Schema 的遵循率达到 100%,而 gpt-4-0613 不足 40%,这是一个巨大的飞跃(来源:OpenAI 官方博客)。

3.2 工作原理

OpenAI API 通过将指定的 JSON Schema 转换为上下文无关文法(CFG)来实现结构化输出。该文法在采样过程中限制可生成的 token,强制执行 Schema 合规性。因此,首次发送新 Schema 时会有额外的预处理延迟,但后续使用相同 Schema 的请求不会产生此延迟。

注意(微调模型):对于微调模型,首次使用新 Schema 的请求会产生额外延迟。后续使用相同 Schema 的请求不会有此问题。其他模型没有此限制。(来源:Structured Outputs Guide

3.3 两种使用方式

Structured Outputs 在 API 上以两种形式提供。

第一种是通过函数调用(tools),通过在函数定义中设置 strict: true 启用。适用于 gpt-4-0613 以后的所有模型,适合将模型能力与应用程序连接(例如访问数据库查询函数)。

第二种是通过 response_format / text.format 参数,指定 json_schema 适合模型以结构化格式响应用户(例如在数学教程 UI 中分别显示不同部分)。

3.4 实现示例(Responses API)

在 Responses API 中,参数已从 response_format 移至 text.format(来源:官方迁移指南)。

关于 Schema 中的 description

强烈建议为 JSON Schema 中的每个字段包含 descriptiondescription 作为对模型的指令,提供线索帮助模型正确判断该字段应填写什么内容。像 explanationoutput 这样的通用字段名,如果没有 description,模型特别容易误解。

使用 Zod 时,使用 .describe("...")。直接编写 JSON Schema 时,在属性对象内用 "description" 键指定。

使用 Zod 定义 Schema(推荐)

import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";

const client = new OpenAI();

const Step = z.object({
  explanation: z.string().describe("此计算步骤中所做内容的说明。"),
  output: z.string().describe("此步骤的计算结果(公式或数值)。"),
});

const MathResponse = z.object({
  steps: z.array(Step).describe("解题步骤列表。"),
  final_answer: z.string().describe("方程的最终答案(例如,x = -3.75)。"),
});

const response = await client.responses.parse({
  model: "gpt-4o",
  input: [
    { role: "system", content: "你是一名数学辅导老师。请逐步解释。" },
    { role: "user", content: "求解 8x + 7 = -23" },
  ],
  text: { format: zodResponseFormat(MathResponse, "math_response") },
});

const result = response.output_parsed;
console.log(result.final_answer);
for (const step of result.steps) {
  console.log(step.explanation, "->", step.output);
}

直接指定 JSON Schema

const response = await client.responses.create({
  model: "gpt-4o",
  input: [
    { role: "system", content: "你是一名数学辅导老师。" },
    { role: "user", content: "求解 8x + 7 = -23" },
  ],
  text: {
    format: {
      type: "json_schema",
      name: "math_response",
      strict: true,
      schema: {
        type: "object",
        description: "显示方程逐步解题过程的响应。",
        properties: {
          steps: {
            type: "array",
            description: "解题步骤列表。",
            items: {
              type: "object",
              properties: {
                explanation: {
                  type: "string",
                  description: "此计算步骤中所做内容的说明。",
                },
                output: {
                  type: "string",
                  description: "此步骤的计算结果(公式或数值)。",
                },
              },
              required: ["explanation", "output"],
              additionalProperties: false,
            },
          },
          final_answer: {
            type: "string",
            description: "方程的最终答案(例如,x = -3.75)。",
          },
        },
        required: ["steps", "final_answer"],
        additionalProperties: false,
      },
    },
  },
});

注意:Responses API 中正确的字段是 text.format。旧的 response_format 键在 Responses API 中已废弃(来源:OpenAI Developer Community)。

3.5 函数调用中的结构化输出

要将 Structured Outputs 应用于工具调用,需在函数定义中添加 strict: true

const response = await client.responses.create({
  model: "gpt-4o",
  input: "告诉我订单 #12345 的交货日期",
  tools: [
    {
      type: "function",
      name: "get_delivery_date",
      description: "获取订单的预计交货日期。",
      strict: true,
      parameters: {
        type: "object",
        properties: {
          order_id: { type: "string" },
        },
        required: ["order_id"],
        additionalProperties: false,
      },
    },
  ],
});

限制:对函数调用使用 Structured Outputs 时,parallel_tool_calls 必须设置为 false

3.6 Structured Outputs 的保证(及不保证)

项目 状态 补充
正确的 JSON 语法 ✅ 保证
遵循指定 Schema ✅ 保证(with strict: true
必填字段存在 ✅ 保证
使用 enum 中指定的值 ✅ 保证
事实正确性 ❌ 不保证 与 Schema 无关的输入可能出现幻觉。
安全策略豁免 ❌ 不保证 出于安全原因,模型可能返回 refusal

处理 refusal 的示例:

const response = await client.responses.parse({
  model: "gpt-4o",
  input: [/* ... */],
  text: { format: zodResponseFormat(MathResponse, "math_response") },
});

if (response.output[0].content[0].type === "refusal") {
  console.log("模型拒绝:", response.output[0].content[0].refusal);
} else {
  const result = response.output_parsed;
}

3.7 strict 模式下的 Schema 约束

strict: true 模式下,某些 JSON Schema 特性受到限制(来源:Structured Outputs Guide)。

  • 必须设置 additionalProperties: false
  • 所有属性必须包含在 required 数组中。
  • 不允许在根对象直接使用 anyOf
  • oneOfanyOf 等组合有限制。

为防止 Schema 与类型定义之间的差异,OpenAI 官方强烈建议使用具有原生 Zod 支持的 SDK。


4. 实时 API

2025 年正式发布(GA)的 Realtime API 是一个专为通过 WebRTC、WebSocket 或 SIP 进行低延迟双向语音和文本流式传输设计的专用 API。它面向实时交互场景,例如直接从浏览器连接的语音代理或与电话系统(PBX)集成,与 Responses API 的使用场景明显区分。有关更多详情,请参阅官方 Realtime API 指南


5. 流式传输

Responses API 支持服务器推送事件(SSE)格式的流式传输,允许逐步接收长响应。

const stream = await client.responses.stream({
  model: "gpt-4o",
  input: "详细讲述宇宙的起源。",
});

for await (const event of stream) {
  if (
    event.type === "response.output_text.delta" &&
    event.delta
  ) {
    process.stdout.write(event.delta);
  }
}

Structured Outputs 也可以与流式传输结合使用,在这种情况下,最终返回完整的符合 Schema 的 JSON。


6. HTTP 响应头

API 响应包含对调试和速率监控有用的头信息。

头信息 内容
x-request-id 请求的唯一 ID(支持咨询时必需)。
x-ratelimit-limit-requests 当前应用的 RPM 限制。
x-ratelimit-limit-tokens 当前应用的 TPM 限制。
x-ratelimit-remaining-requests 剩余请求数量。
x-ratelimit-remaining-tokens 剩余 token 数量。
x-ratelimit-reset-requests RPM 重置的剩余时间。
x-ratelimit-reset-tokens TPM 重置的剩余时间。

如果想从客户端指定请求 ID,请添加 X-Client-Request-Id 头。


7. 速率限制

速率限制按组织和项目(而非按用户)应用。

  • RPM(每分钟请求数):每分钟的请求数量。
  • TPM(每分钟 Token 数):每分钟的 token 数量。

使用层级会根据累计付款和使用记录自动升级。如果返回 429 Too Many Requests,建议使用指数退避进行重试(来源:速率限制指南)。

import retry from "async-retry";

async function callApiWithBackoff(params) {
  return retry(
    async () => {
      return await client.responses.create(params);
    },
    {
      retries: 6,
      minTimeout: 1000,
      maxTimeout: 60000,
      randomize: true,
    }
  );
}

8. 版本稳定性与模型固定

gpt-4o 等别名会定期更新到新快照,即使使用相同的提示,输出也可能发生变化。在生产环境中,建议固定像 gpt-4o-2024-08-06 这样的快照名称,并在更新时始终执行评估(eval)。


总结

要点 内容
新项目 使用 Responses APIPOST /v1/responses)。
Chat Completions 继续支持。无需立即迁移。
Assistants API 2026 年 8 月 26 日停用。建议迁移到 Responses API。
Structured Outputs 使用 strict: true + additionalProperties: false 实现 100% Schema 合规。
Responses API 用法 使用 text.format 而非 response_format
实时语音 参考 Realtime API(WebRTC / WebSocket / SIP)。
速率限制 监控响应头,使用指数退避进行重试。
模型版本控制 在生产环境中固定快照并执行 eval。

实用链接