流式输出:token 逐字吐
大模型自回归逐 token 生成,完整回答往往要等很久。流式输出(Streaming)让服务端每产出一个 token 就立刻推送给客户端,用户能看到文字「逐字出现」,显著降低体感延迟,也便于在生成过程中做增量渲染、中途取消与实时护栏。
是什么
模型并非一次性给完整个回答,而是维护生成状态,每步产出一个新 token。流式输出把这个增量结果通过持续打开的连接实时发送,常见传输是服务器推送事件(SSE),客户端按块读取并拼接。这与一次性返回整段 JSON 形成对比。
为什么需要它
等待一个长回答时,用户如果长时间看不到任何内容,体验很差。流式输出让首字延迟(TTFT)与逐字节奏都可感知,更像人在打字,也更便于做中途取消和增量渲染。在产品层面,它把「等待」变成「进行中」,显著降低跳出率。
怎么做
OpenAI 兼容接口开启 stream 后,按 SSE 逐块读取:
from openai import OpenAI
client = OpenAI()
stream = client.chat.completions.create(
model="gpt-4o-mini", messages=[{"role": "user", "content": "你好"}],
stream=True)
for chunk in stream:
delta = chunk.choices[0].delta.content or ""
print(delta, end="")
每个 chunk 携带增量文本,客户端负责拼接与渲染。
注意点
- 客户端要正确处理分块终止信号,避免连接泄漏。
- 流式下难以在开头做整体校验,护栏策略需支持增量判断。
- 前端渲染建议做节流与换行归一,避免抖动。
- 断线重连需记录已接收长度,避免重复或丢失。
实践建议
前端应做增量渲染与换行归一,避免逐字抖动;断线重连需记录已接收长度,防止重复或丢字。流式下难以在开头做整体校验,护栏策略要支持增量判断,例如边生成边做敏感词拦截。客户端需正确解析 SSE 分块与终止信号,避免连接泄漏。若做中途取消,应主动关闭连接并通知服务端停止生成,节省算力。对长回答可显示进度或占位,提升体感。多轮对话中,流式与第一轮缓存可结合,已生成部分可复用。注意流式会增加请求数量与连接开销,网关层面需做好连接复用与限流,避免被大量长连接拖垮。在聊天产品里,可把流式与打字机动画结合,让用户感知到系统在处理,从而提升整体满意度。对无障碍场景,流式也能配合屏幕阅读器做渐进播报,改善可读性,降低用户的等待焦虑。
小结
流式输出利用自回归生成的增量特性,通过 SSE 实时推送 token,把长等待变成可见的逐字进度。它改善体感延迟,但要求客户端正确处理分块与终止。
参考与延伸阅读
- OpenAI 流式响应文档。已核验。https://platform.openai.com/docs/guides/streaming-responses
- Anthropic 流式文档。已核验。https://docs.anthropic.com/en/docs/build-with-claude/streaming
- MDN 关于服务器推送事件(SSE)的说明。已核验。https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events