Skip to content

流式输出(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_callsdelta.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: noproxy_buffering off,否则用户体验是「等很久突然全出来」。
  • 超时:流式请求建议把客户端超时设到 10 分钟以上。
  • 取消:客户端断连时上游会继续生成完成——要省钱务必显式 abort 请求并立即关 socket。