用 Claude 自动化设计评估与爬山优化

HN Shipped with Claude 2026-09-29T17:37:40.126910

如何设计评估、如何针对评估做爬山优化而不自欺欺人——这是几条原则,以及 claude-api 技能中的 build-eval 和 hillclimb 命令如何把它们落到实处。

评估能告诉你,你的应用或技能在特定任务上表现如何。但设计评估、并在评估上提升表现而不自欺欺人,是件难事。我们在 claude-api 技能里为这两件事都加了指导。

用这个技能,你可以运行 /claude-api build-eval,在代码库里搭一套评估;再运行 /claude-api hillclimb,一次只改一处,针对评估慢慢提升你的应用,同时用一组留出的样本(held-out set)来发现过拟合。

本文先讲评估设计和爬山优化的原则,再展示 Claude Code 配合 claude-api 技能如何落实这些原则,最后给出这几个命令的几个示例。

评估设计

设计得好的评估,通常有几个共同点(图 1):

  1. 评估任务要贴近生产环境。 抽样要来自你真正在意的“生产”任务,也就是你要测试的能力或应用实际会被使用的场景。有时任务之所以被选中,只是因为好生成或好打分。但务必确保任务分布反映的,是你真正在意的那些任务。

  2. 模型更强、思考更多,表现就该更好。 能力更强的模型、更高的推理投入,通常应在评估上拿到更好的成绩。如果相反,往往说明任务本身含糊,或者打分器校准出了问题,拖了后腿。

  3. 在前沿水平上要留有“可通过”的余量。 最强的模型、最高的投入,在评估上的成绩应当明显低于 100%,否则你无法可靠地判断改动的效果。重点是,这个差距不应来自“不可能”或含糊的任务:一个常见征兆是某个任务无论重复多少次、跑多少轮都失败。好的任务,是两位领域专家会得出同样判断,而且打分器检查的每一项都在任务里说清楚了。

1. 多次运行结果稳定

方差大,往往是任务设计得不好、含糊不清,或者评分器对相同输出给出不同判断。方差也可能藏在配置里,比如每次投入的算力/努力程度并不一致。环境同样会影响评测结果:上一次试验残留的状态(一个文件、一段 git 历史)可能直接把答案喂给 agent。

小、中、最强三种模型在低、中、高三档投入下的得分与动作 token 数对比图。编号标注标出四个要素:模型越强、投入越高,得分越高;最上面那条线也达不到满分;误差棒始终保持很窄。

图 1 好评测的四个要素

对抗采样

模型的能力是参差不齐的。如果你专挑当下模型做不出来的题,采到的其实只是某一个模型能力曲面上的「低谷」(见图 2)。这样测出来的,可能只是这个模型的失败特征,而不是对你的应用来说真正困难或真正有价值的东西。

两个面板展示任务空间中的能力分布。每个面板里,当下的模型是一条锯齿状曲线,下一代模型是位于其上方的更平滑曲线。左图:只挑当下模型失败的案例,全部落在它的低谷区;右图:由人来判断哪些任务难,案例分布在高峰和低谷之间,还包含少量本不该触发的案例。

图 2 对抗采样

要挑难题,就得由人来判断它难在哪:一个有用的检验标准是,在把某个任务纳入评测之前,你能说清楚它为什么难。还要把你应用里真实出现过的失败案例收进来,这些案例来自线上流量、bug 报告或工单。不过别盲目相信用户流量:用户有时只尝试他们预计能用的功能,所以严格按用户流量抽出的任务分布可能偏简单。

/CLAUDE-API BUILD-EVAL

claude-api 技能里的 build-eval 命令,把这些原则变成了一套有引导的工作流。在 Claude Code 中运行 /claude-api build-eval,Claude 会先向你提问,再在你的代码库里把评测搭起来,并在几个关键节点停下来等你确认。

设计测试用例

Claude 会按下面的顺序帮你采样输入、构建评测:

  1. 生产环境的对话记录(前提是先确认数据留存情况和是否含敏感信息)。

  2. Bug 报告和客服工单。

  3. 你手写的五到十个用例。

  4. 根据你的代码库合成的用例。

技能会优先用真实的生产流量,但也能以你提供的少量真实用例为基础,生成合成数据。技能会指示 Claude 生成一个简单页面,把所有输入展示出来,必须等你确认后才继续。下面是一个示例:对于邮件路由应用,技能可能会让用户审核这样一组输入(图 3)。

技能为收件箱路由评测生成的审核页面,包含 24 条输入,逐条列出邮件的文本和 billing、easy、ambiguous 等标签。旁边 Claude 在对话中询问这些输入是否具有代表性,用户回答“是”。

图 3:技能生成的示例输入审核页

