流式输出
用 stream 参数逐字接收模型回复,改善长回复的等待体验。
默认情况下,接口会等模型生成完整回复后一次性返回。加上 stream: true 后,服务端会通过 SSE(Server-Sent Events)把回复拆成小块逐步推送——首字出现更快,长回复不用干等,聊天界面也能做出"打字机"效果。
Chat Completions、Responses 和 Anthropic Messages 三个接口都支持流式输出,参数都是 stream: true,但响应格式不同,下面分别说明。
Chat Completions 流式
curl https://anystarx.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MODEL_ID",
"stream": true,
"messages": [
{
"role": "user",
"content": "从 1 数到 5。"
}
]
}'from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://anystarx.com/v1",
)
stream = client.chat.completions.create(
model="MODEL_ID",
messages=[{"role": "user", "content": "从 1 数到 5。"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content if chunk.choices else None
if delta:
print(delta, end="", flush=True)import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'YOUR_API_KEY',
baseURL: 'https://anystarx.com/v1',
});
const stream = await client.chat.completions.create({
model: 'MODEL_ID',
messages: [{ role: 'user', content: '从 1 数到 5。' }],
stream: true,
});
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content;
if (delta) process.stdout.write(delta);
}响应格式
流式响应是一行行的 data: 事件,每行是一个 JSON 块。回复内容在 choices[0].delta.content 里,把每块的 delta.content 拼起来就是完整回复:
data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant","content":""}}]}
data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":"1"}}]}
data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":"、2"}}]}
data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{},"finish_reason":"stop"}]}
data: [DONE]手写解析时注意三点:
- 只处理以
data:开头的行,其余行(空行、注释)直接跳过。 data: [DONE]是结束标记,不是 JSON,不要拿去JSON.parse。- 最后一个 JSON 块的
delta可能是空对象,只带finish_reason。
用官方 SDK 则不需要关心这些,SDK 已经处理好了。
流式下的用量统计
流式响应默认不带 usage 字段。如果需要在最后一个块里拿到 token 用量,加上:
{
"stream": true,
"stream_options": { "include_usage": true }
}个别上游模型可能不支持该参数,报错时去掉即可,用量以控制台记录为准。
Anthropic Messages 流式
Claude 原生协议的流式格式不同:每个事件有 event: 类型行,正文增量在 content_block_delta 事件的 delta.text 里:
event: message_start
data: {"type":"message_start","message":{...}}
event: content_block_delta
data: {"type":"content_block_delta","delta":{"type":"text_delta","text":"1"}}
event: message_stop
data: {"type":"message_stop"}Claude Code 等客户端会自己处理这套格式,你只需要按 Anthropic Messages 配置好 Base URL。手写调用时在请求体里同样加 "stream": true。
常见问题
加了 stream: true 但还是一次性返回
通常是中间层把响应缓冲了。检查:
- 自建反向代理(如 Nginx)是否关闭了缓冲(
proxy_buffering off)。 - 手写 fetch 时是否用
response.body逐块读取,而不是response.json()。
流式中途断开
长回复可能超过客户端或代理的读取超时时间。适当调大超时,或在业务上限制 max_tokens。SDK 一般会在异常里携带已接收的部分内容,按需决定是否重试。
客户端不支持流式怎么办
去掉 stream 参数即可,接口默认就是一次性返回完整 JSON,两种方式可以随时切换。