# 通过统一 API 接入模型流式输出

> https://router.one/zh/llm-streaming 的 Markdown 镜像，供 AI 助手与爬虫使用。Router One 是 OpenAI 兼容的统一 LLM API 网关。
> 最后更新：2026-09-05

流式输出把 chat completion 变成 Server-Sent Events：Token 边生成边渲染，用户边读模型边写。Router One 遵循 OpenAI Chat Completions 规范——把 stream 设为 true，同一条代码路径即可流式调用 GPT、Claude、Gemini、Grok 等模型，具体支持因模型而异。本页覆盖传输格式、经得住生产环境的客户端写法，以及流式绕不开的两个运维问题：超时与计费。

## 开启流式

把 stream 设为 true。-N 参数让 curl 不做缓冲，分块到达即打印。从 /models 选择支持流式、且详情列出 POST /v1/chat/completions 的对话模型：

`stream.sh`

```bash
curl -N https://api.router.one/v1/chat/completions \
  -H "Authorization: Bearer sk-your-router-one-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model-id-from-/models>",
    "messages": [{"role": "user", "content": "写一首俳句"}],
    "stream": true
  }'
```

## 网络上实际传输的是什么

响应是 text/event-stream：每条 SSE 行携带一个 chat.completion.chunk 对象，choices[].delta 里是片段——第一块通常带 role，后续块携带 content 片段，最后以字面量 [DONE] 结束：

`wire-format.txt`

```text
data: {"object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant"},"index":0}]}

data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"秋"},"index":0}]}

data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"月"},"index":0}]}

data: {"object":"chat.completion.chunk","choices":[{"delta":{},"finish_reason":"stop","index":0}]}

data: [DONE]
```

## 客户端写法

官方 SDK 把 SSE 解析藏在了内部——你只管迭代分块、拼接 delta。同一个循环适用于端点上的所有模型家族：

`stream.py`

```python
from openai import OpenAI

client = OpenAI(
    base_url="https://api.router.one/v1",
    api_key="sk-your-router-one-key",
)

stream = client.chat.completions.create(
    model="<model-id-from-/models>",
    messages=[{"role": "user", "content": "写一首俳句"}],
    stream=True,
)
for chunk in stream:
    if not chunk.choices:
        continue  # 仅包含 usage 的分块没有 choices。
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
```

## 超时、取消与长生成

- 首 Token 时间和总时长是两个不同的预算。大 prompt 或深推理模型在第一块到达前会「想」一阵——这段安静是正常现象，不是卡死。
- 不要给生成类接口设激进的客户端超时；它只会把健康的长生成变成客户端侧的失败。真要设限，就限分块之间的空闲时间，并放宽松。
- 取消就是关闭 HTTP 连接——没有专门的 API。把 UI 的停止按钮接到请求的 abort 上即可。
- 在 Dashboard → Logs 对比端到端耗时，先识别慢请求。要区分网络与模型生成耗时，还需要客户端首字时间和网络测量，仅凭总耗时无法判断。

## 怎样判断 SSE 响应真的完成了？

HTTP 200 只确认流已打开。Chat Completions 客户端除了拼接 delta，还要处理 error 事件和连接异常；仅包含 usage 的分块可能带空 choices 数组。Responses 使用另一套事件格式：检查 response.completed、response.failed、response.incomplete，以及其中的 response.error 或 incomplete_details，不要把 Responses 事件交给 Chat Completions 的 delta 解析器。连接意外结束时，先保留部分输出与 request_id，再决定是否重试。

## 流式请求照样全程记账

流式请求会在 Dashboard → Logs 记录最终模型、Token、花费、延迟与状态，同样受 API Key 的预算约束。结算以记录的 usage 与花费为准。仅凭状态无法知道客户端实际收到多少 Token，也无法还原中间尝试过哪些线路；排查时请保留流内错误与 request_id。

## 常见问题

### 流式会更贵吗？

不会。相同内容下 Token 计费与非流式完全一致——流式只改变响应的交付方式。每请求成本 Trace 展示的字段两种方式相同。

### 好几秒没有任何输出——请求卡住了吗？

通常没有：模型在产出第一个 Token 前要先处理你的 prompt，长 prompt 或深推理模型会拉长这一阶段。忍住别加短超时——先到 Dashboard → Logs 看这个请求的端到端延迟，再下结论。

### 工具调用可以流式吗？

可以——工具调用的片段在 delta 分块中逐步到达：累积 id、函数名和参数片段，直到流以 finish_reason 为 tool_calls 结束，然后走正常的工具循环。见 LLM 工具调用指南。

### 流到一半上游挂了怎么办？

可重试的上游失败在生成尚未展开前可以转移到其他符合条件的路由；一旦你已经在接收 Token，上游硬故障会表现为流中断，客户端应当处理。哪些失败可重试，见自动故障转移页。

### 所有模型都支持流式吗？

Router One 遵循 OpenAI Chat Completions 规范，包括流式输出，具体支持程度因底层模型而异。先查 /models 目录里该模型的条目，各功能的最新细节见文档。

## 相关页面

- OpenAI 兼容 API：https://router.one/zh/openai-compatible-api
- LLM 工具调用：https://router.one/zh/llm-tool-calling
- 结构化输出（JSON Schema）：https://router.one/zh/llm-structured-outputs
- 自动故障转移：https://router.one/zh/llm-fallback
- LLM 可观测：https://router.one/zh/llm-observability
- Vercel AI SDK 接入：https://router.one/zh/integrations/vercel-ai-sdk
- 错误码速查：https://router.one/zh/llm-api-error-codes
- 网关层负责什么：https://router.one/zh/llm-api-gateway
- Chat Completions 接口参考：https://router.one/zh/docs/chat/createChatCompletion
- 本页规范地址：https://router.one/zh/llm-streaming
- 模型与每模型 token 价格：https://router.one/zh/models （markdown：https://router.one/zh/models.md ）
- 定价：https://router.one/zh/pricing
- API 文档（markdown）：https://router.one/zh/docs.md
- 公司事实（markdown）：https://router.one/zh/facts/company.md
