跳到主要内容

取消税:用户点击停止后的推理账单

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的停止按钮是个谎言。当用户点击它时,你的 UI 停止渲染 Token;但在大多数配置下,你的供应商仍在继续生成它们。这些字节从未到达浏览器,但却出现在你的发票上。用户看到的与你支付的之间的差距就是“取消税”(cancellation tax),它是 AI 成本仪表盘上被低估最严重的支出项。

取消税的存在是由结构性原因导致的。自回归推理是一个受 GPU 限制的流水线:当你的客户端关闭 TCP 连接时,模型已经排好队、完成了 KV 缓存,并正以每秒 30–200 个 Token 的速度输出。大多数推理服务栈在 Token 之间不会检查客户端的活跃状态。它们完成任务,记录用量,然后向你收费。客户端看到了 10 个 Token,而日志记录了 800 个。Langfuse、Datadog 以及所有其他观测平台都会忠实地报告这 800 个 Token,因为那是供应商 usage 数据块报告的内容。

为什么停止流并不代表停止生成

取消操作可能发生在三个地方:客户端、代理层和推理引擎。只有在第三个地方取消才能真正省钱。前两个只是“表演”。

在客户端 JavaScript 中,附加在 fetch 调用上的 AbortController 会取消订阅 SSE 事件流,但它并不保证 TCP FIN 能到达供应商。它肯定无法向推理引擎发出停止解码循环(decode loop)的信号。即使 FIN 成功传递,引擎在 HTTP 层面上也没有关于如何处理进程中请求的约定。vLLM(最常见的开源推理栈)提供了一个 abort(request_id) 方法,但你的网关是否真的在客户端断开连接时调用它,是一个大多数团队从未问过的配置问题。LiteLLM 在 2025 年底还有一个待解决的功能请求,因为默认情况下,“尽管我中断了迭代器并关闭了流,LLM 供应商的响应仍被完整跟踪。”

Anthropic 和 OpenAI 对此的处理极不一致。截至目前的 OpenAI Responses API 仅支持针对后台响应的 responses.cancel —— 同步流式响应根本没有取消端点;你只能断开套接字并寄希望于此。官方 GitHub issue 对此描述得很明确:“如果用户取消了运行,我们不希望在下一个 ResponseCompletedEvent 中为额外的计算付费,”随后一位工程师询问这是否已经自动实现了。事实并非如此。Anthropic 的 SSE 消息缺乏超时、心跳或服务端取消原语;社区仍在请求流式空闲超时,更不用说取消语义了。

实际结果是:当你在前端粘贴 abortController.abort() 时,你可以从两个方面衡量其效果。客户端的尾部延迟(tail latency)立即降为零。而两周后你拿到的供应商账单则纹丝不动。

成本仪表盘中的沉默倍增

大多数 AI 成本仪表盘都是基于供应商响应中的 usage 对象构建的。该对象报告总的输入和输出 Token —— 包括客户端放弃后生成的那些。因此,你的仪表盘中“单次对话成本”一行反映的是供应商生成的 Token 成本,而不是用户阅读的 Token 成本。在低弃用率的场景(如批量总结、异步 Agent)中,两者很接近。在弃用率高的场景中,它们会相差数倍。

考虑那些弃用行为具有结构性的功能:

  • 带有可编辑输入的聊天。 用户输入,点击发送,读了前三句话,意识到问题措辞不当,编辑并重新发送。第一次生成在后台运行直到完成。
  • 支持插话的语音界面。 LLM 开始流式返回响应。用户打断。你的 TTS 停止,STT 重启,并启动了新的 LLM 调用。而被中断的那个仍在解码。
  • 带有显眼取消按钮的 Agent UI。 Agent 开始制定计划,用户读了计划,点击取消,调整任务。如果你的 Agent 框架没有将取消信号传递给工具调用的推理请求,模型就会为无人阅读的计划完成生成。
  • 带有自动补全触发生成的搜索式 UI。 每过一个阈值的按键都会触发请求。在用户看到输出之前,这些请求中的大多数就已经被替代了。
  • 手机后台切换。 使用 4G 连接的用户切换到另一个应用。TCP 连接中断。推理会一直运行,直到模型命中停止 Token 或达到最大 Token 限制。

付费 Token 与交付 Token 的比例(The ratio of paid tokens to delivered tokens)可以告诉你情况有多糟糕。我们可以称之为 PTDR。如果它是 1.0,说明用户愿意付费的每个 Token 都出现在了屏幕上。如果是 1.3,说明你比用户实际体验到的多支付了三分之一的推理费用。在消费级聊天场景中,我们见过这个比例在没人察觉的情况下超过 1.5,因为没人去计算它。“单活跃用户成本”指标在默默膨胀;FinOps 询问为什么 LLM 的支出增长快于流量;工程团队将其归咎于模型更换,而没有人怀疑那个停止按钮。