验证评分器

确定输入之后,Claude 会根据你应用的输出来推荐最省钱的评分方式:

Claude 会给若干用例打分,然后问你,这些用例里有没有你觉得该打别的分的(图 4)。一般来说,在相信某个评估器之前,先抽一些已评分的转录看一看,这很重要——评分环节出问题,是评估配置出错最常见的原因之一。

验证完评分器之后,这项技能会告诉你评估集的规模(用例数 × 重复次数 × 模型数,以及大概要跑多久),运行基线,并输出分数和置信区间。你会拿到这些东西:用例、评分器、运行器,每个用例一行 JSON 加一份完整转录,还有一个朴素页面,列出每个用例的得分,并附上对应转录的链接。如果你想要的比这一页多(比如图表),直接开口就行,Claude 会在旁边再生成一个页面。默认情况下,这些额外页面都是静态文件,本地打开,不联网加载任何内容。

该技能为 inbox-routing 评估生成的结果页面:基线在 24 个用例上平均正确率 0.681,下方是每个用例的得分表,附有各次重复的链接。点开某个重复的链接会打开该用例的原始 JSON 轨迹,如旁侧所示。

图 4 结果页面示意图,为每条输入附上了建议评分。

诊断检查

在上面提到的基线运行过程中,Claude 会检查几件事:

爬山法

现在你已经有了一套可靠的办法,来评估应用在某个任务上的表现,接下来就可以试着改进了。爬山法(hillclimbing)是调节参数的有效手段,比如 effort 或 prompt,这些参数本质上是在成本与性能之间做权衡。至于该把爬山法用在哪里,下面是一些通用建议:

过拟合

即便评估设计得很好,也很难和生产环境中真正关心的任务分布完全吻合。因此,系统很容易“过拟合”评估,结果就是在评估上表现很好,到了生产流量上却不行。

评估结果“泄漏”进执行框架(即围绕模型的代码,包括提示词、工具,以及调用 Claude 的循环)的方式有很多。举一个例子:假设某个评估任务用 OCR 能加分,但在你的生产任务里,OCR 基本派不上用场。评估的执行框架可能因此给应用加上一个 OCR 工具,评估分数是上去了,生产环境却毫无变化。更普遍地说,渐进优化可能会往执行框架里加各种功能,专门应对你所选的评估样本中的某些边缘情况。这些新增功能提高了评估分数,却没有转化为生产环境的改进(图 5)。

左侧是 benchmark 的各项特征,每项都会给右侧 harness 带来对应改动:需要 OCR 的任务组合会加上 OCR 工具;/app 中的任务会加上「总是 cd /app,运行 pytest」;特殊措辞会得到调优过的 prompt;你读过的失败案例各打一个补丁。虚线箭头标出的是直接泄漏:公开仓库里有答案,harness 可以直接 curl 参考解。

图 5:harness 过拟合的常见原因。

有三个办法可以应对:

下面会讲,claude-api skill 已经把这些原则都落实好了。

/CLAUDE-API HILLCLIMB

claude-api skill 里的 hillclimb 命令把这些原则变成了一个有引导的工作流。在 Claude Code 里运行 /claude-api hillclimb 后,Claude 会针对给定评测反复迭代改进。你可以指定它允许改动哪些东西,包括:

开始之前,Claude 会问你优化目标是什么(比如性能,或者在性能不掉的前提下压低成本),然后随机把评测集拆成测试集和训练集。如果目标是降成本,它会考虑几个常见的成本大户,包括 prompt 缓存、检查 prompt 与所选模型是否兼容、挑选合适的模型和 effort 设置。

第一轮开始前,Claude 会检查评测的噪声(单靠随机波动,分数能有多大起伏)是否小于你愿意采纳的最小改进幅度;如果噪声太大,它会指出来,并建议增加重复次数或样本量。

每一轮,Claude 读取上一轮的训练对话记录,提出一处修改,以补丁形式提交。每次只针对一个能在评估噪声之上看出效果的改动:从根源上修复失败行为(比如重写导致问题的段落,或补上缺失的规则),而不是换句话说说。随后,它在打上补丁的状态下跑一次评估。这时 Claude 会做一次判断:如果训练集得分提高而测试集原地不动,它就怀疑出现了过拟合,撤销补丁;如果分数退步,也撤销。只有训练集和测试集都提升,才保留该补丁(图 6)。

爬山法循环:被修改的对象(如提示词)喂给固定的模型和测试框架,在留出的测试集和训练集上打分。分析器只读取训练集的失败案例,每轮提出一处 diff;当训练和测试都上升时保留该 diff,只有训练上升或任一分数下降时则撤销。

图 6:爬山法所用的流程。

