大模型应用为什么要做流式输出、取消和超时控制?
简化版
流式输出能显著降低用户感知延迟,取消和超时控制能避免无效生成继续消耗 token 与连接资源。生产系统通常用 SSE 或 WebSocket 返回增量 token,同时在服务端做超时、断连检测、重试和幂等处理。
详细版
- 首 token 延迟决定用户是否觉得系统“有反应”。
- 流式输出不等于总耗时变短,但能改善等待体验。
- 取消生成要通知模型服务或停止读取,否则可能继续计费。
- 超时要分连接超时、首 token 超时、总生成超时和工具调用超时。
- 前端、网关、后端和模型服务的超时要协调,否则容易出现半断连。
完整版教学
易错点:流式输出解决的是“感知等待”,取消和超时解决的是“资源泄漏”。两者必须一起设计。
一、这题真正考什么
易错点:流式输出解决的是“感知等待”,取消和超时解决的是“资源泄漏”。两者必须一起设计。
流式输出改善的是感知延迟:用户更早看到首 token,但模型仍需完成已生成 token 的计算。取消必须从浏览器沿网关、编排、模型客户端和工具传播,否则前端断开后后台仍在计费。
二、核心原理和工程边界
自回归模型逐 token 生成,天然适合边生成边返回。应用层通过 SSE 或 WebSocket 把增量 token 推给前端,前端边收边渲染。与此同时,后端要监听客户端断开和用户取消,把取消信号传到上游模型或中断请求链路。
三、带数字的工程算例
一次回答总生成耗时 12 秒。如果非流式,用户 12 秒后才看到内容;如果首 token 1.2 秒返回,之后每秒 20 token,用户会明显觉得系统更快。若 20% 用户在 3 秒内取消,不做取消传播会浪费大量输出 token。
用户感知延迟 ≈ 首 token 延迟,而不是完整生成耗时
浪费 token = 取消后继续生成的 token 数 * 取消请求量
总超时 >= 首 token 超时 + 预期输出长度 / 生成速率
四、典型链路怎么跑
可以把这类问题拆成下面的链路来理解:
前端发起请求
|
后端创建模型流
|
模型返回增量 token
|
SSE/WebSocket 推送前端
|
用户取消或断连
|
服务端传播 abort 信号并记录日志
五、方案对比和选择标准
| 方式 | 优势 | 适用场景 |
|---|---|---|
| 普通 HTTP | 实现简单 | 短回答、批处理 |
| SSE | 浏览器友好、单向流 | 聊天、生成式问答 |
| WebSocket | 双向实时 | 协同编辑、语音交互 |
| 轮询 | 兼容性强 | 异步任务进度 |
六、上线后最容易出问题的地方
-
只在前端隐藏加载状态不算取消,后端和上游仍可能继续执行。
-
代理层缓冲会破坏流式体验,需要确认 Nginx/CDN 是否关闭缓冲。
-
TTFT 从请求到首个内容 token,不能把连接确认或空心跳当首 token;TPOT 则要排除工具等待并单独报告。
七、常见误区与追问
- 误区:流式输出能降低模型计算成本。 仅分块返回不会减少生成计算;只有用户提前取消且取消真正传到推理端时才可能节省后续 token。
- 误区:用户关页面后请求自然就完全停止。 代理和服务端可能继续读取上游响应,必须传播 cancel signal 并关闭工具与模型调用。
- 误区:所有超时设置成同一个值最简单可靠。 连接、首 token、token 间隔、工具和总 deadline 的故障含义不同,应分层设置且服从总预算。
- 追问:SSE 和 WebSocket 在 LLM 场景怎么选? 单向文本流优先 SSE,需双向实时控制或多路事件时选 WebSocket,同时考虑代理与重连语义。
- 追问:如何统计首 token 延迟? 从服务端接收请求开始,到收到并成功写出第一个非空内容 token,按 P50/P95/P99 报告。
- 追问:工具调用阶段如何向前端反馈进度? 发送受控状态事件如 searching/executing,不泄露思维链;事件要有序号并支持取消。
八、加强记忆
记住“流式管体验,取消管浪费,超时管边界”。面试时把前端、服务端、模型上游、代理层四处都讲到,答案就很完整。