跳到正文

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

设计评估并针对其进行爬山优化而不自欺的原则,以及 claude-api 技能的 build-eval 和 hillclimb 命令如何将这些原则付诸实践。

本文目录文章开头
部分图表可能显示不完整

评估可以提供信号,表明你的应用或技能在特定任务上的表现如何。但设计评估,并在不自欺欺人的前提下提升其上的表现,是件难事。我们已在 claude-api skill 中为这两方面都添加了指导。

借助该技能,你可以运行 /claude-api build-eval 在代码库中构建一个评估,然后运行 /claude-api hillclimb 针对它来改进你的应用,每次只做一处改动,并使用一组留出的样例来捕捉过拟合。

在本文中,我们首先阐述良好评估设计与爬山法的原则,然后展示 Claude Code 如何结合 claude-api 技能应用这些原则。最后,我们会展示几个这些命令的示例。

评估设计

设计良好的评估有几个共同要素(图 1):

  1. 评估任务应与生产环境一致。采样你在“生产环境”中关心的任务,也就是你所测试的能力或应用将被使用的场景。有时任务被选中是因为它们易于生成或易于评分。但重要的是要确保任务分布代表你真正关心的内容。
  2. 性能随更强的模型和更多思考而提升。能力更强的模型和 更高的努力程度 通常应在评估中表现更好。如果并非如此,往往是含糊不清的任务或校准不当的评分器在拖累表现。
  3. 在前沿水平上存在“及格”空间。在最高努力程度下,最强的模型在评估中的得分应远低于 100%,否则你就无法可靠地判断改动对性能的影响。重要的是,这一差距不应由不可能或含糊的任务来解释:一个常见的迹象是某个任务无论重复多少次,每次评估都失败。好的任务是两位领域专家会得出相同结论,且评分器检查的所有内容都在任务中明确说明的任务。
  4. 运行间方差低。高方差通常源于设计不佳、含糊不清的任务,或评分器对相同输出给出不同判定。方差也可能隐藏在配置中。例如,努力程度可能未被一致地应用。此外,环境也会影响评估结果:先前试验的残留状态(一个文件、一段 git 历史)可能会把答案直接递给智能体。

按消耗的 token 计分

三种模型规模在三种努力设置下,示意图

针对较小、中等和最强模型在低、中、高努力程度下,每次尝试的动作 token 数进行计分。编号标注指出了四个要素:随着模型能力增强和努力程度提高,分数上升;顶部线条保持在满分以下;误差棒保持紧凑。

图 1良好评估的四个要素

对抗性采样

模型能力是参差不齐的。如果你因为当今模型会失败而挑选案例,你采样到的是某个模型能力曲面的低谷(图 2)。评估最终可能衡量的是该模型的失败特征,而非对你的应用而言本质上困难或有价值的内容。

Two panels plotting capability across task space, each with today’s model as a jagged curve and the next model as a smoother curve above it. On the left, cases sampled where today’s model fails sit only in its valleys; on the right, cases a person judged hard are spread across peaks and valleys, with a few should-not-fire cases.
图 2对抗性采样

选择困难案例,因为有人类判断它们困难:一个有用的测试是在纳入之前能够说明某项任务为何困难。纳入那些源自生产流量、错误报告或工单的、你应用中的具体失败案例。然而,不要盲目信任用户流量:用户有时会尝试他们期望能奏效的操作,因此严格从用户流量中得出的任务分布可能会偏向简单。

/CLAUDE-API BUILD-EVAL

claude-api 技能中的 build-eval 命令将这些原则转化为一个引导式工作流。当你在 Claude Code 中运行 /claude-api build-eval 时,Claude 会对你进行访谈,在你的代码库中构建评估,并在特定节点暂停以等待批准。

设计示例

Claude 按以下顺序帮助你采样输入以构建评估:

  1. 生产记录,在询问数据保留和敏感数据之后。
  2. 错误报告和支持工单。
  3. 你手写的五到十个案例。
  4. 从你的代码库中合成的案例。

该技能优先考虑生产流量,但它也可以基于你提供的几个真实示例生成合成数据。该技能指示 Claude 生成一个简单页面,向你展示每一个输入,并在你确认之前一直等待。作为示例,下面我们展示了一个电子邮件路由应用的输入示例集,该技能可能会要求用户进行审阅(图 3)。

