客服模型成本应按合格工单计算
文章以物业客服分流为例,将输入输出 token、重试、上下文检索及人工复核纳入成本。建议固定测试工单、输出结构和重试策略,比较每条通过校验的分流记录成本。
AI 深度解读
给物业客服机器人选模型,只看每百万 token 的报价,很容易选错。原文提出的办法是:固定工单、输出格式和重试规则,比较每条通过验收的分流记录究竟花了多少钱,把检索、重试和人工复核一起纳入决策。
它讨论的不是聊天回复写得多自然,而是生产队列能否稳定收到正确的数据。对正在用 AI 做工单分类、信息抽取的程序员,这套思路很实用。不过,作者没有提供模型实测排名,交付的是一套评估方法。
先定义什么叫合格,再讨论哪个模型便宜
原文里的流程很短:工单进入系统,分类器提取固定对象,校验器检查结果,队列 worker 把失败项送去重试或人工复核。机器人之后可以继续回答住户,但第一步必须把类别、紧急程度、物业标识和简短理由放进约定字段。
这里的「结构正确」有两层:JSON 能解析,字段符合约定;分类结果也要符合业务事实。漏掉物业标识可能导致派错团队,把漏水标成低优先级则可能延误处理。
一条便宜但无法被业务接受的记录,仍然是一条需要继续花钱处理的记录。
因此,比较候选运行时之前,要固定匿名化工单集、system instructions、允许的标签、输出 schema、上下文窗口、历史消息策略和重试规则。否则,价格差异可能只是某个模型少看了上下文,或另一个模型多输出了会被拒收的解释文字。
运行时也不只是模型名称,它包括托管 API、自托管服务器以及实际请求路径。托管方案减少运维工作,却依赖网络和服务限额;自托管提供部署控制,同时要求团队负责容量规划、补丁和加速器利用率。原文没有断言哪一种必胜,前提是先写下这条队列的验收门槛。
每条合格记录的成本,要怎么计算
作者最初以为输出是主要开销,因为用户看得见客服回复。转向分流任务后,作者发现反复携带的历史工单、检索出来的租约和维修资料可能占据更多输入;输出即使只是短 JSON,也可能因校验失败而反复生成。
下面的代码把输入和输出分别计费,再计算每条合格记录分摊的 token 成本:
type Usage = {
inputTokens: number;
outputTokens: number;
};
type Rates = {
inputPerToken: number;
outputPerToken: number;
};
function tokenCost(usage: Usage, rates: Rates): number {
return usage.inputTokens * rates.inputPerToken
+ usage.outputTokens * rates.outputPerToken;
}
function costPerAcceptedRecord(
usage: Usage,
rates: Rates,
attempts: number,
accepted: number,
): number {
if (accepted <= 0) throw new Error('No accepted records');
return tokenCost(usage, rates) * attempts / accepted;
}
要看最后一行乘以 attempts 的口径:如果 usage 已经累计了所有请求的消耗,再乘请求次数就会重复计费。原文没有明确这个参数代表单次用量还是平均用量,落地前必须补齐定义。
费率需要放进配置,并记录计价单位和生效日期。缓存提示词、新请求和重试也要分别标记,不能混成一个没有说明的 token 总量。
评估表则应为每个候选运行时保留输入 token、输出 token、有效记录率、重试率、延迟和每条合格记录成本,人工复核数量单独记录。若使用检索,embedding 计算和存储另列账目。原文引用 OpenAI 的 Embeddings guide 解释向量表示与搜索用途,并不能由此推导出检索免费或某种检索结构合理。
还要区分两个口径:代码算的是 token 成本分摊,生产选型讨论的却是更广的总成本。人工复核、运维等开销如何折算,原文没有给出完整公式。
用适配层和失败样本,让比较能够持续复用
作者建议在队列 worker 与模型端点之间放一个供应商无关的适配层。它接收 messages、目标输出 schema 和生成设置,统一返回用量、解析结果、延迟和错误类别。业务代码便不必跟着托管 API、自托管服务器或 fallback 路由变化。
数据库也应保存校验后的分流对象和用量事件,避免直接把供应商响应结构当成业务记录。原始响应按客服数据的保留策略处理,评估日志写入前先删去个人信息。
输出端采用窄 schema,拒绝未知值,可选字段明确声明,由确定性的校验器执行检查。如果运行时允许,重试只带简短提示和校验错误,避免再次发送整段对话。
跑完相同工单集后,不能只比较平均值。作者要求查看被拒绝的记录,并按短工单、长历史、紧急维修措辞和物业信息缺失分别检查。一个总体均价很低的候选,可能恰好在紧急工单上表现差。
上线前还应设置最大重试次数、队列延迟预算和人工复核路径,记录 prompt 版本、schema 版本、生效费率、token 用量、校验结果及最终去向。配置或工作负载变化后,旧结果需要重新验证。
我的判断
我赞同把计量单位改成「每条合格记录」。它把重试和拒收造成的浪费暴露出来,比单看 token 单价更接近业务实际。把供应商差异收进适配层,也能降低替换运行时的改造成本。
但这仍是一套方法建议。作者对输入消耗的认识来自自身经历,文中没有给出票量、候选模型、测试结果或对照数据,无法据此认定小模型、大模型、托管或自托管哪种更划算。
另一个需要补上的环节是语义验收。确定性校验器能拦住缺字段和非法标签,却未必知道漏水是否被误判。原文没有交代如何建立人工标注、如何衡量业务正确率。
schema 校验通过,只能作为验收的一部分。
对类别稳定的队列,还可以把规则分类或规则与模型组合列为对照候选。这是站内建议,原文没有提供这类比较。最终选择仍需用同一批样本验证。
能拿来做什么
- 在 Node 工单处理中,把每次请求的输入、输出、重试原因和最终去向关联到同一条工单,先统一累计口径,再计算每条合格记录的成本。
- 为分类和抽取任务固定 schema、标签及校验逻辑,同时准备人工确认的样本,分别检查格式合格率与业务判断正确率。
- 更换模型前,用同一套匿名工单回放,并单独查看长历史、紧急维修和信息缺失样本,避免平均值掩盖问题。
- 给队列设置重试上限和人工接管路径;使用检索时,把 embedding、存储及检索上下文带来的输入消耗分别记账。