用 Claude 自动化设计评估与爬山优化
如何设计评估、如何针对评估做爬山优化而不自欺欺人——这是几条原则,以及 claude-api 技能中的 build-eval 和 hillclimb 命令如何把它们落到实处。
评估能告诉你,你的应用或技能在特定任务上表现如何。但设计评估、并在评估上提升表现而不自欺欺人,是件难事。我们在 claude-api 技能里为这两件事都加了指导。
用这个技能,你可以运行 /claude-api build-eval,在代码库里搭一套评估;再运行 /claude-api hillclimb,一次只改一处,针对评估慢慢提升你的应用,同时用一组留出的样本(held-out set)来发现过拟合。
本文先讲评估设计和爬山优化的原则,再展示 Claude Code 配合 claude-api 技能如何落实这些原则,最后给出这几个命令的几个示例。
评估设计
设计得好的评估,通常有几个共同点(图 1):
-
评估任务要贴近生产环境。 抽样要来自你真正在意的“生产”任务,也就是你要测试的能力或应用实际会被使用的场景。有时任务之所以被选中,只是因为好生成或好打分。但务必确保任务分布反映的,是你真正在意的那些任务。
-
模型更强、思考更多,表现就该更好。 能力更强的模型、更高的推理投入,通常应在评估上拿到更好的成绩。如果相反,往往说明任务本身含糊,或者打分器校准出了问题,拖了后腿。
-
在前沿水平上要留有“可通过”的余量。 最强的模型、最高的投入,在评估上的成绩应当明显低于 100%,否则你无法可靠地判断改动的效果。重点是,这个差距不应来自“不可能”或含糊的任务:一个常见征兆是某个任务无论重复多少次、跑多少轮都失败。好的任务,是两位领域专家会得出同样判断,而且打分器检查的每一项都在任务里说清楚了。
1. 多次运行结果稳定
方差大,往往是任务设计得不好、含糊不清,或者评分器对相同输出给出不同判断。方差也可能藏在配置里,比如每次投入的算力/努力程度并不一致。环境同样会影响评测结果:上一次试验残留的状态(一个文件、一段 git 历史)可能直接把答案喂给 agent。

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

图 2 对抗采样
要挑难题,就得由人来判断它难在哪:一个有用的检验标准是,在把某个任务纳入评测之前,你能说清楚它为什么难。还要把你应用里真实出现过的失败案例收进来,这些案例来自线上流量、bug 报告或工单。不过别盲目相信用户流量:用户有时只尝试他们预计能用的功能,所以严格按用户流量抽出的任务分布可能偏简单。
/CLAUDE-API BUILD-EVAL
claude-api 技能里的 build-eval 命令,把这些原则变成了一套有引导的工作流。在 Claude Code 中运行 /claude-api build-eval,Claude 会先向你提问,再在你的代码库里把评测搭起来,并在几个关键节点停下来等你确认。
设计测试用例
Claude 会按下面的顺序帮你采样输入、构建评测:
-
生产环境的对话记录(前提是先确认数据留存情况和是否含敏感信息)。
-
Bug 报告和客服工单。
-
你手写的五到十个用例。
-
根据你的代码库合成的用例。
技能会优先用真实的生产流量,但也能以你提供的少量真实用例为基础,生成合成数据。技能会指示 Claude 生成一个简单页面,把所有输入展示出来,必须等你确认后才继续。下面是一个示例:对于邮件路由应用,技能可能会让用户审核这样一组输入(图 3)。

