用Token账本决定模型路由:60行Python的成本控制术

先记录每次调用的token与路由,再用查表规则决定调用去向。
文章主张多模型成本控制应先记账再路由:用一个约60行的Python脚本,以CHARS_PER_TOKEN=3.6的确定性估算器测算prompt规模,把每次调用的哈希、估算token、路由选择与实测挂钟时间写入JSONL账本,再依据“是否需要严格JSON、是否超出免费路径上限、是否为重试”三个条件查表决定走pinned还是free端点。账本每晚汇总出各组的中位数与p95 token、延迟及重复prompt数量。作者强调估算只用于调用间相对比较而非绝对预算,重试必须走固定模型以保证确定性,并以免费小实例托管路由服务、用冒烟测试和systemd自动重启作为最低韧性保障。
用Token账本决定模型路由:60行Python的成本控制术
多模型调用的成本失控,往往不是因为模型选错了,而是因为调用决策本身从来没有被记录过。一个典型的翻车场景是这样的:脚本为每个变更文件发一个请求,最长的那个文件把prompt撑过了廉价端点的上限,重试循环照常触发,一次代码审查变成了一次账单事件。没有人主动做出这个选择,它只是从一个从不询问"发出去的东西有多大"的for循环里掉了出来。
原作者的解法很朴素:花两天时间停止调prompt,转而给"决策"本身装上仪表。问题从"哪个模型更好"换成"哪一次调用被允许发生",而后者用大约60行Python加一个JSONL文件就能回答。
先记账,再路由
大多数关于路由的建议都从模型质量开始,但对个人项目来说这个顺序是反的——质量是你无法廉价衡量的东西,而调用量是你能衡量的。原作者的主张是:先把每一次调用写下来,再去争论它该去哪儿。