The skill’s review page for an inbox-routing eval with 24 inputs, listing each case’s email text with tags such as billing, easy and ambiguous. Beside it, Claude asks in chat whether the inputs are representative, and the user answers yes.
图 3该技能生成的示例输入审阅

验证评分器

在输入之后,Claude 会提出最适合你应用输出的最经济的评分器:

  • 程序化验证:如果输出的可能性是受限的,它会使用基于代码的检查(精确匹配、来自固定集合的标签、符合 schema 的 JSON、通过的测试)。
  • LLM 即评委:如果输出空间是开放式的,存在许多有效答案但有明确的质量标准,它将默认使用这种类型的检查。在这种情况下,第二个模型会读取输入、输出以及写成可检查断言(而非 1 到 5 分制)的评分标准,并返回一个分数及其推理过程。如果你有基线可以比较,评委则会以随机顺序读取两个输入,且不被告知哪个是基线,并选出更好的一个。你来选择评委模型,它不应该是你正在测试的模型。

Claude 会为少数几个案例评分,并询问你是否会对其中任何一个给出不同的评分(图 4)。通常,在相信你的评估器之前,阅读一些已评分的记录样本非常重要;评分失败是评估配置错误最常见的原因之一。

当你验证了评分器后,该技能会告诉你评估集的大小(案例数 × 重复次数 × 模型,以及大约需要多长时间),运行基线,并打印出带有置信区间的分数。你得到的内容包括:案例、评分器、运行器、每个案例一行 JSON 和一份完整记录,以及一个列出每个案例分数并链接到其记录的普通页面。如果你想要的内容超出该页面的显示范围(例如图表),只需提出要求,Claude 就会将其构建为旁边的额外页面。默认情况下,这些额外页面是静态文件,在本地打开,不从网络加载任何内容。

The skill’s results page for the inbox-routing eval: a baseline scoring 0.681 mean correct across 24 cases, then a table of per-case scores with a link to each repetition. A rep link opens that case’s raw JSON trace, shown alongside.
图 4为每个输入生成建议分数的结果页面示意图。

诊断检查

在上述基线运行期间,Claude 会检查多项内容:

  • 评分器:Claude 对同一输出运行两次评分器,并报告结论是否发生了变化。
  • 管道检查:Claude 会检查超时、API 错误和被截断的回答,以确保基础设施噪声不会被误认为是模型方差。
  • 提升空间:如果基线得分已达到约 95% 或更高,该技能会警告用户,并提示爬山优化应着眼于探索成本或延迟,而非质量。

爬山优化

既然你已经有了可靠的手段来评估应用在某项任务上的表现,就可以尝试改进它了。爬山优化是调整 effort 或提示词等参数的有效方式,这些参数在成本与性能之间进行权衡。以下是一些选择优化方向的通用建议:

  • 迭代成本低——修改你用于爬山优化的任何对象,在时间、成本和精力上都应当是廉价的。许多内部工作和客户都聚焦于对文本进行爬山优化,例如提示词和技能。这些内容易于修改和回滚。相比之下,在爬山优化过程中对 agent harness 进行开放式修改可能涉及大量代码变更。
  • 可归因——评估得分的变化应当能够归因于你在爬山优化过程中所修改的对象。例如,多次成功的爬山优化应用都聚焦于 技能触发。评估指标(该技能的触发率)与正在被修改的技能描述直接耦合。
  • 目标范围明确——一种常见的失败模式是,在未仔细考虑评估中可用提升空间的情况下,提出开放式提升性能的请求;接近饱和的评估或范围界定不佳的对象(例如,更新 harness 的开放式请求)更容易停滞不前。在各种工作中,一个普遍有效的目标是成本:即使评估已饱和,你也可以要求 Claude 寻找降低成本的方法,同时保持性能持平。

过拟合

即使设计良好的评估,也很少与你在生产环境中关心的确切任务分布完全匹配。因此,对评估“过拟合”是一个常见问题,会导致系统在评估上的表现优于生产流量。

评估有许多方式可以“泄漏”到你的 harness 中(即模型周围的代码,包括提示词、工具和调用 Claude 的循环)。例如,考虑一个受益于 OCR 的评估任务,但 OCR 在你的生产任务中很少有用。评估 harness 可能会为你的应用添加一个 OCR 工具,这能在基准测试上带来提升,但对生产毫无影响。更广泛地说,爬山优化可能会向该 harness 添加功能,以处理你所选特定评估示例中的边缘情况。这些 harness 的增补提升了你的评估得分,但无法转化为生产环境的改进(图 5)。