图 3:技能生成的示例输入审核页
验证评分器
确定输入之后,Claude 会根据你应用的输出来推荐最省钱的评分方式:
-
程序化验证:如果输出可能是有限的几种,就用代码检查——精确匹配、从固定标签集中取值、符合 schema 的 JSON、能通过的测试。
-
大模型充当裁判(LLM-as-judge):如果输出是开放式的——答案很多但质量好坏有明确标准——默认用这种检查。具体做法是让第二个模型读取输入、输出和一份评分标准,标准写成一条条可核查的声明(不是 1 到 5 分的打分表),然后返回分数和判断理由。如果你有基准可以对比,裁判会改为同时读两个输出,顺序随机,且不告诉它哪个是基准,由它选出更好的那个。裁判模型由你来选,而且不能是你正在测试的那个模型。
Claude 会给若干用例打分,然后问你,这些用例里有没有你觉得该打别的分的(图 4)。一般来说,在相信某个评估器之前,先抽一些已评分的转录看一看,这很重要——评分环节出问题,是评估配置出错最常见的原因之一。
验证完评分器之后,这项技能会告诉你评估集的规模(用例数 × 重复次数 × 模型数,以及大概要跑多久),运行基线,并输出分数和置信区间。你会拿到这些东西:用例、评分器、运行器,每个用例一行 JSON 加一份完整转录,还有一个朴素页面,列出每个用例的得分,并附上对应转录的链接。如果你想要的比这一页多(比如图表),直接开口就行,Claude 会在旁边再生成一个页面。默认情况下,这些额外页面都是静态文件,本地打开,不联网加载任何内容。

图 4 结果页面示意图,为每条输入附上了建议评分。
诊断检查
在上面提到的基线运行过程中,Claude 会检查几件事:
-
评分器:对同一份输出,Claude 会跑两次评分器,报告判定结果有没有变化。
-
底层管道:Claude 会检查超时、API 错误和回答被截断的情况,确保基础设施的噪音不会被误判成模型本身的波动。
-
提升空间:如果基线得分已经达到 95% 左右甚至更高,这项技能会提醒用户,并提示爬山优化应该把重点放在探索成本或延迟上,而不是质量。
爬山法
现在你已经有了一套可靠的办法,来评估应用在某个任务上的表现,接下来就可以试着改进了。爬山法(hillclimbing)是调节参数的有效手段,比如 effort 或 prompt,这些参数本质上是在成本与性能之间做权衡。至于该把爬山法用在哪里,下面是一些通用建议:
-
迭代成本低:调整优化对象时,花费的时间、金钱和精力都要尽可能少。很多内部项目和客户都选择在文本层面做渐进优化,比如提示词和技能,因为这些改起来容易,回退也方便。相比之下,如果在渐进优化过程中大改智能体的执行框架,就可能牵扯大量代码修改。
-
变化可归因:评估分数的变化,应该能追溯到你在优化过程中所改动的那个部分。举个例子,有几次成功的渐进优化,重点都放在技能的触发机制上,评估指标(技能的触发率)直接和正在修改的技能描述挂钩。
-
目标范围要明确:一种常见的失败模式是,提出一个开放式的性能提升要求,却没有认真评估还有多少提升空间。如果评估本身已经接近饱和,或者优化对象界定不清(比如笼统地说要改执行框架),就很容易卡住。一个普遍有效的目标其实是成本:即便评估已经饱和,你仍然可以让 Claude 想办法在保持性能不下降的前提下降低成本。
过拟合
即便评估设计得很好,也很难和生产环境中真正关心的任务分布完全吻合。因此,系统很容易“过拟合”评估,结果就是在评估上表现很好,到了生产流量上却不行。
评估结果“泄漏”进执行框架(即围绕模型的代码,包括提示词、工具,以及调用 Claude 的循环)的方式有很多。举一个例子:假设某个评估任务用 OCR 能加分,但在你的生产任务里,OCR 基本派不上用场。评估的执行框架可能因此给应用加上一个 OCR 工具,评估分数是上去了,生产环境却毫无变化。更普遍地说,渐进优化可能会往执行框架里加各种功能,专门应对你所选的评估样本中的某些边缘情况。这些新增功能提高了评估分数,却没有转化为生产环境的改进(图 5)。