当分数连续两三轮停滞,Claude 会读取训练集中每一个尚未解决的失败案例,按原因归类。如果没有任何单一修复能带来超过评估噪声的收益,它也会提前做这一步,并建议增加重复次数或用例数,而不是把轮次浪费在太小、量不出来的改动上。这一步能发现含糊的评估用例、测试框架的错误,或者每次运行之间的方差。

只有合理的失败才会进入后续爬山轮次。

爬山结束后,Claude 会把你代码留在测试集上对目标表现最好的那一版。它会报告测试结果与基线的对比,并给出置信区间(图 7)。如果提升幅度落在噪声范围内,它也会说明,并建议不要合并。

爬山后的收件箱路由结果页,比较三个变体在训练集和测试集上的得分。变体 v1 为每个队列下了定义并增加了打破平局的规则,在两者上都以 0.875 被评为最佳;变体 v2 增加了两个示例,因训练集上升而测试集持平被撤销。

图 7:爬坡优化后生成的报告示意图 — wait, the image in this段 is FIG 8. FIG 7 is mentioned as text only: "FIG 7 Schematic of the report generated following hillclimbing." That's a caption with no URL. I'll render it as a caption line.

Let me produce output.

FIG 7 的说明文字没有图片 URL,就按文字处理。

Output:

图 7:爬坡优化后生成的报告示意图。

示例

用爬坡优化降成本

我们针对一个内部客户支持基准跑了一次 /claude-api hillclimb,目标是既降成本又提效果。这个基准有 44 张工单,其中 30 张用于搜索、14 张留作验证。起点是 Opus 4.8,用默认(高强度)设置,在搜索工单上的决策准确率是 74.4%,每张工单的 token 成本为 4.6 美分。

爬坡过程先审查了提示词,去掉了强制调用工具的固定套路、一个草稿板步骤,以及互相矛盾的规则。接着它试了 Opus 5.5 的低强度模式。结果准确率达标,为 87.8%,成本降到每张工单 1.9 美分,不到初始成本的一半。

省下来的钱有一部分来自 Opus 5.5 的定价:输入和输出 token 比 Opus 4.8 便宜 20%,缓存读取便宜 60%。由于 Opus 5.5 越过了及格线,爬坡就再降一档,看更便宜的模型能不能也达标。Sonnet 5 在低强度下得分差不多,88.9%,成本约为一半,每张工单 1 美分(图 8)。

训练集上的决策准确率与每张工单成本的对照,展示最终采用的路径:从 Opus 4.8 高强度基线 74.4%、略高于 4 美分,到 Opus 5.5 低强度,再到 Sonnet 5 低强度约 1 美分,最后是改进提示词后的 Sonnet 5 接近 100%。

图 8:以成本为目标的爬坡优化。

最后,Claude 又改进了提示词,加入路由规则和退款上限的交叉引用,让 Sonnet 5 在成本基本不变的情况下达到 98.9%。在搜索阶段从未见过的 14 张验证工单上,最终配置得分 90.5%,而原始设置为 78.6%,成本约为其五分之一。

用爬坡优化提效果

另一个例子是我们的 claude-api 技能,它提供使用我们 API 的指导,以及使用 Claude 的通用技巧(包括本文讨论的那些子命令)。我们要确保这个技能能正确实现调用我们 API 的代码,于是基于我们的文档构建了一套评测集来测试这个技能。

在我们的评测中,这项技能一开始通过率是 66%。我们让爬山器(hillclimber)能访问文档和我们的 SDK,Claude 因此能够发现错误并自行修正(图 9)。Claude 发现这项技能漏掉了八个功能的覆盖。

为它们补上对应章节后,通过率提升到 74%。接着它又发现 C# 和 Java 类型表里的错误,通过率进一步升到 77%。

claude-api 技能评测的各轮爬山通过率,从基线 66.1% 升到第 24 轮的 87.9%。阴影阶段标注了各阶段工作:补充缺失章节与类型表,然后修正技能中指导 Claude 写代码的方式,再修正评分器并做更多技能编辑。

图 9 以提升表现为目标的爬山过程。

分数连续两轮停滞之后,Claude 分析了剩余的失败案例,并按根因给它们分了类。普通的一轮只针对最常见的失败做一处修改;而这一步不做任何修改,只是把每一个剩余失败按原因归类。这个反思步骤在几个方面都很有用:

如何上手

下面这些子命令可以在 Claude Code 里通过 claude-api 技能直接调用:

想为某个具体问题生成一套评估集,运行 /claude-api build-eval。你可以把示例(比如 trace 调用记录)喂给它来引导方向。Claude 会按照本文的思路设计示例和评分器,并确保最终由你确认示例和评分器。

查看原文