流式输出不只是 UX,还是 budget 保险丝
去年 10 月某个周五凌晨,我手机震了一下。Anthropic 的 budget alert:当日消费已超 $300。
我爬起来打开控制台,发现是一个长文档摘要 agent 跑飞了,进入了一个自我引用的死循环。每次调用都把前一次的输出塞回 context,越滚越大。跑了大概 4 小时,烧掉 $347.18。
后来做善后的时候意识到一个事:如果我在流式输出里加一个 watchdog,检测到异常模式就主动 abort,这 $347 能压在 $10 以内。
从那之后我看 streaming 的视角就变了。它不只是前端体验好看那点事,它是实打实的 budget 保险丝。
流式的隐藏价值:早停止
非流式调用:你发一个 request,等 8 秒,拿到完整回复,按 output token 数扣钱。无论这回复你要不要,钱都付了。
流式调用:你发一个 request,开始一个 token 一个 token 往回吐。你可以在任何时刻 abort 连接。abort 之前生成的 token 计费,之后的不计费。
这个差别在大多数短任务里无关紧要 —— 生成个 200 字的回复也就一两秒,等就等了。但在三类场景里差距极大:
一是长文生成(5000+ token)。生成中途发现跑偏可以立刻停。
二是 agent 推理链(带 extended thinking 或多轮 tool use)。检测到重复工具调用就 abort。
三是 RAG 场景下的长文总结。用户看到一半觉得够了手动停。
省下来的钱取决于你 abort 得多及时。我实测过几个场景,激进 abort 策略下能从总 output token 里砍掉 50-70%。
实战:边流边判断
具体怎么做。我一般在 SDK 外面包一层 streaming handler,里面维护一个 buffer,每收到一个 chunk 做下面这些检查:
检查一:重复内容检测。
用滑动窗口(比如最近 200 字符)算一个简单的 hash 或者 ngram 频率。如果当前窗口和 30 秒前的窗口相似度 > 85%,说明模型开始复读机了,直接 abort。
我救那个失控 agent 就是靠这个。它当时生成的是 “用户的问题是… 让我重新分析… 用户的问题是… 让我重新分析…” 这种循环。
检查二:工具调用异常。
如果是 agent 模式,同一个工具在短时间内被调用超过 N 次(我设的是 3 次/分钟)就怀疑循环了。特别是同一个工具被传入相同参数调用两次以上,基本就是死循环。直接 abort 然后报警。
检查三:明显跑偏的语义信号。
这个主观一点。我在一个合同审查 agent 里加了个规则:如果输出里出现「我无法完成这个任务」「让我重新开始分析」这类撤退语,说明模型卡住了,abort。
检查四:token 数硬阈值。
最 naive 的一条但很管用。给每种任务设一个合理的最大 output token 数(比如摘要任务 800、答复任务 300、报告生成 3000),流到阈值主动停。比 API 的 max_tokens 参数更细粒度,因为你可以根据任务类型动态调整。
stop sequences 配合 streaming
API 原生支持 stop_sequences 参数,匹配到指定字符串自动停。和 streaming 搭配有奇效。
场景:我让 Claude 分步骤回答,每步用 <step>...</step> 包裹。设 stop_sequence 为 <end>,在 system prompt 里约定「回答完所有步骤后输出
这样我在 client 侧边流边处理 step,如果中途 step 解析出错或者业务逻辑判断已经够了,主动 abort。如果模型正常完成,遇到 <end> API 自己停。
比单纯靠 max_tokens 限制优雅。max_tokens 截断会留半句话、JSON 不完整,stop_sequence 截断在语义边界上。
长文档总结:让用户自己停
这是我觉得最反直觉但最有效的一招。
传统做法:用户点「总结这个 50 页 PDF」,后端跑完返回 2000 字总结,用户看一半觉得够了关了页面。你为剩下那 1000 字付的钱全浪费。
流式做法:一开始就 stream。用户看着 token 一个个冒出来,看到自己想看的部分之后,点「够了」按钮,前端发 abort 信号给 server,server 关 Anthropic 的 stream 连接,停止计费。
我一个法律文档助手产品实测:开启用户主动停功能之后,平均 output token 从 1847 降到 563,省了 69.5%。用户满意度反而小涨了 2 个百分点,因为他们觉得自己「掌控了节奏」。
要注意的是 UI 上要把「停止」按钮做得明显。我一开始把它做成一个小 × 号,用户根本没注意到。改成一个大大的「这些够了,停止生成」之后才真正发挥作用。
失控 Agent 的 watchdog 案例
回到开头那个 $347 事件。复盘之后我在公司内部统一加了一个 streaming watchdog,规则大致是:
- 单请求 output 超过 5k token → warning log
- 单请求 output 超过 10k token → 强制 abort
- 单请求持续时间超过 3 分钟 → 强制 abort
- 检测到上面讲的重复模式 → abort + 报警
- 工具调用超过 15 次 → abort + 报警
上线之后第一周 watchdog 触发 abort 了 21 次。21 次里有 17 次是真的有问题(prompt bug、context 没裁、循环调用),4 次是正常长任务被误杀。后面调了阈值把误杀降到 1% 以下。
现在 watchdog 平均每天触发 abort 3-5 次。按每次平均节省 $0.80 算,一个月给我省 $100 多。更关键的是再也没出过那种一晚上烧几百刀的惊魂时刻。
server 端 cost budget 阈值
更精细的玩法是给每个请求设一个成本预算。
我在 streaming handler 里维护一个累计 cost 计算器,每收到一个 token 按该模型的 output 单价累加。到达阈值(我给普通用户是 $0.10 / request,付费用户 $1.00)主动 abort 并返回一个礼貌的「本次回复已达生成上限」的提示。
实现不难。Sonnet 4.5 的 output 是 $15/M,每个 token 大概 $0.000015。你累加到 $0.10 就是 6666 个 token,足够 90% 的合理任务,拦截的是那 10% 的异常长输出。
这个机制救过我一次更隐蔽的事故:某个用户 prompt injection 让模型生成 50000 字的小说。如果没预算拦截,这一次请求 $0.75。watchdog 在 $0.10 处截断,省了 $0.65。单次不多,但如果被黑产批量刷就是另一回事了。
多租户 SaaS 的预算控制还涉及按用户维度的日/月上限,这块结合 Agent SDK 生产部署 里讲的 key 分层一起做比较干净。
和其他降本手段的配合
流式 abort 主要解决的是「异常输出」的成本,常规输出的成本还是得靠 output token 压缩 和 多模型路由。
streaming 和 batch 是互斥的,选 batch 就没流式。但大多数实时场景不走 batch,所以不冲突。
cache 和 streaming 完全兼容。cache 优化的是 input 侧,streaming 管 output 侧,Prompt Caching 深度指南 那些实践可以和 streaming watchdog 叠加使用。
一点经验
从把 streaming 当 UX 特性到当作 budget 工具,这个视角切换对我帮助很大。现在每个新产品上线前,streaming + watchdog 是标配。
顺带一提:别等出事才加 watchdog。我那 $347 账单虽然最后 Anthropic 客服帮我申诉退回了一部分(因为他们后台也看得出是异常模式),但也退了不到一半。自己装好保险丝比事后求情靠谱。
- 标题: 流式输出不只是 UX,还是 budget 保险丝
- 作者: Claude 中文知识站
- 创建于 : 2026-04-18 22:05:00
- 更新于 : 2026-04-19 14:28:00
- 链接: https://claude.cocoloop.cn/posts/cost-streaming-for-ux-and-budget/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。