图 5:harness 过拟合的常见原因。
有三个办法可以应对:
-
拆分样本。 准备两个集合:训练集可以让爬山器读取,测试集则永不暴露。如果训练集分数上涨、测试集分数却原地不动,这就是过拟合最常见的预警信号。
-
永远不要把失败案例粘贴进 prompt。 爬山器可以读失败的对话记录,但绝不能把失败内容直接塞进 prompt。
-
从结构上让答案远离模型。 模型有时会「奖励作弊」——直接找到评测的答案。
下面会讲,claude-api skill 已经把这些原则都落实好了。
/CLAUDE-API HILLCLIMB
claude-api skill 里的 hillclimb 命令把这些原则变成了一个有引导的工作流。在 Claude Code 里运行 /claude-api hillclimb 后,Claude 会针对给定评测反复迭代改进。你可以指定它允许改动哪些东西,包括:
-
system prompt
-
skill 或指令文件
-
工具描述
-
模型选择、effort 等级和其他 API 参数
-
harness 代码
开始之前,Claude 会问你优化目标是什么(比如性能,或者在性能不掉的前提下压低成本),然后随机把评测集拆成测试集和训练集。如果目标是降成本,它会考虑几个常见的成本大户,包括 prompt 缓存、检查 prompt 与所选模型是否兼容、挑选合适的模型和 effort 设置。
第一轮开始前,Claude 会检查评测的噪声(单靠随机波动,分数能有多大起伏)是否小于你愿意采纳的最小改进幅度;如果噪声太大,它会指出来,并建议增加重复次数或样本量。
每一轮,Claude 读取上一轮的训练对话记录,提出一处修改,以补丁形式提交。每次只针对一个能在评估噪声之上看出效果的改动:从根源上修复失败行为(比如重写导致问题的段落,或补上缺失的规则),而不是换句话说说。随后,它在打上补丁的状态下跑一次评估。这时 Claude 会做一次判断:如果训练集得分提高而测试集原地不动,它就怀疑出现了过拟合,撤销补丁;如果分数退步,也撤销。只有训练集和测试集都提升,才保留该补丁(图 6)。

图 6:爬山法所用的流程。
当分数连续两三轮停滞,Claude 会读取训练集中每一个尚未解决的失败案例,按原因归类。如果没有任何单一修复能带来超过评估噪声的收益,它也会提前做这一步,并建议增加重复次数或用例数,而不是把轮次浪费在太小、量不出来的改动上。这一步能发现含糊的评估用例、测试框架的错误,或者每次运行之间的方差。
只有合理的失败才会进入后续爬山轮次。
爬山结束后,Claude 会把你代码留在测试集上对目标表现最好的那一版。它会报告测试结果与基线的对比,并给出置信区间(图 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)。

图 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%。

图 9 以提升表现为目标的爬山过程。
分数连续两轮停滞之后,Claude 分析了剩余的失败案例,并按根因给它们分了类。普通的一轮只针对最常见的失败做一处修改;而这一步不做任何修改,只是把每一个剩余失败按原因归类。这个反思步骤在几个方面都很有用:
-
在成批失败案例上做反思时,爬山器发现技能内容其实已经写了,问题出在 Claude 写的是旧版 API 的形态(比如来自它训练时的先验)。为解决这一点,爬山器在技能靠前的位置加了一张表,引导 Claude 从它记住的形式迁移到当前形式:例如,从固定 token 预算的扩展思考(extended thinking)改到自适应思考(adaptive thinking)——前者在最新的 Opus 模型上已被 API 拒绝;再从旧版的网页搜索和网页抓取工具换到当前版本。它还把 C# 和 Java 中反对固定预算思考的警示,移到了各自自适应思考示例的前面。这一步把通过率提升到 80%。
-
有些任务明明补上了明显的内容缺口,性能却始终不涨,这通常说明示例或评分器本身有问题。比如有个任务要求写出能捕获某一类错误的代码,可它的评分器却要求至少捕获三类错误串成的链条,Claude 只好把任务描述重新改写。还有一处评分器的指令和我们自己的文档对不上,实测真实 API 后确认文档才是对的。把这些修好,再补上一些技能层面的调整,性能就到了约 88%。
如何上手
下面这些子命令可以在 Claude Code 里通过 claude-api 技能直接调用:
想为某个具体问题生成一套评估集,运行 /claude-api build-eval。你可以把示例(比如 trace 调用记录)喂给它来引导方向。Claude 会按照本文的思路设计示例和评分器,并确保最终由你确认示例和评分器。