首页/AI/AI 应用速查/流式输出与提前取消的成本

流式输出与提前取消的成本

流式(SSE)让用户边看边等,同时在用户主动停止、超时或页面关闭时可立刻中断连接——模型停止生成,后续输出 token 不再计费,是长回答场景的省钱阀。

AI 应用速查AI更新于 2026-10-13

流式输出与提前取消

流式输出通过 SSE 把生成结果边算边返回,首字延迟明显降低,同时带来一个省钱阀:用户点击停止、关闭页面或请求超时断开时,网关把断连传导到上游模型调用,生成立刻中止,之后没有产生的 token 不再计费。反过来,只断开自己这一侧的连接而不通知上游,是长回答场景里最常见的隐性浪费,账单上看不出问题,用量却在持续增长。

基本信息

传输方式SSE 或 HTTP 分块传输,服务端逐块推送生成结果
计费口径按实际生成的 token 计费,中断后停止累计
关键链路客户端断开、网关捕获、上游请求取消,三段必须打通
易漏点排队中与重试中的请求、后台批处理任务、多路并发生成
观测指标中断率、平均生成 token、中止后仍产生的 token 占比
适用层自建网关、模型代理层、各厂商流式接口的调用封装

典型使用场景

  • 长文生成与代码生成:用户往往看到前几段就决定停,中断即停能省下大半输出费用
  • 对话产品的停止生成按钮:体验与成本同时受益,是性价比最高的成本优化之一
  • 移动端弱网环境:网络中断频繁,不传导取消就会替用户把整段话生成完
  • 批量任务的超时保护:超过时限的生成应当中止而不是继续占配额
  • 成本复盘:把中断率与浪费占比纳入观测,定位隐性支出的来源

取消要传导到上游

取消要传导到上游
async def proxy(req):
    upstream = client.stream(payload)   # 打开指向上游模型的流式请求
    try:
        async for chunk in upstream:    # 逐块转发给前端
            yield chunk
    except ClientDisconnect:
        raise                           # 客户端走了,交给 finally 收尾
    finally:
        await upstream.aclose()         # 关键一步:真正取消上游生成,停止计费
# 前端侧:AbortController.abort() 触发断连,服务端据此走上面的 finally

浪费场景与处理

场景原因处理
用户关页面后仍在生成断连未传导到上游网关捕获断连并取消上游请求
超时后继续占额度只在前端做了超时服务端设置生成超时并主动中止
重试导致重复生成超时重试但旧请求未取消重试前先取消上一次请求
后台批量任务长尾无单条上限为每条生成设置 token 与时长上限
多路并发取首个结果其余分支未取消拿到首个结果后取消其余分支
服务端自身的生成超时应短于网关与客户端的超时,否则客户端已经放弃,服务端还在继续生成,等于用最贵的方式产生没人看的内容。
中断后要明确半截内容的处理策略:对用户标记为不完整、对计费按实际已生成量入账、对需要重试的场景记录断点,避免出现内容截断却按完整结果入库。

易错点

  • 客户端断开但服务端继续生成到底:用户看不到的内容照样付费,是最常见的隐性浪费
  • 取消只断自己的连接:上游请求仍在运行,token 继续消耗,账单对不上用量
  • 超时与重试叠加:旧请求没取消就发起重试,同一问题被生成两次并计费两次
  • 把流式当纯体验优化:只优化首字延迟,却忘了它同时是成本控制手段,取消逻辑没设计
  • 异步生成的异常路径未清理连接:长连接泄漏,运行一段时间后网关句柄耗尽

数据来源与参考

  • SSE 流式接口工程实践;各厂商流式文档

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