介绍
进入 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 传入数组时,可以为每条消息指定 role。role 告诉模型"这是谁说的话",共有三种类型。
| 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 中的每个字段包含 description。description 作为对模型的指令,提供线索帮助模型正确判断该字段应填写什么内容。像 explanation 或 output 这样的通用字段名,如果没有 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。 oneOf、anyOf等组合有限制。
为防止 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 API(POST /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。 |
实用链接
- Responses API 迁移指南 — 官方迁移指南。
- Structured Outputs 指南 — 官方 Structured Outputs 指南。
- 在 API 中引入 Structured Outputs — 官方发布博客。
- Realtime API 指南 — 实时双向语音和文本的详细信息。
- 速率限制指南 — 速率限制的详细信息。
- OpenAI 变更日志 — API 更新历史。
