流式输出

通过配置 stream 参数以 Server-Sent Events(SSE)协议逐块接收文本回复,降低首字延迟。

在默认的同步调用模式下,服务端会在模型完成全部内容的生成后,将完整的 JSON 数据包一次性返回。当在请求体中传入 "stream": true 后,服务端将采用 Server-Sent Events(SSE)长连接协议,按生成进度逐块推送文本增量。这种方式可以显著缩短首字呈现时间,提升终端交互的流畅度。

Chat Completions、Responses 以及 Anthropic Messages 接口均支持通过 "stream": true 参数开启流式输出,各协议的增量数据格式略有不同。

Chat Completions 流式传输

curl https://console.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://console.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://console.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);
}

SSE 协议响应格式解析

Chat Completions 接口在流式模式下以标准的 SSE 事件流返回,每一行为一个带有 data: 前缀的独立 JSON 数据块。文本增量存储在 choices[0].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 解析器。
  • 最后一个有效数据块的 delta 可能为空对象,此时通过 finish_reason(如 stoplength)判断生成终止原因。

使用各语言的官方 SDK 时,底层已封装好事件分块与文本拼接逻辑,可以直接遍历接收流式对象。

流式用量统计配置

按照 OpenAI 官方标准,流式传输过程中默认不返回 usage 统计字段。如果需要在最后一个数据块中获取本次请求实际消耗的 token 数量,可以在请求体中增加 stream_options 配置:

{
  "stream": true,
  "stream_options": { "include_usage": true }
}

部分上游模型可能尚未支持该扩展字段。如果设置后接口报错,移除该配置即可,实际消耗仍以控制台记录的账单明细为准。

Anthropic Messages 流式规范

在调用 Anthropic Messages 接口时,流式协议遵循 Anthropic 的专用事件格式:每个事件由 event: 类型声明行和随后的 data: 数据行组成,文本增量位于 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 等官方及衍生工具时,客户端内部已集成该协议的流式解析。通过代码自主调用时,同样在请求体中传入 "stream": true 即可启用。

常见流式问题排查

配置了流式参数但依然一次性返回结果

如果在发起流式请求后未观察到逐步输出效果,通常是请求链路中的中间代理开启了响应缓冲(Buffering):

  • 检查自建的 Nginx 或反向代理服务是否开启了缓冲机制,可以配置 proxy_buffering off; 禁用缓冲并实时透传分块数据。
  • 在前端使用原生 fetch 接收数据时,应使用 response.body.getReader() 进行可读流逐步读取,避免使用 await response.json() 等待完整响应。

长文本生成过程中连接意外断开

当模型生成超长内容时,持续时间可能超过客户端或反向代理设定的 HTTP 读取超时阈值(Read Timeout)。建议根据业务需求适当放宽中间件超时时间,并在请求中合理设置 max_tokens 参数控制输出长度。

客户端环境不支持流式传输

如果业务调用方运行在批处理脚本或无法处理 SSE 事件流的遗留系统中,直接在请求体中省略 stream 参数或将其设置为 false 即可,接口将按标准模式返回一次性的完整 JSON 数据。

本页内容