使用 Claude 自动化评估设计与爬山优化
设计评估并针对其进行爬山优化而不自欺的原则,以及 claude-api 技能的 build-eval 和 hillclimb 命令如何将这些原则付诸实践。
评估可以提供信号,表明你的应用或技能在特定任务上的表现如何。但设计评估,并在不自欺欺人的前提下提升其上的表现,是件难事。我们已在 claude-api skill 中为这两方面都添加了指导。
借助该技能,你可以运行 /claude-api build-eval 在代码库中构建一个评估,然后运行 /claude-api hillclimb 针对它来改进你的应用,每次只做一处改动,并使用一组留出的样例来捕捉过拟合。
在本文中,我们首先阐述良好评估设计与爬山法的原则,然后展示 Claude Code 如何结合 claude-api 技能应用这些原则。最后,我们会展示几个这些命令的示例。
评估设计
设计良好的评估有几个共同要素(图 1):
- 评估任务应与生产环境一致。采样你在“生产环境”中关心的任务,也就是你所测试的能力或应用将被使用的场景。有时任务被选中是因为它们易于生成或易于评分。但重要的是要确保任务分布代表你真正关心的内容。
- 性能随更强的模型和更多思考而提升。能力更强的模型和 更高的努力程度 通常应在评估中表现更好。如果并非如此,往往是含糊不清的任务或校准不当的评分器在拖累表现。
- 在前沿水平上存在“及格”空间。在最高努力程度下,最强的模型在评估中的得分应远低于 100%,否则你就无法可靠地判断改动对性能的影响。重要的是,这一差距不应由不可能或含糊的任务来解释:一个常见的迹象是某个任务无论重复多少次,每次评估都失败。好的任务是两位领域专家会得出相同结论,且评分器检查的所有内容都在任务中明确说明的任务。
- 运行间方差低。高方差通常源于设计不佳、含糊不清的任务,或评分器对相同输出给出不同判定。方差也可能隐藏在配置中。例如,努力程度可能未被一致地应用。此外,环境也会影响评估结果:先前试验的残留状态(一个文件、一段 git 历史)可能会把答案直接递给智能体。
按消耗的 token 计分
三种模型规模在三种努力设置下,示意图
针对较小、中等和最强模型在低、中、高努力程度下,每次尝试的动作 token 数进行计分。编号标注指出了四个要素:随着模型能力增强和努力程度提高,分数上升;顶部线条保持在满分以下;误差棒保持紧凑。
对抗性采样
模型能力是参差不齐的。如果你因为当今模型会失败而挑选案例,你采样到的是某个模型能力曲面的低谷(图 2)。评估最终可能衡量的是该模型的失败特征,而非对你的应用而言本质上困难或有价值的内容。
选择困难案例,因为有人类判断它们困难:一个有用的测试是在纳入之前能够说明某项任务为何困难。纳入那些源自生产流量、错误报告或工单的、你应用中的具体失败案例。然而,不要盲目信任用户流量:用户有时会尝试他们期望能奏效的操作,因此严格从用户流量中得出的任务分布可能会偏向简单。
/CLAUDE-API BUILD-EVAL
claude-api 技能中的 build-eval 命令将这些原则转化为一个引导式工作流。当你在 Claude Code 中运行 /claude-api build-eval 时,Claude 会对你进行访谈,在你的代码库中构建评估,并在特定节点暂停以等待批准。
设计示例
Claude 按以下顺序帮助你采样输入以构建评估:
- 生产记录,在询问数据保留和敏感数据之后。
- 错误报告和支持工单。
- 你手写的五到十个案例。
- 从你的代码库中合成的案例。
该技能优先考虑生产流量,但它也可以基于你提供的几个真实示例生成合成数据。该技能指示 Claude 生成一个简单页面,向你展示每一个输入,并在你确认之前一直等待。作为示例,下面我们展示了一个电子邮件路由应用的输入示例集,该技能可能会要求用户进行审阅(图 3)。
验证评分器
在输入之后,Claude 会提出最适合你应用输出的最经济的评分器:
- 程序化验证:如果输出的可能性是受限的,它会使用基于代码的检查(精确匹配、来自固定集合的标签、符合 schema 的 JSON、通过的测试)。
- LLM 即评委:如果输出空间是开放式的,存在许多有效答案但有明确的质量标准,它将默认使用这种类型的检查。在这种情况下,第二个模型会读取输入、输出以及写成可检查断言(而非 1 到 5 分制)的评分标准,并返回一个分数及其推理过程。如果你有基线可以比较,评委则会以随机顺序读取两个输入,且不被告知哪个是基线,并选出更好的一个。你来选择评委模型,它不应该是你正在测试的模型。
Claude 会为少数几个案例评分,并询问你是否会对其中任何一个给出不同的评分(图 4)。通常,在相信你的评估器之前,阅读一些已评分的记录样本非常重要;评分失败是评估配置错误最常见的原因之一。
当你验证了评分器后,该技能会告诉你评估集的大小(案例数 × 重复次数 × 模型,以及大约需要多长时间),运行基线,并打印出带有置信区间的分数。你得到的内容包括:案例、评分器、运行器、每个案例一行 JSON 和一份完整记录,以及一个列出每个案例分数并链接到其记录的普通页面。如果你想要的内容超出该页面的显示范围(例如图表),只需提出要求,Claude 就会将其构建为旁边的额外页面。默认情况下,这些额外页面是静态文件,在本地打开,不从网络加载任何内容。
诊断检查
在上述基线运行期间,Claude 会检查多项内容:
- 评分器:Claude 对同一输出运行两次评分器,并报告结论是否发生了变化。
- 管道检查:Claude 会检查超时、API 错误和被截断的回答,以确保基础设施噪声不会被误认为是模型方差。
- 提升空间:如果基线得分已达到约 95% 或更高,该技能会警告用户,并提示爬山优化应着眼于探索成本或延迟,而非质量。
爬山优化
既然你已经有了可靠的手段来评估应用在某项任务上的表现,就可以尝试改进它了。爬山优化是调整 effort 或提示词等参数的有效方式,这些参数在成本与性能之间进行权衡。以下是一些选择优化方向的通用建议:
- 迭代成本低——修改你用于爬山优化的任何对象,在时间、成本和精力上都应当是廉价的。许多内部工作和客户都聚焦于对文本进行爬山优化,例如提示词和技能。这些内容易于修改和回滚。相比之下,在爬山优化过程中对 agent harness 进行开放式修改可能涉及大量代码变更。
- 可归因——评估得分的变化应当能够归因于你在爬山优化过程中所修改的对象。例如,多次成功的爬山优化应用都聚焦于 技能触发。评估指标(该技能的触发率)与正在被修改的技能描述直接耦合。
- 目标范围明确——一种常见的失败模式是,在未仔细考虑评估中可用提升空间的情况下,提出开放式提升性能的请求;接近饱和的评估或范围界定不佳的对象(例如,更新 harness 的开放式请求)更容易停滞不前。在各种工作中,一个普遍有效的目标是成本:即使评估已饱和,你也可以要求 Claude 寻找降低成本的方法,同时保持性能持平。
过拟合
即使设计良好的评估,也很少与你在生产环境中关心的确切任务分布完全匹配。因此,对评估“过拟合”是一个常见问题,会导致系统在评估上的表现优于生产流量。
评估有许多方式可以“泄漏”到你的 harness 中(即模型周围的代码,包括提示词、工具和调用 Claude 的循环)。例如,考虑一个受益于 OCR 的评估任务,但 OCR 在你的生产任务中很少有用。评估 harness 可能会为你的应用添加一个 OCR 工具,这能在基准测试上带来提升,但对生产毫无影响。更广泛地说,爬山优化可能会向该 harness 添加功能,以处理你所选特定评估示例中的边缘情况。这些 harness 的增补提升了你的评估得分,但无法转化为生产环境的改进(图 5)。
有三件事可以帮助解决这个问题:
- 划分用例。使用爬山优化器可以读取的训练集,以及一个从未被看到的测试集。如果训练集得分提高而测试集得分保持不变,那就是一个常见的过拟合警示信号。
- 绝不要将失败内容粘贴到提示词中。如果爬山优化器读取了失败的对话记录,它绝不能将失败内容粘贴到提示词中。
- 将答案从结构上置于模型无法触及的位置。模型有时会通过直接寻找评测答案来进行“奖励作弊”。
正如后文所述,claude-api 技能会为你应用这些原则。
/CLAUDE-API HILLCLIMB
claude-api 技能中的 hillclimb 命令将这些原则转化为引导式工作流。当你在 Claude Code 中运行 /claude-api hillclimb 时,Claude 会针对给定的评测进行迭代改进。你可以选择它能做出的更改,包括:
- 你的系统提示词
- 技能或指令文件
- 工具描述
- 模型选择、努力程度及其他 API 参数
- 你的框架代码
在开始之前,Claude 会询问你想要优化什么(例如性能,或在性能保持不变的情况下优化成本),然后将评测集随机划分为测试集和训练集。对于成本目标,它会考虑 几个常见的成本驱动因素,包括提示词缓存、审查提示词与所选模型的兼容性,以及选择模型和努力程度设置。
在第一轮之前,Claude 会检查评测的噪声(分数仅凭偶然可能波动的幅度)是否小于你愿意采取行动的最小改进幅度;如果不是,它会说明这一点并建议增加重复次数或案例。
每一轮,Claude 都会读取上一轮的训练记录,并以补丁形式提出一项更改。它每一轮都瞄准一项效果能超出评测噪声的更改:它从根源上修复失败行为(例如,重写导致问题的部分或添加缺失的规则),而不是改写某一行。然后它会运行带有该补丁更改的评测。此时,Claude 会应用一项检查:如果 train 集有所改善但 test 集持平,Claude 会怀疑过拟合并回滚该补丁。如果出现回退,Claude 会回滚。如果训练集和测试集都有改善,它会保留该补丁(图 6)。
当分数停滞两三轮时,Claude 会读取每个剩余的训练失败项并按原因排序。如果没有单一修复能带来超过评测噪声的提升,它也会提前做同样的事,并建议增加重复次数或案例,而不是把轮次花在小到无法测量的更改上。这一步可以发现有歧义的评测案例、框架错误或运行间的差异。
只有合理的失败才会被纳入更多的爬山轮次。
当爬山过程完成后,Claude 会将你的代码保留在针对你的目标在测试集上表现最好的版本。它会报告相对于基线的测试结果及置信区间(图 7)。如果增益在噪声范围内,它会说明这一点并建议不要合并。
示例
用于降低成本的爬山优化
我们在一个 内部客户支持基准 上运行了 /claude-api hillclimb,目标是降低成本并提升性能。该基准包含 44 个工单,其中 30 个用于搜索,14 个留出。它从 Opus 4.8 的默认(高)努力程度设置开始,在搜索工单上的决策准确率为 74.4%,每个工单的 token 成本为 4.6 美分。
hillclimb 首先审查了提示词,移除了强制性的工具调用仪式、草稿板步骤和相互矛盾的规则。然后它尝试了低努力程度的 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.6 美分,Opus 5.5 低努力配合审核过的提示词为 87.8% 和 1.9 美分,Sonnet 5 低努力配合相同提示词为 88.9% 和约 1 美分,Sonnet 5 配合改进后的提示词为 98.9% 和约 1 美分。虚线标示了 74.4% 的起始准确率。
最后,Claude 通过添加路由规则和退款上限交叉引用改进了提示词,使 Sonnet 5 在成本大致相同的情况下达到 98.9%。在搜索从未见过的 14 个留出工单上,最终配置得分为 90.5%,而原始设置为 78.6%,成本约为其五分之一。
以性能为导向的爬山搜索
另一个例子是我们的 claude-api 技能,它提供了使用我们 API 的指南以及与 Claude 协作的通用技巧(包括本文讨论的子命令)。我们希望确保我们的技能能够正确实现使用我们 API 的代码,因此我们基于文档构建了一个评估集来测试该技能。
在我们的评估中,该技能的起始分为 66%。我们让爬山搜索器可以访问文档和我们的 SDK,使 Claude 能够识别错误并自我纠正(图 9)。Claude 发现该技能缺少对八项功能的覆盖。
在技能中添加这些部分后,性能提升至 74%。随后它发现了 C# 和 Java 类型表中的错误,将性能提升至 77%。
claude-api 技能评估
三个工作阶段内从 66.1% 提升至 87.9%
claude-api 技能评估中各轮爬山搜索的通过率,从基线的 66.1% 上升到第 24 轮的 87.9%。三个编号阶段标示了工作内容:添加缺失的部分和类型表,然后修复技能指示 Claude 编写代码的方式,最后修复评分器以及更多技能编辑。
在分数停滞两轮后,Claude 分析了剩余的失败并按根本原因进行了分类。普通轮次会针对最常见的失败进行一次编辑。这一步不进行任何编辑;它只是将每个剩余的失败按原因排序。这个反思步骤在几个方面很有用:
- 通过反思一系列失败,爬山搜索器发现技能内容是存在的,但 Claude 只是在编写较旧的 API 形式(例如,来自其训练先验)。为了解决这个问题,爬山搜索器在技能顶部附近添加了一个表格,引导 Claude 从它记住的形式转向当前的形式:例如,从固定 token 预算的扩展思考(API 现在在最近的 Opus 模型上会拒绝这种形式)转向自适应思考,以及从旧版本的网页搜索和网页抓取工具转向当前版本。它还将针对固定预算思考的 C# 和 Java 警告移到了自适应思考示例之上。这将性能提升至 80%。
- 那些尽管解决了明显内容缺口却从未在性能上有所改善的任务,表明示例或评分器存在缺陷。有一个任务要求编写能捕获一种错误类型的代码,但其评分器却要求至少三个错误类型的链式处理。Claude 对任务进行了重新措辞。另一个评分器的说明与我们的文档相矛盾,测试真实 API 后发现文档才是正确的。解决这些问题,加上更多的技能修改,使性能提升到了约 88%。
入门
注意:请先运行 claude update。claude-api 技能随 Claude Code 一起发布,因此更新后即可获得这些命令的最新版本。
代码Shell
claude update然后,在 Claude Code 中:
提示
/claude-api build-eval /claude-api hillclimb
这些子命令可以直接在 Claude Code 中通过 claude-api 技能 使用:
如果你想为特定问题生成评估集,请运行 /claude-api build-eval。你可以通过提供示例(例如追踪记录)的访问权限来引导它。Claude 将运用本文分享的指导原则来设计示例和评分器,并确保你批准这些示例和评分器。
如果你已有评估并希望 Claude 在此基础上改进,请运行 /claude-api hillclimb,由你的目标引导(例如,更好的性能,或在保持性能的同时降低成本)。Claude 将运用本文分享的指导原则,在提升过程中检查过拟合,并检查评估本身是否存在缺陷,例如评分器将看似正确的答案判为错误,或测试框架出错,这些检查会在第一轮之前以及每次分数停滞时进行。
特别感谢 Misha Khalman 在技能开发方面的工作。感谢 Misha Khalman、Michael Segner、Matt Bell、Matt Thanabalan 和 Punit Shah 的审阅、贡献和产品支持。