作者用个人git提交历史构建评分卡评估新模型,而非依赖官方benchmark。评分维度包括:选择效应、记忆伪装推理、首次印象噪音,三类错误成本不同。
本周发布了一款模型。几小时内截图就铺天盖地:不可能的重构、一次搞定的修复、宣言一切前代皆已过时。我不再和发布周的狂热情绪争辩了。我做了一件更无聊但更有用的事:用我自己 git 历史里提炼出的记分卡给新版模型打分,分数决定这款模型能不能靠近我的工作树。
这和通常"跑个基准测试"的建议完全不同。我不是在跑基准测试。我是在用自己亲身经历过的故障来考核一个候选者——而且是加权评分,因为不同的失败代价并不相同。
我对自己糟糕的模型采纳经历做复盘,错误集中在这三类:
看到的都是筛选过的。公开演示之所以是演示,是因为它成功了。我的代码没有这种过滤。
把记忆当推理。看起来像公开 GitHub 代码的任务,靠记忆就能答上来。我的评估任务必须来自私有历史。
第一印象太吵。一个在空白文件上闪闪发光的模型,可能还是会搞砸一个满是内部约定的成熟模块。第二种情况才是我真正要付费的。
记分卡能解决这三类问题:从私有 PR 里冻结的任务、机械化检查、以及反映爆炸半径而非主观感受的权重。
构建任务套件最快的方式是恢复你已经验证过的工作。我扫描那些小而自包含的修复:
# Candidate commits: single-file changes, small diffs, likely bugfixes
git log --since="-6 months" --name-only --oneline \
| awk '/^[0-9a-f]{7,}/ {sha=$1} /\.[a-z]+$/ {print sha, $0}' \
| sort | uniq -c | awk '$1 == 1 {print}' > candidates.txt
从这份列表中我手工挑选八个事件:一个空值处理的回归、一个后台 worker 的竞态、一个需要回滚路径的迁移、一个缠绕在内部风格指南里的重构。每一个变成:
suite/worker-race/
brief.md # the task, written once, model-agnostic
before.patch # starting state of the code
check.sh # mechanical verification, exit 0 = pass
两条规则保证客观性:每个任务都有一个已知好的解决方案(因为我合并过),而且 check.sh 永远不会被改来迁就某个模型。一份令人困惑的 brief 是任务的缺陷,而不是模型的罪证。
原始通过率会掩盖那些真正造成损失的失败。我给每个任务分配一个权重,反映如果这个类别静默失败会在生产环境造成多大损失,然后让脚本做算术:
#!/usr/bin/env python3
"""grade.py — read results/*.json, emit a weighted verdict."""
import json, glob, sys
# weight = blast radius if this category fails silently
WEIGHTS = {"correct": 1.0, "scope": 3.0, "revertable": 2.0}
def grade(result):
score, total = 0.0, 0.0
for task in result["tasks"]:
total += sum(WEIGHTS.values())
if task["tests_pass"]: score += WEIGHTS["correct"]
if not task["touched_out_of_scope"]: score += WEIGHTS["scope"]
if task["diff_reverts_cleanly"]: score += WEIGHTS["revertable"]
return score / total
for path in glob.glob("results/*.json"):
r = json.load(open(path))
print(f"{r['model']:40s} {grade(r):.2%}")
有意的不对称:作用域纪律权重是正确性的三倍。在我经历的事故历史里,贵的模型行为从来不是"修复是错的"——测试能抓住这个。贵的是"修复是对的,但它还顺手改了两个没人要求改的文件"。一个 91% 但 diff 精准的候选者,排名高于 95% 但四处游荡的那个。权重表才是真正的决策文件;调权重要看自己的事故日志,不是我的。
我还记录每个任务的延迟和 token 消耗,因为"免费"和"便宜"的说法只有在和你的工作负载形状对照时才有意义。
每一对(模型,任务)只在温度为零的情况下尝试一次。重试和重新 prompt 测的是我的耐心,不是模型。运行器是一个很薄的循环:应用 before.patch,通过一个通用封装调用我正在测试的端点,应用返回的 diff,运行 check.sh,然后将一条 JSON 记录写入 results/。换成本周的发布版只是一个环境变量——模型是变量,其他一切保持冻结,这样分数跨周可比。
给每个新发布跑付费 API 评分很快就会累计起来,在第一天自托管一个模型会吃掉你本来想节省的那个小时。在这些评分轮次中我目前用 MonkeyCode,它提供免费访问一批模型的选择,还提供跑手侧的免费服务器选项——完整的八任务评分跑一次花的是我的时间,不是账单。披露:本文是作为 MonkeyCode 产品推广的一部分准备的。
对任何免费层我都会加上的警告,这个也不例外:把它当评估环境用,不是生产承诺,也不要假设托管端点和厂商的参考部署行为完全一致。如果一个候选者通过了,后来要升级到真实使用,我会在生产端点上重新评分——我见过端点差异翻转判决的情况。
高分只是给模型买来一周作为建议模式的助手:它提方案,我逐行阅读,没有东西能自己合并。第二周它可以在低风险路径上开草稿 PR。接近 CI 门控自动合并是更久以后的事,而且永远在必须人工批准之后。记分卡是一个必要关卡,绝不是充分条件。
八个加权任务是一个烟雾测试,不是排名系统。它能淘汰灾难级和四处游荡的候选者,但无法精细区分两个都不错的选择。在做昂贵承诺之前先扩大套件。
单次、温度为零的评分对 agent 循环模型不公平。如果你的工作流是多轮的,建一个冻结的多轮变体——但冻结程度要一样硬。
小或者主要是绿地的仓库损失更少。这套记分卡在大型、老旧、约定繁重的代码库上才物有所值。
数据处理优先。如果代码不能离开你的边界,不要发给任何第三方端点,免费层最不能例外。
下周 Feed 里又会给另一个模型加冕。记分卡不在乎——它花一小时,用权重说话,用我真金白银买过的 bug 做考题。如果你在组装自己的版本,想要一个零成本跑评分的地方,MonkeyCode 的免费模型访问和服务器是一个合理的基准;但 git 历史、checks 和权重必须来自你自己。