跳转到内容

流式输出

在 1折AI 上用流式输出:Anthropic 原生的 SSE 事件序列、OpenAI 兼容的 chunk 格式,以及断流时怎么处理。

长回答用流式输出("stream": true),首字更快出来,也不容易因为单个请求时间太长被中间网络掐断。两种协议都支持,格式各自和官方一致。

请求里加 "stream": true,返回的是 Server-Sent Events。一次正常的流按这个顺序(来自 Anthropic Streaming 文档):

事件含义
message_start消息开始,带模型和初始 usage
content_block_start一个内容块开始(文本、thinking、tool_use)
content_block_delta内容增量,文本在 delta.text 里
content_block_stop这个内容块结束
message_delta消息级更新,带 stop_reason 和最终的输出 token 数
message_stop整条消息结束

中间可能穿插 ping 事件,可以忽略;出错时会收到 error 事件。

bash
curl -N https://1zheai.com/v1/messages \
-H "x-api-key: $ONEZHE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model":"claude-sonnet-5-5","max_tokens":128,"stream":true,
"messages":[{"role":"user","content":"从一数到五"}]}'

用 SDK 时不用自己解析事件,见 Anthropic SDK 的流式示例。

/v1/chat/completions 加 "stream": true,返回 data: {...} 形式的 chunk,文本在 choices[0].delta.content 里,最后以 data: [DONE] 结束。SDK 示例见 OpenAI SDK。

[DONE] 前的最后一个 chunk 带 usage,choices 是空数组。不传 stream_options.include_usage 也会返回。2026-10-15 实测的完整流:

text
data: {"id":"msg_011Cg3ERqM8nN58LxLt7TVuG","object":"chat.completion.chunk","created":1792031230,"model":"claude-sonnet-4-6","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"msg_011Cg3ERqM8nN58LxLt7TVuG","object":"chat.completion.chunk","created":1792031230,"model":"claude-sonnet-4-6","choices":[{"index":0,"delta":{"content":"ok"},"finish_reason":null}]}
data: {"id":"msg_011Cg3ERqM8nN58LxLt7TVuG","object":"chat.completion.chunk","created":1792031230,"model":"claude-sonnet-4-6","choices":[{"index":0,"delta":{"content":""},"finish_reason":"stop"}]}
data: {"id":"msg_011Cg3ERqM8nN58LxLt7TVuG","object":"chat.completion.chunk","created":1792031230,"model":"claude-sonnet-4-6","choices":[],"usage":{"prompt_tokens":370,"completion_tokens":4,"total_tokens":374}}
data: [DONE]

处理 chunk 时先判断 choices 是否为空,上面 OpenAI SDK 页的示例已经这样写了。

  • 先看是不是代理:关掉代理直连再试。
  • 客户端的读超时要比模型生成时间长,长输出时调大超时设置。
  • 收到 error 事件里的 overloaded_error,等几秒重试,见错误码与排错。

中途断开的请求不是整笔免费,按断开前已经生成的输出 token 计费,记录在调用日志里。计费的输出可能比客户端实际收到的多一些。2026-10-15 实测,让模型从 1 数到 600,客户端在第 4 秒断开时收到了 188 行(约 380 个输出 token),调用日志记的输出是 750 token。不需要的长输出,与其中途断开,不如一开始就把 max_tokens 设小。