流式输出(SSE)
所有支持流的端点都遵循 OpenAI 风格的 Server-Sent Events 协议。
启用
请求体里加:
json
{ "stream": true }响应格式
Content-Type: text/event-stream,每条事件形如:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{"content":"床"},"index":0,"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{"content":"前"},"index":0,"finish_reason":null}]}
...
data: [DONE]每条 data: 一个 JSON chunk,最后以 data: [DONE] 结束。
拼接消息
把所有 chunk 的 choices[0].delta.content 顺序拼接,就是完整回复。
工具调用、推理过程也通过 delta 传递(delta.tool_calls、delta.reasoning_content)。
拿 usage
默认 chunk 不带 usage。要在最后一条 chunk 拿到 usage:
json
{
"stream": true,
"stream_options": { "include_usage": true }
}最后会多出一条 chunk:
data: {"id":"...","choices":[],"usage":{"prompt_tokens":10,"completion_tokens":42,"total_tokens":52}}错误处理
流中途出错时,会发送一条 data: 含 error 字段,然后断开连接:
data: {"error":{"type":"upstream_error","message":"...","code":"upstream_500"}}应用层应监听并妥善展示。
SDK 示例
Python (openai):
python
stream = client.chat.completions.create(
model="qwen-max",
messages=[...],
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.usage:
print(f"\nusage: {chunk.usage}")TypeScript:
ts
const stream = await client.chat.completions.create({
model: 'qwen-max',
messages: [...],
stream: true,
stream_options: { include_usage: true },
})
for await (const chunk of stream) {
if (chunk.choices[0]?.delta?.content) {
process.stdout.write(chunk.choices[0].delta.content)
}
if (chunk.usage) console.log('\nusage:', chunk.usage)
}注意事项
- 代理 / CDN 缓冲:自建反代时设
X-Accel-Buffering: no、proxy_buffering off,否则用户体验是「等很久突然全出来」。 - 超时:流式请求建议把客户端超时设到 10 分钟以上。
- 取消:客户端断连时上游会继续生成完成——要省钱务必显式 abort 请求并立即关 socket。