具备中止意识的核算:你的流水线需要的契约

解决这个问题需要将取消(cancellation)视为可观测性中的一等事件,而不是前端的一个边缘案例。这需要三个环节的配合。

第一,客户端核算要与供应商侧的使用量对账。 当用户中止时,记录客户端实际渲染了多少 token —— 即“已交付”(delivered)数量。当供应商的最终使用情况事件到达时(即使是在中止的流中,只要你保持 socket 连接足够长的时间来读取它,通常都会到达),将其记录为“已支付”(paid)。同时存储这两个数值。你的仪表盘应该有三个指标,而不是一个:tokens_deliveredtokens_paid 以及两者的比例。

第二,在技术栈支持的地方实现服务端取消。 如果你是在 vLLM 或 SGLang 上自托管,请将网关的 on_disconnect 处理程序连接到引擎的 abort(request_id)。这是白给的省钱机会,但大多数团队还没做,因为这需要在 HTTP 层知道请求 ID,而这需要通过代理传递该 ID。如果你使用托管 API,对于用户可能取消的任何内容,请使用后台模式 —— OpenAI 的 Responses API 允许通过 ID 取消后台响应,而流式传输端点则不支持。延迟的折中是客观存在的,但比人们想象的要小,特别是如果你同时保留了流式传输的能力。

第三,按路由统计弃用率(abandonment-rate)的仪表盘。 弃用不是模型问题,而是产品界面问题。“带可编辑输入的对话”界面和“带取消按钮的智能体”界面具有不同的弃用特征,它们需要不同的缓解策略。为每个推理请求标记其来源路由,并跟踪每个路由的弃用率和 PTDR。当产品经理提出一个其交互模式容易引发弃用的功能时,你将拥有数据来为该功能准确定价。

产品设计是支付“税费”的地方

工程手段可以止血,但伤口的大小是由产品决定的。取消税最高的那些功能,往往也是现代 AI 产品中最重要的功能。你无法消除它们,但可以让它们变得更便宜。

推迟推理中昂贵的部分。 大多数响应的前 100 个 token 是便宜的,最后 2000 个则是昂贵的(在旗舰级模型中,输出 token 的价格通常是输入 token 的 3–5 倍)。如果你的产品允许用户预览并确认,请将确认门槛设置在昂贵的生成开始之前,而不是在它结束后。一个明确要求用户授权进一步输出的“继续”按钮,其价值抵得上十次关于“用户为什么点击停止”的用户体验研究会议。

在交互界面上激进地限制最大输出 token 数。 如果你的平均响应是 400 个 token,设置 max_tokens=4096 就像是在邀请用户在第 50 个 token 退出时,让你为 3600 个失控的 token 买单。请将其设置为响应长度的第 90 百分位数,而不是理论上限。被弃用的失控生成所产生的税费是不成比例的。

对于短文本补全,优先选择非流式传输。 “流式传输总是更好”的思维模式已经过时了。对于短于约 200 个 token 的补全,流式和批处理之间的用户体验差异微乎其微。但在发生弃用时,成本差异却是巨大的:如果你在请求出队前看到了陈旧信号(用户输入了新提示、用户离开了屏幕),批处理请求可以通过队列在执行前被取消。一旦流式传输开始,这些信号就来得太晚了。

将投机生成(speculative generation)视为其本质 —— 有预算限制的投机。 那些根据部分输入预生成响应的产品(听取部分转录的语音智能体、运行探索性工具调用的智能体)本质上是在运行一种没有核算的草稿模型模式(draft-model pattern)。大多数这些生成的内容都会被丢弃。为每个会话的投机支出设定预算并进行追踪,然后对其设置上限。将预生成视为一个独立的成本池进行管理的纪律,与在基础设施层防止投机解码(speculative decoding)导致服务预算激增的纪律是一致的。

每个 AI 成本仪表盘都应具备的指标

本季度唯一值得埋点的数字是按路由分组的“已支付与已交付 token 比例”(PTDR)。低于 1.1,说明你的产品非常克制。在 1.1 到 1.3 之间,说明弃用水平处于正常状态,你的缓解预算应该是适度的。高于 1.3,说明你正在为没人完成的工作流买单,解决方法是工程管线优化(服务端中止传播、后台模式取消) and 产品重新设计(最大 token 限制、确认门槛、非流式降级方案)的结合。

这个指标之所以尚未成为标准,是因为行业默认将供应商的 usage 数据块视为唯一事实来源(ground truth)。但它不是。它是你支付了多少钱的事实来源。你交付了多少内容的事实来源存在于你的客户端中,即用户离开前实际渲染的 token 数量。这两个数字应该并排记录。它们之间的差距就是你的“取消税”,这是一项你可以降低的税费 —— 不是通过与供应商重新谈判,而是通过意识到它的存在。

References:Let's stay in touch and Follow me for more thoughts and updates