The benchmark’s traits on the left, each shaping a matching addition to the harness on the right: a task mix that needs OCR adds an OCR tool, tasks in /app add “always cd /app, run pytest”, distinctive phrasings get a tuned prompt, and failures you’ve read get one patch each. A dashed arrow marks the outright leak: a public repo with answers lets the harness curl the reference solution.
图 5导致 harness 过拟合的常见原因。

有三件事可以帮助解决这个问题:

  • 划分用例。使用爬山优化器可以读取的训练集,以及一个从未被看到的测试集。如果训练集得分提高而测试集得分保持不变,那就是一个常见的过拟合警示信号。
  • 绝不要将失败内容粘贴到提示词中。如果爬山优化器读取了失败的对话记录,它绝不能将失败内容粘贴到提示词中。
  • 将答案从结构上置于模型无法触及的位置。模型有时会通过直接寻找评测答案来进行“奖励作弊”。

正如后文所述,claude-api 技能会为你应用这些原则。

/CLAUDE-API HILLCLIMB

claude-api 技能中的 hillclimb 命令将这些原则转化为引导式工作流。当你在 Claude Code 中运行 /claude-api hillclimb 时,Claude 会针对给定的评测进行迭代改进。你可以选择它能做出的更改,包括:

  • 你的系统提示词
  • 技能或指令文件
  • 工具描述
  • 模型选择、努力程度及其他 API 参数
  • 你的框架代码

在开始之前,Claude 会询问你想要优化什么(例如性能,或在性能保持不变的情况下优化成本),然后将评测集随机划分为测试集和训练集。对于成本目标,它会考虑 几个常见的成本驱动因素,包括提示词缓存、审查提示词与所选模型的兼容性,以及选择模型和努力程度设置。

在第一轮之前,Claude 会检查评测的噪声(分数仅凭偶然可能波动的幅度)是否小于你愿意采取行动的最小改进幅度;如果不是,它会说明这一点并建议增加重复次数或案例。

每一轮,Claude 都会读取上一轮的训练记录,并以补丁形式提出一项更改。它每一轮都瞄准一项效果能超出评测噪声的更改:它从根源上修复失败行为(例如,重写导致问题的部分或添加缺失的规则),而不是改写某一行。然后它会运行带有该补丁更改的评测。此时,Claude 会应用一项检查:如果 train 集有所改善但 test 集持平,Claude 会怀疑过拟合并回滚该补丁。如果出现回退,Claude 会回滚。如果训练集和测试集都有改善,它会保留该补丁(图 6)。

The hillclimbing loop: the thing being edited, such as a prompt, feeds a fixed model and harness that is scored on a held-out test split and a train split. An analyzer reads only the train failures and proposes one diff per round; the diff is kept when train and test both rise, and reverted when only train rises or either score drops.
图 6爬山法所使用的过程。

当分数停滞两三轮时,Claude 会读取每个剩余的训练失败项并按原因排序。如果没有单一修复能带来超过评测噪声的提升,它也会提前做同样的事,并建议增加重复次数或案例,而不是把轮次花在小到无法测量的更改上。这一步可以发现有歧义的评测案例、框架错误或运行间的差异。

只有合理的失败才会被纳入更多的爬山轮次。

当爬山过程完成后,Claude 会将你的代码保留在针对你的目标在测试集上表现最好的版本。它会报告相对于基线的测试结果及置信区间(图 7)。如果增益在噪声范围内,它会说明这一点并建议不要合并。

The inbox-routing results page after hillclimbing, comparing three variants on train and test scores. Variant v1, which defines each queue and adds a tie-break rule, is marked best at 0.875 on both; v2, which adds two worked examples, was reverted because train went up while test stayed flat.
图 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% 的起始准确率。

图 8以成本为导向的爬山搜索。

最后,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 编写代码的方式,最后修复评分器以及更多技能编辑。

图 9以性能为导向的爬山搜索。

在分数停滞两轮后,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 的审阅、贡献和产品支持。

阅读显示设置

调整正文排版

当前浏览器记住选择,应用于文章正文。手机上正文宽度以屏幕可用空间为限。

图表完整性提示

普通文章遇到图表保存问题时显示提示。