流式输出: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,把长等待变成可见的逐字进度。它改善体感延迟,但要求客户端正确处理分块与终止。

参考与延伸阅读

本文累计阅读