作者开源了一套小型路由器方案:对任务类型分类查找历史评测数据,优先用便宜模型,失败才升级到贵价模型,避免为简单任务付高价。
每周都有新的开源或廉价 API 编程模型发布,每周都有人问我应该换成哪个。我用一个小评估框架跑了几个月后的真实答案是:这个问题本身就问错了。没有哪个模型能在所有任务类型上都胜出。能搞定你正则密集型重构的模型,可能把你的 SQL 迁移搞成一团糟,而你一直作为默认项的那个昂贵模型,对于你一半的 prompt 来说可能都是杀鸡用牛刀。
所以我没有挑选一个赢家,而是写了一个小型路由程序:对任务进行分类,查找最便宜的、已证明能在我的代码库上通过该任务类的模型,只有在便宜模型失败时才升级。这篇文章是完整的搭建指南。如果使用免费层级,运行它几乎不花任何成本,大概需要一个小时左右。
单一模型默认配置有两个缺陷:
为简单任务付冤枉钱。 文档字符串生成、简单测试脚手架和样板编辑几乎在任何当前的模型上都能通过。为这些任务支付前沿模型的价格是浪费。
在困难任务上不信任便宜模型。 一些预算模型确实在某个狭窄领域很强(在我的评估框架中,一个免费模型在 TypeScript 类型错误修复上专门打败了付费模型)。你只有通过按任务类别来衡量才能发现这一点,而不是看总体表现。
路由同时解决了这两个问题。它还具有前瞻性:当下周出现闪亮的新模型时,你无需重新争论是否切换——你只需通过相同的评估框架运行它,让路由表自动更新。
不要复制基准测试的类别。从你自己的历史记录中挖掘。我从编辑器日志中提取了最近 300 个 prompt,并将它们聚类成五个类别,覆盖了大约 90% 的使用量:
| 类别 | 示例 prompt |
|---|---|
sql-migration |
重命名列、添加索引、迁移数据 |
fix-typo-lint |
修复 ESLint 错误、拼写错误、格式问题 |
boilerplate-edit |
增删路由、组件声明、import |
ts-type-fix |
修复类型错误、补充类型注解 |
explain-debug |
解释错误信息、调试崩溃日志 |
你的表格会不同。这才是重点——路由器的可靠性取决于分类体系的诚实度。
每个类别需要一些可验证的任务——那些可以通过测试或差异来机械化检查的,而不是凭感觉。我为每个类别保留 6 个任务,放在 tasks/<class>/ 下,每个任务目录包含 prompt.md、起始文件和 check.sh(成功时退出 0)。
评分框架(故意写得无聊的 bash 脚本):
#!/usr/bin/env bash
# score.sh <model-name> — runs every task against one model, writes results.tsv
MODEL="$1"
: "${RESULTS:=results.tsv}"
for task_dir in tasks/*/; do
class=$(basename "$task_dir")
for task in "$task_dir"*/; do
work=$(mktemp -d)
cp -r "$task"/* "$work"/
prompt=$(cat "$work/prompt.md")
# llm_call is your adapter: sends prompt + starter files to $MODEL,
# writes the model's file edits back into $work. ~20 lines of curl/python.
if llm_call "$MODEL" "$prompt" "$work" && (cd "$work" && bash check.sh >/dev/null 2>&1); then
echo -e "$MODEL\t$class\t$(basename "$task")\tpass" >> "$RESULTS"
else
echo -e "$MODEL\t$class\t$(basename "$task")\tfail" >> "$RESULTS"
fi
rm -rf "$work"
done
done
然后构建路由表——每个类别中最便宜的通过模型:
#!/usr/bin/env bash
# route.sh — emits routing-table.tsv: class -> cheapest model with pass rate >= threshold
awk -F'\t' '
{ key=$1 FS $2; total[key]++; if ($4=="pass") passed[key]++ }
END {
for (k in passed) {
rate = passed[k]/total[k]
if (rate >= 0.8) print k, rate # threshold: 80% per class
}
}' results.tsv | sort -t$'\t' -k2,2 -k4,4nr | \
awk -F'\t' '!seen[$2]++ { print $2 "\t" $1 "\t" $3 }' > routing-table.tsv
这里的 sort 代表"按每个类别的成本排序";我维护一个静态的 costs.tsv,将模型映射到相对成本层级(free = 0)并与其连接。免费模型自动赢得所有平局,这就是我想要的行为。
分类不需要机器学习模型。一个 15 行的分类器,使用 prompt 中的关键词启发式方法加上编辑器中的文件 glob 模式,就能覆盖大多数情况(路径中有 .sql 或 migration → sql-migration;prompt 中有 --fix 或 eslint → fix-typo-lint 等)。任何无法分类的都归到默认类别,映射到你最强的通过模型。升级规则:如果路由模型的输出未通过 check.sh(或者你在审查中拒绝了它),用该类别成本阶梯上的下一个模型重试一次,并记录升级。升级日志是信号——一个升级率上升的类别意味着路由模型正在漂移,需要重新评分。
"衡量一切"的问题在于:对 5 个模型 × 30 个任务进行评分,然后每当新模型发布时重新评分,会快速消耗 API 预算。我在 MonkeyCode 上运行这个框架,它提供免费访问一组编程模型和免费服务器选项来运行框架本身——所以整个评估循环(运行器 + 候选模型)对我来说是零成本的,只有在生产路由中才会产生付费 API 调用,而那时调用是合理的。披露: 本文是作为 MonkeyCode 产品推广的一部分准备的。我专门将其用于评估方面;上面的框架是纯 bash 脚本,可以与任何有 API 的提供商一起工作,所以这里没有任何锁定。
如果你想尝试这个,最快的路径是:选择你最频繁的两个任务类别,每个类别写 6 个可验证的任务,然后用一个免费模型对你的当前默认模型进行评分。这样通常会发现一个惊喜。如果你在评估选项,MonkeyCode 的免费模型层级是一个低摩擦的地方,可以从中获取候选模型。
小样本会说谎。 每个类别 6 个任务给你的只是一个粗略的过滤器,而不是置信区间。把通过率当作"足够好到可以路由",每月重新审视一次,永远不要把它们当作基准来引用。
可验证的任务会偏置分类体系。 "解释这个架构决策"没有 check.sh。我的路由器通过始终将主观类别发送到最强模型来处理它们——这意味着节省集中在机械性工作上。没关系,但要清楚你正在优化什么。
分类体系会过时。 新项目、新技术栈、新 prompt 习惯——每隔几个月重新聚类,否则路由器会悄悄地路由到垃圾。
启发式分类会误路由。 我的包含"migration"这个词的解释-调试 prompt 被发送到 SQL 模型一个星期。记录每一个路由决策;你会需要这个审计追踪。
如果你的量很低(每天几个 prompt——就使用你喜欢的模型),如果你的工作主要是新颖设计(没有可重复的任务类别),或者如果你不能为你委托的任何东西写机械检查,就跳过这个。没有验证的路由只是更快的猜测。
每周模型发布的节奏不会放慢,"我应该使用哪个模型"永远不会有一个稳定的答案。"根据我自己的测试,哪个模型应该处理这类任务"会——而且每次你重新运行框架时它都会自动更新。建一次表,让路由表吸收这些变化,然后把你的注意力花在真正需要它的任务上。