AI API 流式输出指南:SSE 调试与断流排查
流式输出让应用在生成完成前逐步展示内容。实现时需要同时处理服务器事件、客户端读取和中间代理,单独设置 stream=true 并不能保证界面立即刷新。
请求启用 stream,并让客户端持续读取。按 SSE 事件边界解析,区分正常完成与网络中断,避免把重试的内容直接追加到旧响应。
本文目录
1. 开启流式并使用不缓冲的客户端
先按 API 接入指南 配好密钥和支持流式聊天的模型。请求体中加入 "stream": true。使用 cURL 时加入 -N,关闭它的输出缓冲。
python3 - <<'PY' | curl -N --fail-with-body --silent --show-error \
https://zzq.si/v1/chat/completions \
-H "Authorization: Bearer ${ZEROTOKEN_API_KEY}" \
-H "Content-Type: application/json" --data-binary @-
import json, os
print(json.dumps({
"model": os.environ["ZEROTOKEN_MODEL"],
"messages": [{"role": "user", "content": "请分三点说明如何整理笔记。"}],
"stream": True
}, ensure_ascii=False))
PY这是一次实际模型调用,会消耗相应额度。先用短请求确认行为,再接入业务界面。
2. 按事件边界解析,不按网络块解析
SSE 通过文本事件传输。网络读取到的一块数据可能只有半个事件,也可能包含多个事件;解析器需要保留未完成的数据,并按事件分隔符组装完整事件。不要把每一次网络读取直接当作一个完整 JSON。
对 Chat Completions,文本增量通常来自 choices[0].delta.content;有些块只带角色、结束原因或用量,所以要先检查字段是否存在。正常结束时会遇到 data: [DONE]。其他协议的事件名称和结束方式不同。
3. 区分首段延迟与总生成时间
首段延迟描述等待第一段内容的时间,总生成时间描述完整回答结束的时间。流式展示可以让用户更早看到内容,但并不保证模型整体生成得更快。
若命令行持续输出而网页一次性显示全部内容,检查前端是否在等待完整响应后才渲染。若所有客户端都在最后一次性返回,检查应用框架、中间代理或 CDN 是否缓冲了响应。
4. 把断流与完成分开处理
连接关闭不一定代表正常完成。应用应区分结束事件、用户取消、网络错误和服务端错误;没有收到协议要求的完成信号时,界面应提示响应可能不完整。
不要在后台无条件重试并把第二次结果追加到第一次文本中。涉及工具执行的会话,需要记录工具调用状态并做去重,防止网络重连造成重复业务动作。
5. 核对用量与协议
按本站 流式输出文档,Chat Completions 可通过 stream_options.include_usage 请求末尾的用量信息;具体支持情况仍需结合模型确认。中途断流可能拿不到最终 usage,应再查看控制台用量记录。
Anthropic Messages、Responses 和 Gemini 使用各自的事件结构。切换协议时应同时替换解析器,不能只改变请求地址。
常见问题
开启流式后,为什么仍然一次性显示全部内容?
检查客户端是否等待完整响应才渲染,以及应用框架或中间代理是否缓冲响应。用 curl -N 可以帮助区分客户端显示和传输层问题。
每个网络数据块都是一段完整 JSON 吗?
不是。网络块可能包含半个事件或多个事件,必须先按 SSE 事件边界缓冲、分割,再解析其中的数据。
断流后没有 usage,能按已显示字数算账吗?
不能。显示字符数不等同于计费 token 数。请查看控制台用量记录,并结合当前模型和协议的用量定义核对。
准备好开始验证了吗?
使用已有账号进入控制台,确认密钥权限与可用额度,再执行最小请求。
登录控制台 查看文档