核心要点

  • 调用时开 stream=true,模型按 token/分片边生成边返回,首字延迟大幅降低

  • 传输用 SSE(Server-Sent Events),后端转发分片、前端 onmessage 追加渲染

  • 分片可能截断 markdown/JSON,要做缓冲累积,等完整再做最终解析与校验

  • 支持中止(AbortController)和错误中断处理,断流时给用户明确提示

标准回答

后端:开启流式

调用大模型 API 时传 stream=true,模型不再等全部生成完,而是一边生成一边把 token 分片推回来。后端用 SSE(text/event-stream)把这些分片逐条转发给前端,每条形如 data: {...}。

前端:边收边渲染

前端用 EventSource 或 fetch 的 ReadableStream 接收,每收到一片就把文本累加到当前消息末尾并重新渲染,视觉上就是「逐字蹦出」的打字机效果。用 requestAnimationFrame 或节流控制刷新频率,避免高频重渲染卡顿。

关键细节

  • 分片是按 token 切的,可能把一个 markdown 语法(如 ``` 代码块)或一段 JSON 切成两半。要先把分片缓冲累积成完整文本,等收到结束信号再做 markdown 渲染或 JSON 解析。
  • 用 AbortController 支持用户「停止生成」,主动断开连接。
  • 监听错误事件,网络中断或服务报错时停止动画并提示「生成中断,可重试」,别让光标一直闪。

常见误区

⚠️ 常见踩坑

对每个分片单独做 JSON.parse 或 markdown 渲染,结果因分片把语法截断而频繁报错或乱码;正确做法是累积成完整文本后再解析。

追问

追问 1SSE 和 WebSocket 在这个场景怎么选?

流式输出是单向的(服务端持续推、客户端只接收),SSE 足够且更轻量:基于 HTTP、自动重连、实现简单。需要双向实时交互(如语音对话、协同编辑)才上 WebSocket。多数大模型聊天 UI 用 SSE。

追问 2流式输出怎么统计 token 和成本?

流式响应通常在最后一个分片或结束事件里带 usage(输入/输出 token 数),后端在流结束时读取并记账。如果 API 不返回 usage,可在服务端累积完整输出后用 tokenizer 估算输出 token 数。

延伸学习

与本题相关的知识库文章、术语、工具与行业资讯。