估算器的设计刻意粗糙:确定性、不需要网络往返、对代码文本悲观。核心逻辑是CHARS_PER_TOKEN = 3.6这个经验值,针对混合了散文和代码的prompt。这个选择的价值在于可复现——任何人跑同一段文本都会得到同一个数字,不存在模型侧的随机性。
账本记录里有两个设计细节值得借鉴。一是对prompt做SHA256哈希截断后存储,这样可以在不保留原始prompt的前提下找出重复调用——原作者特意强调,审查用的diff不属于他可以留存的数据。二是wall_s记录的是实测挂钟时间而非估算值,这让免费路径的延迟可以用真实数字评判,而不是凭感觉。
Token估算中CHARS_PER_TOKEN的取法与误差来源
CHARS_PER_TOKEN = 3.6 是一个适用于英文散文与常见源代码的粗略换算经验值:OpenAI的BPE分词器对英文平均约4字符/token,但代码中大量符号、缩进和短标识符会把比例拉低到3.5~3.8。取一个偏小的值意味着估算出的token数偏多,也就是对成本更悲观,这正是设计者刻意选择的方向。
误差会在几类文本上显著放大:压缩后的JSON或minified JS几乎不含空格,字符/token比可低至2.5;中文、日文、韩文等非拉丁文本常常一个字符就要占1~2个token。因此这个数字不能用于与账单对账,只能用于同一脚本内不同调用之间的相对排序——比较“这次和上次哪次更大”是可靠的,断言“这次会花多少钱”则不是。
路由表就是全部设计
路由规则本身没有任何聪明之处:一个基于两个布尔值和一个大小的查表。价值恰恰在于规则被写在了评审者可以反对的地方。
| 条件 | 路由 | 理由 |
|---|---|---|
| 需要严格JSON或固定模型版本 | pinned | schema漂移比成本更糟 |
| 估算token超过免费路径上限 | pinned | diff中途截断会产出静默的垃圾 |
| 其他情况 | free | 这是走量的场景,走量正是免费访问的价值所在 |
| 失败后重试 | pinned | 重试不是实验,为确定性付费 |
表中最后一行是原作者最愿意为之辩护的:用不同的采样结果重试,那不是重试,是第二次实验,而实验就应该被标记为实验。
这个表格也解释了为什么"先记账再路由"是必要的。没有账本,你无法知道免费路径的上限该设在哪,也不知道哪些调用其实是在重复。
pinned与free两类端点的工程含义
pinned指请求被固定绑定到某一个明确的模型版本或供应商端点,不接受服务端的自动降级、采样参数漂移或版本滚动;free指依赖免费额度或免费层访问的端点,通常带有速率限制、额度上限、实例休眠或模型版本随时变更等不确定性。两者的差异不只是价格,而是可预期性:pinned路径的输出可以复现、schema可以信任,free路径则适合承接那些即使结果波动也无所谓的走量调用。路由表之所以能用两个布尔值加一个阈值表达,是因为它把“这次调用能否容忍不确定性”这一个问题拆成了结构约束、规模约束和失败处理三个可判定的条件。
两天的流量长什么样
仪表如果不读,就只是磁盘占用。原作者每晚跑一次汇总脚本,输出的是按路由分组的分布:每组的中位数token、p95 token、中位数延迟,外加一个哈希统计出的重复prompt数量。
重复计数是原作者没料到会关心的数字。重复的prompt在任何层级上都是纯浪费,免费与否都一样,而在你对prompt做哈希之前,这些重复是完全隐形的。
值得一提的是原作者对数据披露的克制:他明确拒绝公布自己两天窗口里省下的百分比,理由是"单个仓库单个周末不构成证据,引用它就等于引用一个没人能复现的benchmark"。他的立场是——脚本才是论点,把它跑在你自己的流量上,数字一晚上就出来了。这种态度在动辄宣称"节省80%成本"的AI内容里相当少见,也更可信。
在小免费实例上跑路由服务
路由服务本身几乎不做事——一个文件、一个端口、没有数据库——这使它成为小实例而非付费实例的合理候选。原作者提到了MonkeyCode的免费模型访问和免费服务器选项,工作流依赖这两块:免费路径承接走量的调用,免费实例托管账本服务。
需要说明的是,这是一篇带有产品推广性质的文章,原作者对此做了披露。他的处理方式是:把免费额度和免费服务器都当作"运营方提供的可用性声明",在自己的环境里验证后才信任。具体做法是第0天就做冒烟测试而不是第30天——用20次并发请求打一遍路由端点,统计HTTP状态码和响应时间,再用systemd的Restart=on-failure作为唯一的韧性承诺,配合journalctl -f观察突发流量下的表现。如果免费实例会休眠,你会在wall_s里先看到它,而不是在账单上。
冒烟测试与systemd的Restart=on-failure
冒烟测试指在系统正式投入使用前,用少量真实请求打通关键路径、确认基本可用性的验证手段,这里具体化为用20次并发请求打路由端点并统计HTTP状态码与响应时间,目的是在部署当天而非运行一个月后才发现免费实例的限流或冷启动问题。Restart=on-failure是systemd服务单元的一项配置,表示进程以非零状态退出或被信号杀死时由systemd自动重启,它不处理挂起或假死,因此需要配合journalctl -f实时跟踪日志来观察突发流量下的真实行为。二者组合构成了一套“最低成本韧性承诺”:不保证服务永远可用,只保证崩溃后能自动拉起且过程可观测。
踩到的坑与值得复用的部分
坏消息是可预测的:估算器对长diff的过度计数严重到把中等规模的prompt推上了pinned路径,而最初的上限设得太低。靠眼睛调高不是修复——真正的修复是读免费路由的tokens_median和p95,把上限设在你实际发送量的95分位。
值得复用的是那个顺序:先账本,再路由,最后部署。反过来做,你会得到一个无法审计的路由策略和一台不敢重启的服务器。
原作者还坦白了两条局限。字符数估算的token在压缩文件和非拉丁文本上误差很大,所以别用它做预算,只用来在调用之间做相对比较。以及这套设计完全不涉及答案质量——它决定调用去哪里,不决定答案好不好。
至于谁应该跳过这套东西:有延迟SLA的人、diff不能出内网的人、以及流量小到账本耗费的注意力超过调用本身花费的人。如果你属于其中任何一类,硬编码单一端点才是正确的工程选择。
这套方案的说服力不在代码量,而在它把一个模糊的成本焦虑拆成了可记录、可查表、可审计的三步。对于任何在多个端点之间手动切换的个人开发者来说,先把账本建起来,剩下的决定会自己变得清晰。
为什么用p95而非平均值设定阈值
p95指把所有观测值排序后位于第95百分位的那个数值,意味着95%的调用不超过它。相比平均值,p95不会被少数极小值拉低,也不会被极端离群值主导,能更真实地反映“绝大多数情况下会发送多大”的prompt。原作者最初的教训正是阈值设得过低,导致估算器对长diff的过度计数把中等规模prompt推上pinned路径;改用实际发送量的tokens_median与p95来定位上限,相当于让阈值由观测数据而非主观感觉决定。这一做法也适用于延迟指标:免费路径的wall_s用p95而非均值评判,才能看出休眠或限流造成的长尾。
相关推荐

AI数字分身实战:用DOT自动追踪Bug与用户反馈
DOTS 团队工程师演示如何用 AI 数字分身 DOT 跨平台收集用户反馈、自动归类问题主题、开线程调查 Bug 根因并直接提交 PR,展示 AI 代理参与缺陷分诊的完整工作流与可审计设计。

晶体管为何不再扁平?从平面到环绕栅极的演进
晶体管从平面到FinFET再到环绕栅极的演进:为何栅极需要从三面包裹到四面环绕,以抑制短沟道效应和泄漏电流,延续摩尔定律。

蜂群思维=单个RL智能体?多臂老虎机等价性证明
一篇论文证明蜂群通过局部模仿进行的集体决策,在数学上等价于单智能体强化学习。N个盲目模仿者相当于N个并行环境采样,有效学习率为1/N。本文解读Maynard-Cross Learning算法的推导与影响。