流式输出不是“模型更快”,而是让客户端在完整结果生成前持续收到增量内容。它能改善首字等待体验,但也会引入 SSE 解析、代理缓冲、连接中断和用量统计 等额外问题。
开始前检查
先完成三个确认:
- 使用非流式请求验证 API Key、模型 ID 和基础接口正常。
- 确认目标模型与接口支持流式输出。
- 确认客户端、反向代理和 CDN 不会缓存或合并事件流。
如果非流式请求也失败,先排查 401、model not found 或接口路径,不要直接从 SSE 开始调试。
配置步骤
1. 使用 curl 查看原始事件流
curl -N https://www.aifast.club/v1/chat/completions \
-H "Authorization: Bearer $AIFAST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_MODEL_ID",
"stream": true,
"messages": [
{"role": "user", "content": "用三点解释什么是 SSE。"}
]
}'
-N 会关闭 curl 的输出缓冲。正常情况下,终端会连续出现多个 data: 数据块,而不是等待全部内容生成后一次性显示。
2. Python SDK 流式读取
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["AIFAST_API_KEY"],
base_url="https://www.aifast.club/v1",
)
stream = client.chat.completions.create(
model="YOUR_MODEL_ID",
stream=True,
messages=[
{"role": "user", "content": "给出三个 API 上线检查项。"}
],
)
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
不要假设每个数据块都有文本。工具调用、角色信息、结束原因或兼容层事件可能出现在不同字段中,正式代码需要先判断字段是否存在。
3. Node.js SDK 流式读取
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.AIFAST_API_KEY,
baseURL: "https://www.aifast.club/v1",
});
const stream = await client.chat.completions.create({
model: "YOUR_MODEL_ID",
stream: true,
messages: [
{ role: "user", content: "解释流式输出的两个常见故障。" },
],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
4. 记录完整性而不是只显示文字
生产环境至少记录:
| 字段 | 用途 |
|---|---|
| 请求开始时间 | 计算总耗时 |
| 首个数据块时间 | 计算首字延迟 |
| 最后事件或结束原因 | 判断是否完整结束 |
| 请求 ID | 联系支持时定位请求 |
| 已拼接内容长度 | 识别中途断流 |
| usage | 核对用量;中断时可能拿不到最终统计 |
常见问题
服务端是流式,但网页仍然一次性显示
先用 curl -N 验证源站。如果终端能逐块显示,问题通常在你的后端框架、反向代理或前端读取逻辑。检查是否开启响应缓冲,以及是否真的按流读取 response.body。
输出到一半突然停止
记录最后一个数据块、结束原因和请求 ID。常见原因包括读取超时、网络中断、代理空闲超时、浏览器取消请求或上游生成失败。不要把残缺内容当成成功结果写入数据库。
为什么流式请求没有 usage
部分协议只在最后数据块返回完整 usage。如果连接提前中断,客户端可能拿不到最终统计。账务核对应以控制台和服务端记录为准,不能只依赖前端收到的数据块。
下一步
分别测试短文本、长文本、中文、多字节字符、主动取消、网络断开和代理超时。上线前还应为流式请求设置最大任务时长、断线状态和用户可见的重试入口。