单词元降价、额度却掉得更快:共享额度池的四笔账|洹拓科技

一、单价与总额这两件事怎么同时为真
一家模型公司(公开报道为 Kimi)就新一代旗舰模型使用中的限流与不必要的额度消耗发布用户公告致歉,承认问题出在服务方,并承认本应更早修复。这条公告激起的第一层疑问很朴素:接口文档里新一代模型的单词元定价较上一代是下调的,为什么用户手里的额度反而掉得更快。
把这两句放在一起看,它们指向同一件事,决定账单的不是单价而是计量口径。我们做云服务与模型服务的计费模块时,习惯把费用写成单价乘以计费量,单价是市场行为,计费量则由链路上几个可以各自调整的实现细节决定。三个机制各自都有可核对的现象。
其一,一次用户请求被拆成多个子任务,每个子任务各自带一遍上下文。用户看到的是一轮对话,计费链路上记的是若干次子调用,账单按子调用叠加而不是按用户轮次累加。可核对的现象是,同一句请求在不同实现下扣减金额差别明显,而界面显示的轮次读数与扣减记录对不上。
其二,上下文窗口越长,每轮重复处理的历史越多。长窗口模型把此前内容重新作为输入送进去,历史不是免费的,它每一轮都进一次输入侧计量。公开报道里“第一次生成任务就消耗掉长时间窗额度的 66%,追加一句继续优化后升到 94%”是用户反馈的读数,不是本篇的判断依据,但它最合理的解释就是第二次请求把整段历史重新计入,而增量输出的长度远小于重放历史的长度。
其三,输出与思考过程的长度是否计入计量。同一句结论,思考段计入与不计入两种口径差价明显;这一项在公告里通常不写,往往要等到争议发生才被发现。
二、共享池带来的串扰与两种处置
该产品的额度定义里有三句要紧的话:多个会员档位共享同一个月度额度池;按实际词元消耗扣减;某项功能用尽会影响其他功能,未用完的额度不结转到下一账期。第三句在工程上等价于把多个用例放进同一个故障域。文本生成、长文档处理、多模态生成这几类任务的成本结构完全不同,共用一份余额之后,任何一类跑冒滴漏都会串到其余几类上。
处置只有两条路。一条是按用例分池,每类任务有独立额度与独立告警线,好处是故障域天然隔离,代价是要重新做一套额度分配与结算逻辑。另一条是同池但按用例打标签,每一笔扣减在写入时就带上来源用例标识,可归因到任务类型、可出报表。两条路给用户的读数差别很大:分池之后用户能看见“这一类用完了”,打标之后用户能看见“这一类花掉了多少”。
同池不打标是最差的一种组合,因为它让双方都算不清。用户只知道余额掉了,服务方只知道总量掉了,谁都没有把消耗摊到用例上的能力;一旦进入争议,只能靠人工翻日志逐条还原,而还原出来的结论又无法复核。洹拓在给客户实现配额与计费模块时,把“每一笔扣减必须带归因字段”列为不可删项,原因就在这里:归因字段在系统建设期是几行代码,在争议期是一份证据。
三、不结转叠加重置式补偿的账务语义
补偿方案值得逐字读。公告对所有档位的订阅会员做一次用量重置,有效期内的会员按月度总额的 25% 获得补偿,公开报道把它类比为相当于一周的用量,且不需要申请;同一条公告里还有一句容易漏掉的话,当前用量不足月度总额的 25% 时,重置为 0。上述比例与类比都是公告给出的口径,只用于说明事件关系,不是本篇的判断依据。
把不结转和重置合起来看,语义就清楚了。重置不增加下一账期的可用量,它是一次账期内的余额调整,作用范围只在当期;对企业客户来说,这类补偿在账务上不能记作追加服务量,只能记作当期服务量的一次修正,审计时也要按当期修正来附说明。而“不足 25% 则重置为 0”这一条,对几乎没有使用新模型的用户意味着把他本来还没用完的额度抹平到这个数,而不是在原有余额上增加。同一条公告,对高消耗用户是补,对低消耗用户是削,两类人的读数完全不同,这也解释了为什么有用户在拿到补偿之后仍然不敢再跑大任务。
用户侧能做的自证只有一件事:把任务前后的额度读数与任务清单配对。具体做法是每条任务记下发起时刻、结束时刻、请求内容摘要、任务前后的余额读数四样,形成一一对应的记录。这份记录不是投诉材料,而是争议时唯一可用的证据。服务方给出的账单粒度只到扣减金额,不到“这一笔对应哪一次点击”,没有配对记录,双方各自的读数都对不上,只能各说各话。
四、限流与额度异常必须分列
公告把限流与额度消耗写在同一句话里,这是最容易被误读的地方,因为它们是两类问题,处置路径互不通用。
限流是容量现象,根因是请求量超过可用的算力或并发上限,表现形式是等待、排队、拒绝。它随扩容自然缓解,不需要改动计费链路。额度异常是计量现象,根因在链路的哪一段被计入费、被计入几次,表现形式是余额减少的速度与用户感知到的产出对不上。它不会自愈,而且修复动作落在计费链路上,不在集群上。
两者写在同一份对外说明里,读者很容易得出扩容完成即整改完成的结论。公告里“减少不必要的子 Agent 调用与输出长度”这一句属于计量侧整改而不是容量侧;它同时说明一件事,一次用户请求背后的子调用数量,是服务方自己也在调整的变量。这类变量不写进合同与文档,用户就永远只能事后从余额变化里倒推。我们把这条经验搬进自己的告警规范:容量类告警与计量类告警分开分级、分开指派处置人、分开写复盘结论;两者出现在同一份对外说明里时必须分列两栏,各写各的原因与修复动作。
五、四笔账与合同里该写死的五项口径
围绕共享额度池,能核对的读数其实只有四笔账。
| 账名 | 谁定的口径 | 用户能不能自证 | 争议时怎么办 |
|---|---|---|---|
| 单价账 | 服务方的定价文档 | 能,接口文档公开可查 | 按公示单价与计费量核算差额 |
| 轮次账 | 服务方的链路实现,用户侧不可见 | 不能直接自证,要靠任务清单与前后读数配对 | 要求对方给出子调用粒度的明细 |
| 归因账 | 池化策略决定,取决于是否分池或打标 | 分池或打标后可以自证,同池不打标时不能 | 先补齐归因字段再谈责任划分 |
| 补偿账 | 公告与客服条款 | 能,但需要比对账期边界 | 按当期修正处理,不得计入下一账期 |
轮次账是四笔里唯一口径在对方手里而自己看不见的一笔,也是所有争议的源头。所以采购侧要把它写进合同,至少写死五项计量口径:第一,哪一段计入费,输入是否包含全部历史、思考段是否计价、被中断的输出计不计;第二,子调用是否叠加计量,一次请求按几次记;第三,失败与中断任务是否扣减,扣多少,谁来判定失败;第四,缓存命中是否单独计价;第五,争议时以哪一侧的读数为准,对账周期是多长。五项里最容易漏的是第三项,任务跑完但没有产出,到底扣不扣费。这类情形在视频与多模态生成上并不罕见,公开报道里就有用户反馈一次视频生成任务运行到结束、额度从满降到零而视频并未产出,该读数同样只是用户反馈,不是本篇的判断依据。
六、我们自己的交付要补的三条验收项
写到这里必须自查一句:我们交付给客户的智能体系统,同样在制造用户看不见的子调用。一个带工具编排的对话服务,用户提一轮问题,后端可能串联检索、改写、多次模型调用与若干次校验,这些子调用在客户侧的账单上如果只表现为一次扣减,我们就成了自己最不喜欢的那种服务方。
因此把三项做成硬性验收项。第一,一次用户请求的子调用数量上限与深度上限要有明确数值并写进配置,超出即停止并回传原因,而不是静默继续展开;这条不写,链路会在长任务里自己生长。第二,任务被中断时的计量减免规则要有定义,中断在哪一段、按比例减免还是全免、由谁判定,三个问题都要有答案。第三,在演示环境里就给出可读的子调用清单,逐项标注每个子调用的输入规模、输出规模与耗时。清单要在演示阶段就可见,是因为它到上线阶段会变成计费明细,那时再补,客户会把它当作补救而不是设计。
至于公开报道所称的百万级上下文窗口,这类参数只说明历史重放的分母有多大,并不说明一次任务的真实成本,两者之间的差距恰好就是本篇所说的轮次账。额度这件事上我们更愿意把话讲朴素:单价由市场给出,口径由实现者决定;口径提前写得越清楚,事后争议越少,这也是这份公告对客户交付最实际的一条提示。