# 流式输出

> 在 BigModel.io 的 Chat Completions、Messages 和 Responses 接口上通过 SSE 流式接收模型输出，读取末尾的 usage 数据块，并处理流中途的错误。

网页版: https://bigmodel.io/zh-cn/docs/streaming · 更新于 2026-10-18

设置 `"stream": true` 后，BigModel.io 会在模型生成的同时以 SSE（server-sent events）返回内容。只要 API Key 所在分组支持某个文本接口，就可以在该接口上使用流式输出。

| 接口 | 开启方式 | 流结束标志 |
|---|---|---|
| `POST /v1/chat/completions` | `"stream": true` | `data: [DONE]` |
| `POST /v1/messages` | `"stream": true` | `event: message_stop` |
| `POST /v1/responses` | `"stream": true` | `response.completed` 事件 |

能调用哪些接口由 Key 的分组决定。GLM、DeepSeek 分组只支持 Chat Completions。

## Chat Completions 流式调用

```bash [cURL]
curl -N https://bigmodel.io/v1/chat/completions \
  -H "Authorization: Bearer $BIGMODEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm-5.3",
    "stream": true,
    "stream_options": {"include_usage": true},
    "messages": [{"role": "user", "content": "写一首关于河流的俳句。"}]
  }'
```

```python [Python]
import os
from openai import OpenAI

client = OpenAI(base_url="https://bigmodel.io/v1", api_key=os.environ["BIGMODEL_API_KEY"])

stream = client.chat.completions.create(
    model="glm-5.3",
    messages=[{"role": "user", "content": "写一首关于河流的俳句。"}],
    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("\n", chunk.usage)
```

```js [Node.js]
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://bigmodel.io/v1", apiKey: process.env.BIGMODEL_API_KEY });

const stream = await client.chat.completions.create({
  model: "glm-5.3",
  messages: [{ role: "user", content: "写一首关于河流的俳句。" }],
  stream: true,
  stream_options: { include_usage: true },
});
for await (const chunk of stream) {
  const text = chunk.choices[0]?.delta?.content;
  if (text) process.stdout.write(text);
  if (chunk.usage) console.log("\n", chunk.usage);
}
```

每个事件是一行 `data:`，内容为 `chat.completion.chunk` JSON，文本在 `choices[0].delta.content` 中。

## usage 数据块

流式请求需要 token 数才能计费，因此在 GLM、DeepSeek 分组上，网关会始终打开 `stream_options.include_usage`，即使你没有设置。`[DONE]` 之前的最后一个数据块 `choices` 为空数组，并带有 `usage`：

```json
{"object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":14,"completion_tokens":21,"total_tokens":35}}
```

代码不能假设每个数据块都有 `choices[0]`，上面的示例都先做了判断。在其他分组上，如需在流中拿到用量，请自行传 `stream_options: {"include_usage": true}`。

LangChain 的 `ChatOpenAI` 配合自定义 Base URL 时，需传 `stream_usage=True` 才能拿到用量。

## Messages API 流式调用

在支持 `/v1/messages` 的分组上，流式输出使用 Anthropic 的事件类型：`message_start`、`content_block_start`、`content_block_delta`、`content_block_stop`、`message_delta`（含输出用量）和 `message_stop`。

```bash [cURL]
curl -N https://bigmodel.io/v1/messages \
  -H "Authorization: Bearer $BIGMODEL_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{"model":"glm-5.3","max_tokens":256,"stream":true,"messages":[{"role":"user","content":"写一首关于河流的俳句。"}]}'
```

```python [Python]
import os
from anthropic import Anthropic

client = Anthropic(base_url="https://bigmodel.io", api_key=os.environ["BIGMODEL_API_KEY"])

with client.messages.stream(
    model="glm-5.3",
    max_tokens=256,
    messages=[{"role": "user", "content": "写一首关于河流的俳句。"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    print("\n", stream.get_final_message().usage)
```

```js [Node.js]
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({ baseURL: "https://bigmodel.io", apiKey: process.env.BIGMODEL_API_KEY });

const stream = client.messages.stream({
  model: "glm-5.3",
  max_tokens: 256,
  messages: [{ role: "user", content: "写一首关于河流的俳句。" }],
});
stream.on("text", (text) => process.stdout.write(text));
const final = await stream.finalMessage();
console.log("\n", final.usage);
```

Anthropic SDK 的 Base URL 是根地址 `https://bigmodel.io`，不带 `/v1`。

## 流中途的错误

在发出第一个字节之前出现的错误，会以普通 HTTP 错误和 JSON 响应体返回。流一旦开始，状态码已经是 `200`，之后的失败会以 SSE `error` 事件送达，随后流结束。没有收到 `[DONE]` 或 `message_stop` 就结束的流，应视为不完整。

如果请求带了 `models` 备选列表，只有在发出任何字节之前才会切换模型。keep-alive 心跳也算字节，所以流一旦建立就不会再尝试其他模型。详见 [OpenRouter 兼容](https://bigmodel.io/zh-cn/docs/openrouter-compat)。

## 验证配置

运行上面的 cURL 示例。你应当看到 `data:` 行逐条到达，最后是一个 `"choices":[]` 且带 `usage` 的数据块，然后是 `data: [DONE]`。在[用量](https://bigmodel.io/usage)页面，这条请求会显示为流式类型，并带有首 token 时间。

## 常见问题排查

**访问 `choices[0]` 时报 `IndexError` 或 `Cannot read properties of undefined`。** usage 数据块的 `choices` 是空数组。按示例先检查 `chunk.choices` 再取下标。

**整段回复一次性到达。** 你和 BigModel.io 之间的代理在缓冲响应。先用 `curl -N` 排除客户端问题，再关闭自己代理的响应缓冲（nginx 为 `proxy_buffering off`）。BigModel.io 已发送 `X-Accel-Buffering: no`。

**400 `invalid_request_error`，提示 stream 类型错误。** `stream` 必须是 JSON 布尔值 `true`，不能是字符串 `"true"`。

**流以 `error` 事件结束。** 上游在流开始后出错。请重试；如果某个模型反复出现，请查看[状态页](https://bigmodel.io/zh-cn/status)。

**`/v1/messages` 或 `/v1/responses` 返回 404。** Key 所在分组只支持 Chat Completions，请改用 `/v1/chat/completions`。

**503 `api_error`「No available accounts」。** 模型 ID 拼写错误，或 Key 的分组不提供该模型。见[模型 ID](https://bigmodel.io/zh-cn/docs/model-ids)。

## 相关文档

- [工具调用](https://bigmodel.io/zh-cn/docs/tool-calling)：流式工具调用的参数会分段到达。
- [推理与思考](https://bigmodel.io/zh-cn/docs/reasoning)：流中的 `reasoning_content` 增量。
- [Chat Completions API 参考](https://bigmodel.io/zh-cn/docs/api-chat-completions)与 [Messages API 参考](https://bigmodel.io/zh-cn/docs/api-messages)。
- [错误码](https://bigmodel.io/zh-cn/docs/errors)。
