OpenAI API stream 参数怎么用:两种接口与最小示例
简答:一句话结论:在请求 JSON 中把 stream 设置为布尔值 true,API 就会通过 SSE 分段返回结果。Responses API 读取 response.output_text.delta 事件,Chat Completions 读取 choices[0].delta.content;两套字段不能混用。本文按 2026-11-01 检索到的官方文档整理,模型名、SDK 版本和可用参数发送前仍需核验。
定义:stream 是控制 API 是否以流式方式返回生成结果的布尔参数,开启后客户端需要逐个事件或数据块读取响应。
先试这一步:stream=true 改变了什么
普通请求通常等模型生成完成后再返回一个完整响应;设置 stream: true 后,服务端会通过服务器发送事件(SSE)持续发送部分结果,客户端可以边接收边显示。它主要改善首段内容的等待体验,不代表完整生成时间一定缩短。
下面的模型名只是示例值,发送前请从当前官方文档或控制台复制并核验。API Key 使用环境变量读取,不要直接写入命令行参数、Shell 历史、截图或日志。
| 接口 | 开启方式 | 文本增量 | 常用结束判断 |
|---|---|---|---|
| Responses API | stream: true | response.output_text.delta 事件的 delta | response.completed,同时处理 error |
| Chat Completions | stream: true | choices[0].delta.content | 检查 finish_reason,原始 SSE 还要处理 data: [DONE] |
官方说明和字段定义可参考流式响应指南、Responses 流式事件参考与Chat Completions 流式事件参考。
直接复制版:两套接口的 curl 请求
先在当前 Shell 会话中以安全方式设置环境变量,具体密钥获取和权限以当前平台控制台为准。下面两个请求都使用占位模型名,不能直接把 MODEL_NAME 当成真实模型。
Responses API:
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_NAME","input":"用一句话解释 SSE","stream":true}'
Chat Completions:
curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_NAME","messages":[{"role":"user","content":"用一句话解释 SSE"}],"stream":true}'
原始响应出现连续的 SSE 数据,而不是等到最后才出现一个完整 JSON,说明请求已经进入流式路径。若没有实时显示,仍需继续检查客户端解析、代理缓冲和前端刷新,不能只凭最终页面显示时间归因。
Responses API:Python 与 Node.js 最小示例
Responses API 使用语义化事件。文本增量事件的类型是 response.output_text.delta,文本内容在事件的 delta 字段中。事件对象可能是其他生命周期通知,因此不要假设每个事件都有文本字段。
Python:
from openai import OpenAI
client = OpenAI()
stream = client.responses.create(
model="MODEL_NAME",
input="用两句话解释流式响应",
stream=True,
)
for event in stream:
event_type = getattr(event, "type", None)
if event_type == "response.output_text.delta":
text = getattr(event, "delta", None)
if text:
print(text, end="", flush=True)
elif event_type == "response.completed":
print()
elif event_type == "error":
print("\nstream error:", event)
Node.js:
import OpenAI from "openai";
const client = new OpenAI();
const stream = await client.responses.create({
model: "MODEL_NAME",
input: "用两句话解释流式响应",
stream: true,
});
for await (const event of stream) {
if (event.type === "response.output_text.delta" && event.delta) {
process.stdout.write(event.delta);
} else if (event.type === "response.completed") {
process.stdout.write("\n");
} else if (event.type === "error") {
console.error("stream error:", event);
}
}
示例只使用事件类型和增量字段做判断,避免依赖某个 SDK 版本中不一定存在的完成事件详细属性。安装方式、客户端版本和模型可用性请以当前官方文档为准。
Chat Completions:Python 与 Node.js 如何读取 delta
Chat Completions 的流式返回由多个 chat.completion.chunk 数据块组成。文本通常在 choices[0].delta.content,但某些块可能没有 choices,或者 content 为 null,例如角色信息、工具调用增量和最终统计块。
Python:
from openai import OpenAI
client = OpenAI()
stream = client.chat.completions.create(
model="MODEL_NAME",
messages=[{"role": "user", "content": "用两句话解释 SSE"}],
stream=True,
)
for chunk in stream:
if not chunk.choices:
continue
choice = chunk.choices[0]
delta = choice.delta
text = getattr(delta, "content", None)
if text:
print(text, end="", flush=True)
if choice.finish_reason:
print("\nfinish_reason=", choice.finish_reason)
Node.js:
import OpenAI from "openai";
const client = new OpenAI();
const stream = await client.chat.completions.create({
model: "MODEL_NAME",
messages: [{ role: "user", content: "用两句话解释 SSE" }],
stream: true,
});
for await (const chunk of stream) {
const choice = chunk.choices?.[0];
const text = choice?.delta?.content;
if (text) process.stdout.write(text);
if (choice?.finish_reason) {
console.error(`\nfinish_reason=${choice.finish_reason}`);
}
}
读取时不要把普通响应的 message.content 当作流式字段。message 通常对应完整消息,流式 Chat Completions 则使用 delta 表示当前数据块中的增量内容。
相关参数定义可查看Chat Completions 创建接口参考。
include_usage 怎么用:最后统计块不等于每个 chunk 都有 usage
如果希望 Chat Completions 流式响应提供整次请求的 Token 统计,可以在开启 stream: true 时设置 stream_options: {"include_usage": true}。官方参考说明,服务端会在 data: [DONE] 前发送额外统计块,该块的 choices 为空,usage 包含整次请求的统计;其他数据块的 usage 通常为 null。
const stream = await client.chat.completions.create({
model: "MODEL_NAME",
messages: [{ role: "user", content: "统计这次请求的 Token" }],
stream: true,
stream_options: { include_usage: true },
});
for await (const chunk of stream) {
if (chunk.usage) {
console.error("usage=", chunk.usage);
}
const text = chunk.choices?.[0]?.delta?.content;
if (text) process.stdout.write(text);
}
如果连接被中断、取消或代理截断,最终 usage 统计块可能收不到。因此“没有 usage”不能自动解释为零消耗,应记录为统计不完整,并结合请求日志或用量记录核对。stream_options 的具体可用字段以当前接口参考为准。developers.openai.com
SSE、结束事件与工具调用的处理要点
SSE 是一种基于 HTTP 的事件传输方式。使用 SDK 时,SDK 通常已经负责读取事件边界;使用原始 HTTP 客户端时,不能把每次网络读取都当作一个完整 JSON,因为一条事件可能被拆成多次读取,也可能一次读取包含多个事件。
Responses API 中,常见文本事件包括 response.output_text.delta、response.output_text.done 和 response.completed,还应处理 error。Chat Completions 中,文本增量通常从 choices[0].delta.content读取,结束时检查 finish_reason;原始 SSE 解析还要识别 data: [DONE]。具体事件集合以当前官方参考为准。
工具调用或函数参数也可能分段到达。应按工具调用的标识、索引和参数片段顺序累积,等到对应的完成条件满足后再解析完整 JSON;不要对每个参数片段单独执行 JSON 解析,也不要默认工具参数只会出现在一个事件里。
流式输出会让部分内容更早显示,但也会增加逐段审核和中断恢复的处理复杂度。官方指南特别提醒,部分输出更难在生成前完整评估,生产环境需要结合自身审核要求设计处理流程。developers.openai.com
四项成功判定:不要只看终端有没有文字
- 状态码:请求没有被认证、路径、参数或权限错误拦截。
- 响应字段:Responses 能识别文本增量事件,Chat Completions 能安全读取 choices、delta 和 content。
- 实际文本:多个增量片段按顺序拼接后内容完整,没有因空字段、结束块或事件类型判断错误而丢字。
- 客户端显示:终端、服务端日志或前端能够逐段显示,而不是请求结束后才一次性出现。
如果状态码正常但看不到实时输出,按“凭据→最终 URL 和路径→模型→权限或区域→最小请求→错误响应与日志”的顺序排查。重点查看响应体、响应头和客户端日志,再判断是接口、解析器、代理缓冲还是前端刷新问题。
截至 2026-11-01,本文所列主要结构和事件名称参考本次检索到的官方文档;具体 SDK 版本、模型名称、接口行为、可用区域和权限仍需以当前官方文档或控制台为准。本文是 apikey.sbs 的第三方接入说明,不是任何 API 平台的官方页面。
常见问题
OpenAI API 的 stream 参数应该写 true 还是字符串?
应使用布尔值 true,而不是字符串 "true"。在 JSON 中写成 "stream": true;不同语言只是代码语法不同。
Responses API 可以读取 choices[0].delta.content 吗?
不能直接这样读取。Responses API 使用事件模型,文本增量通常来自 type 为 response.output_text.delta 的事件,其文本位于 delta;choices[0].delta.content 是 Chat Completions 的常见读取路径。
为什么开启 stream=true 后仍然看不到实时输出?
先确认响应体确实持续返回,再检查客户端是否按 SSE 事件边界解析、是否等待完整响应、代理层是否缓冲,以及前端是否及时刷新。仅凭页面最后显示时间,不能判断请求是否没有流式返回。
stream_options.include_usage 会保证一定拿到 Token 统计吗?
不会。Chat Completions 会请求一个位于 [DONE] 前的最终统计块,但流被中断、取消或截断时可能收不到。缺少该块应记录为统计不完整,而不是记为零消耗。
最后一个 Chat Completions chunk 一定有 content 吗?
不一定。某些块可能没有 choices,或 content 为 null;最后统计块的 choices 也可能为空。读取前应逐层判断 choices、delta 和 content 是否存在。
流式输出是否一定比普通请求更快?
不一定。stream=true 主要让客户端更早看到开头内容,改善首段等待体验;完整生成时间仍会受到模型生成、网络、客户端解析和代理缓冲影响。
工具调用参数能否每收到一段就直接解析?
通常不能。工具参数可能分段到达,应按工具调用标识和顺序累积,等到完整条件满足后再解析 JSON,避免把不完整片段当成完整参数。