
1. 为什么我要用 Claude 来搭一套 eval 体系第一次认真做 eval 是去年底当时手头有个基于 Claude API 的垂直场景应用上线前老板问了一句准确率多少我张口结舌。凭感觉说挺好的显然过不了关于是硬着头皮从零搭了一套评测流程。踩了大概两周的坑之后我才明白eval 这件事最反直觉的地方在于写评测集本身比调模型难得多而把分数一轮轮提上去的过程本质上是在做一场有方向的爬山hillclimb不是盲目试参数。这篇东西想聊的就是这套完整打法怎么用 Claude 来设计 eval、怎么把评测跑通、怎么根据失败样本一轮轮把分数往上推。适合两类人看——一类是刚接触 Claude API、想给自己项目加个质量护栏的开发者另一类是已经在用 Claude Code 或 agent skill 做产品、但苦于没有量化指标、每次改 prompt 都靠玄学的同学。全文不涉及任何敏感内容纯粹是工程经验分享。先说结论性的判断eval 不是一次性任务而是一个持续迭代的闭环。你设计评测集、跑分、看失败案例、改 prompt 或改 skill、再跑分这个循环转得越快你的产品就越稳。Claude 在这个闭环里扮演两个角色一是帮你生成和扩充评测样本的出题人二是被评测的考生。把这两个角色分清楚是整套方法论的地基。我见过太多人把 eval 做成跑一次就扔的摆设最后分数虚高、上线翻车。真正有用的 eval 必须满足三个条件样本贴近真实分布、评分标准可复现、失败案例能定位到具体原因。下面我按这个逻辑一层层拆。2. 用 Claude 设计 eval 的整体思路拆解2.1 先想清楚 eval 到底在评什么很多人一上来就问用什么框架这是本末倒置。框架只是壳核心是你到底要评什么。我一般把评测目标拆成三层能力层模型能不能完成这个任务比如信息抽取、意图分类、代码生成。质量层完成得好不好比如格式是否规范、语气是否合适、有没有幻觉。稳定层换个输入还稳不稳比如边界 case、对抗输入、长尾场景。这三层的评测难度是递增的。能力层用准确率就能糊弄过去质量层往往需要 LLM-as-judge稳定层则必须靠精心设计的对抗样本。我建议新手从能力层做起先把 pipeline 跑通再逐步加码。为什么强调这个分层因为不同层对应的优化手段完全不同。能力层不行多半是 prompt 没写清楚或模型选错了质量层不行通常是 few-shot 示例不够或评分标准模糊稳定层不行往往是你的 skill 或 agent 逻辑有漏洞。分不清层就会陷入瞎调参数的泥潭。2.2 为什么让 Claude 当出题人而不是自己硬编自己手写评测集最大的问题是样本量上不去、多样性差。你脑子里能想到的 case 就那么几十个而且都带着自己的思维定式。让 Claude 来生成样本好处有三个第一覆盖长尾。你给它一个任务描述它能一口气生成几百条不同角度、不同难度的输入包括你根本想不到的边界情况。第二成本低。生成样本的 token 消耗远低于人工编写的时间成本。第三可迭代。当你的产品逻辑变了重新生成一批样本比手动改快得多。但这里有个大坑Claude 生成的样本会带有它自己的偏好。比如你让它生成用户投诉的样本它可能翻来覆去就是那几种句式。所以我的做法是Claude 生成初稿人工过一遍筛掉重复和离谱的再让 Claude 针对薄弱类别补充。这个生成-筛选-补充的循环跑两三轮样本质量就上来了。2.3 评测集的结构设计一个能用的评测集我一般按这个结构组织字段说明示例id唯一标识case_001input输入内容用户原始 queryexpected期望输出标准答案或评分要点category类别标签分类/抽取/生成difficulty难度分级easy/medium/hardsource样本来源真实/合成/对抗category和difficulty这两个字段特别关键因为分维度看分数才能定位问题。如果整体准确率 85%但 hard 类别只有 40%那问题就很明确了。我见过有人只存 input 和 expected跑完分一脸懵不知道从哪下手。样本量方面我的经验是每个类别至少 30 条总样本 200 条起步。低于这个数分数波动会大到没有参考价值。如果预算有限宁可类别少一点也要保证每类样本够多。3. 核心细节解析与实操要点3.1 用 Claude 生成评测样本的 prompt 怎么写生成样本的 prompt 质量直接决定评测集质量。我常用的模板长这样你是一个评测数据集生成器。请针对以下任务生成 {N} 条测试样本 任务描述{task_description} 输出格式JSON 数组每条包含 input、expected、category、difficulty 要求 1. 覆盖 {categories} 这些类别每类均匀分布 2. difficulty 分为 easy/medium/hardhard 类要包含边界情况和歧义输入 3. input 要贴近真实用户表达允许有错别字、口语化、信息不全 4. expected 要明确可判定避免主观模糊的答案 5. 不要重复不要生成与任务无关的内容这里有几个细节值得说。允许有错别字、口语化这句一定要加否则 Claude 生成的样本会过于教科书跟真实分布差很远。expected 要明确可判定也很关键如果期望答案本身就有歧义后面评分根本没法做。生成完之后我会写个小脚本做去重和统计看看各类别分布是否均匀。如果某类样本明显偏少就单独再生成一批补上。3.2 评分方式的选择精确匹配还是 LLM-as-judge评分方式的选择取决于任务类型。我整理了一张对照表任务类型推荐评分方式理由分类/意图识别精确匹配答案唯一直接比对信息抽取字段级匹配 部分分允许多字段部分正确文本生成LLM-as-judge无唯一答案需语义评判代码生成执行测试用例跑通即正确最客观对话回复LLM-as-judge 规则语义 格式双重校验LLM-as-judge 是绕不开的一环但它有个致命问题judge 本身也会犯错而且会偏向自己生成的答案。我的应对策略是judge 用跟被测模型不同的模型避免自我偏好评分标准写成明确的 rubric而不是你觉得好不好定期人工抽检 judge 的评分校准它的偏差一个实用的 judge prompt 模板你是评分员。请根据以下标准给回答打分1-5 分 评分标准 5分完全正确格式规范无冗余 4分核心正确有小瑕疵 3分部分正确遗漏关键信息 2分方向对但错误较多 1分完全错误或答非所问 问题{input} 参考答案{expected} 待评回答{output} 请先给出评分理由再输出分数。格式理由... 分数X注意judge 的评分理由一定要让它先输出再输出分数。这个顺序能显著提升评分一致性因为模型在写理由时会自我校准。3.3 评测脚本的工程化要点评测脚本看着简单但工程细节决定它能不能长期用。我踩过的坑包括API 限流导致大批失败、并发太高被拒、结果没落盘重跑一次全白干。所以我的脚本一定包含这几个模块并发控制用信号量限制并发数我一般设 5-10别贪多重试机制指数退避重试处理偶发的连接中断断点续跑每条结果实时落盘中断后能接着跑结果归档每次跑分存一份带时间戳的结果方便对比import json, time, asyncio from pathlib import Path async def run_eval(cases, sem, client, model): results [] async def one(case): async with sem: for attempt in range(3): try: resp await client.messages.create( modelmodel, max_tokens1024, messages[{role: user, content: case[input]}] ) return {id: case[id], output: resp.content[0].text} except Exception as e: if attempt 2: return {id: case[id], error: str(e)} await asyncio.sleep(2 ** attempt) tasks [one(c) for c in cases] for coro in asyncio.as_completed(tasks): r await coro results.append(r) Path(results.jsonl).open(a).write(json.dumps(r) \n) return results这段代码的核心是实时落盘。别小看这一行我因为没加它重跑过好几次几百条的评测浪费的时间和 token 够买好几杯咖啡了。4. 实操过程与核心环节实现4.1 从零搭一套 eval 的完整流程我把整个流程拆成六步按顺序走基本不会乱定义任务和评分标准写清楚输入输出格式、什么算对什么算错生成评测样本用 Claude 批量生成人工筛选补充搭建评测脚本并发、重试、落盘三件套跑基线分先跑一遍看当前水平作为后续对比基准分析失败案例按类别、难度分组看找出主要失分点迭代优化改 prompt / 改 skill / 换模型再跑分对比这六步里第 5 步是最容易被跳过、也最值钱的。很多人跑完分看到 80% 就满足了不去看那 20% 错在哪。但恰恰是这 20% 决定了你能不能上到 90%。4.2 基线跑分与失败案例归类跑完基线分之后我会写个脚本把失败案例按类别聚合输出一份失分地图。比如类别统计 - 分类任务准确率 92%失分 4/50 - 抽取任务准确率 78%失分 11/50 - 生成任务准确率 65%失分 17/50 难度统计 - easy95% - medium82% - hard58%看到这张表优化方向就一目了然了生成任务和 hard 难度是重灾区。接下来我会把生成任务的失败案例逐条看一遍归纳出失败模式。常见的失败模式有格式不符输出没按要求的 JSON 格式信息遗漏关键字段没抽出来幻觉编造了原文没有的信息过度冗长答案对但废话太多每种失败模式对应不同的修法。格式不符就加格式约束和示例信息遗漏就拆解任务、分步抽取幻觉就加不确定时输出未知的指令过度冗长就明确长度限制。4.3 一轮轮把分数提上去的 hillclimb 打法hillclimb 的精髓是每次只改一个变量改完立刻验证。我一般按这个优先级改第一轮修 prompt 的硬伤。检查指令是否清晰、格式约束是否明确、有没有自相矛盾的地方。这一轮通常能涨 5-10 个点成本最低。第二轮加 few-shot 示例。从失败案例里挑几个典型的作为示例塞进 prompt。注意示例要覆盖不同的失败模式别都是同一类。这一轮一般再涨 5 个点。第三轮拆解任务。如果单次调用搞不定就拆成多步。比如先分类再抽取先理解再生成。拆解会增加延迟和成本但准确率提升明显。第四轮换模型或调参数。前面都试过了还不行再考虑换更强的模型或调 temperature。这一步成本最高放最后。我实测下来前三轮通常能把分数从 70% 推到 90% 左右。剩下的 10% 往往是任务本身的模糊性导致的硬啃性价比不高。实操心得每次改完一定要全量重跑别只跑失败的那几条。因为你的修改可能修好了 A 却弄坏了 B只跑失败案例会漏掉这种回归。4.4 用 skill 封装评测能力如果你在用 Claude Code 或类似的 agent 环境可以把整套评测流程封装成一个 skill这样每次迭代直接调用不用重复搭环境。一个评测 skill 大概包含样本生成脚本评测执行脚本结果分析脚本历史结果对比脚本封装成 skill 的好处是流程标准化团队里谁都能跑结果可复现。我见过团队里每个人评测方式都不一样最后分数没法横向对比非常痛苦。5. 常见问题与排查技巧实录5.1 评测分数虚高的几个陷阱分数虚高是最危险的情况因为它会让你误以为产品已经达标。常见的虚高来源陷阱表现解法样本泄漏评测样本和训练/prompt 示例重复严格隔离示例从训练集取评分过松judge 给分普遍偏高校准 judge加人工抽检样本太简单全是 easy 案例强制包含 hard 和对抗样本只测 happy path没有边界和异常输入专门生成对抗样本我踩过最狠的一次是样本泄漏我把几个典型示例写进了 prompt结果评测集里也有几乎一样的 case分数虚高到 95%上线后真实场景只有 70%。从那以后我定了个规矩prompt 里的示例和评测集必须来自不同批次。5.2 judge 评分不一致怎么办LLM-as-judge 最大的问题是同一份回答跑两次分数不一样。这通常是因为 temperature 没设成 0或者评分标准太模糊。我的处理办法judge 的 temperature 设为 0评分标准细化到每个分数档都有明确描述对边界 case 跑三次取多数定期用人工标注的黄金集校准 judge如果 judge 和人工的一致性低于 80%那这个 judge 就不能信得重新设计评分标准。5.3 API 调用失败的排查清单跑评测时 API 报错是家常便饭我整理了一份速查清单连接中断多半是并发太高降并发 加重试限流 429加退避重试或错峰跑超时检查 max_tokens 是否设太大或网络问题返回格式异常加输出解析的容错别让一条坏数据搞崩整个脚本token 超限检查输入是否过长考虑截断或分段避坑技巧评测脚本一定要能跳过已成功的 case。我一般用 id 去重重跑时自动跳过已完成的这样中断恢复特别快。5.4 分数卡住不动了怎么办分数提到一定程度会进入平台期怎么改都不涨。这时候别硬刚换个思路第一回头看失败案例是不是同一类。如果 90% 的失败都是同一个原因那说明你的优化没打到点上。第二检查评测集本身有没有问题。有些 case 的 expected 可能标错了或者本身就有歧义。第三考虑任务是否可拆。一个复杂任务拆成几个子任务分别评测往往比整体硬调更有效。我遇到过一次分数卡在 88% 死活上不去最后发现是评测集里有 5 条样本的 expected 标错了。修正之后分数直接到 93%。所以定期审计评测集是必要的。6. 我在这套流程里攒下的几条硬经验做了一年多的 eval最大的体会是评测的价值不在于那个分数而在于它逼你把什么叫做好想清楚。很多产品问题本质上是需求没定义清楚eval 只是把这个模糊暴露出来了。几条具体的经验样本质量比数量重要200 条精心设计的样本胜过 2000 条凑数的评分标准要写到换个人也能照着打分的程度每次优化只改一个变量否则你不知道是哪个改动起了作用失败案例要逐条看别只看统计数字。还有一点eval 要跟着产品一起演进。产品加了新功能评测集就得加对应的样本用户反馈了新的失败模式就补进评测集。一个半年没更新的评测集参考价值会大打折扣。最后分享个小技巧我会给每个版本的评测结果打上 git tag跟代码版本对应。这样任何时候都能回溯这个分数是哪个版本跑出来的排查回归问题特别方便。这套东西搭起来前期费点劲但一旦跑顺了每次改 prompt 心里都有底不用再靠感觉拍脑袋了。