关于 validate-evaluator
validate-evaluator 是校准 LLM judge 与人工判断一致性的 Skill,指导团队划分数据集、迭代评估器并测量 TPR、TNR。它还说明如何校正生产数据的通过率并计算置信区间。
主要功能
- 01划分训练、开发与测试集
- 02测量 TPR 与 TNR
- 03依据分歧迭代 judge 提示词
- 04校正通过率并估算置信区间
适用场景
- 01验证二分类 LLM judge 的判断表现
- 02调整评估提示词并检查开发集结果
- 03估算生产轨迹的真实通过率
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ai-evals-course/ evals-skills --skill validate-evaluator安装后在 Claude Code 中输入/validate-evaluator确认已加载。
附带文件agents/openai.yaml
详细介绍
验证评估器
根据人工判断校准 LLM 评审器。
概览
- 将人工标注的数据拆分为训练集(10-20%)、开发集(40-45%)和测试集(40-45%)
- 在开发集上运行评审器并测量 TPR/TNR
- 迭代调整评审器,直到开发集上的 TPR 和 TNR 均 > 90%
- 在留出的测试集上运行一次,测得最终 TPR/TNR
- 将偏差校正公式应用于生产数据
先决条件
- 已构建的 LLM 评审提示词(来自 write-judge-prompt)
- 人工标注的数据:约 100 条跟踪记录,每种失败模式都有二元通过/失败标签
- 目标是约 50 条通过和 50 条失败(保持平衡,即使实际分布有所偏斜)
- 标签必须由领域专家提供,不能使用外包标注员
- 来自已标注数据的候选少样本示例
核心说明
第 1 步:创建数据集拆分
将人工标注的数据拆分为三个互不重叠的集合:
| 拆分 | 大小 | 用途 | 规则 |
|---|---|---|---|
| 训练集 | 10-20%(约 10-20 个示例) | 为评审提示词提供少样本示例 | 仅使用明确的通过和失败案例。直接用于提示词中。 |
| 开发集 | 40-45%(约 40-45 个示例) | 迭代改进评估器 | 不得加入提示词。反复用于评估。 |
| 测试集 | 40-45%(约 40-45 个示例) | 最终的无偏准确率测量 | 开发期间不得查看。仅在最后使用一次。 |
目标:开发集和测试集合计包含 30-50 个属于每个类别(通过和失败)的示例。即使实际情况中的占比有所偏斜,也要使用平衡的拆分——你需要足够多的失败示例,才能可靠地测量 TNR。
from sklearn.model_selection import train_test_split
# First split: separate test set
train_dev, test = train_test_split(
labeled_data, test_size=0.4, stratify=labeled_data['label'], random_state=42
)
# Second split: separate training examples from dev set
train, dev = train_test_split(
train_dev, test_size=0.75, stratify=train_dev['label'], random_state=42
)
# Result: ~15% train, ~45% dev, ~40% test
第 2 步:在开发集上运行评估器
在开发集的每个示例上运行评审器。将预测结果与人工标签进行比较。
第 3 步:测量 TPR 和 TNR
TPR(真正率): 人工判断为通过时,评审器也判断为通过的频率是多少?
TPR = (judge says Pass AND human says Pass) / (human says Pass)
TNR(真负率): 人工判断为失败时,评审器也判断为失败的频率是多少?
TNR = (judge says Fail AND human says Fail) / (human says Fail)
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(human_labels, evaluator_labels,
labels=['Fail', 'Pass']).ravel()
tpr = tp / (tp + fn)
tnr = tn / (tn + fp)
使用 TPR/TNR,而非精确率/召回率或原始准确率。这两个指标可直接对应偏差校正公式。Cohen's Kappa 仅用于衡量两位人工标注员之间的一致性,不用于衡量评审器与真实标签之间的一致性。
第 4 步:检查不一致项
检查所有评审器判断与人工标签不一致的案例:
| 不一致类型 | 评审器 | 人工判断 | 修正方法 |
|---|---|---|---|
| 误判为通过 | 通过 | 失败 | 评审器过于宽松。强化失败定义或添加边界案例示例。 |
| 误判为失败 | 失败 | 通过 | 评审器过于严格。明确通过定义或调整示例。 |
对于每个不一致案例,确定是否需要:
- 明确评审提示词中的措辞
- 从训练集中替换或添加少样本示例
- 为边界案例添加明确规则
- 将评估标准拆分为更具体的子检查项
第 5 步:迭代
优化评审提示词,并在开发集上重新运行。重复此过程,直到 TPR 和 TNR 趋于稳定。
停止标准:
- 目标: TPR > 90% 且 TNR > 90%
- 最低可接受标准: TPR > 80% 且 TNR > 80%
如果一致性提升停滞:
| 问题 | 解决方案 |
|---|---|
| TPR 和 TNR 都较低 | 为评审器使用能力更强的 LLM |
| 一个指标较低,另一个可接受 | 针对较低的指标检查不一致案例 |
| 两者都停滞在目标以下 | 将评估标准拆解为更小、更原子化的检查项 |
| 对某些输入类型持续判断错误 | 从训练集中添加有针对性的少样本示例 |
| 标签本身似乎不一致 | 重新检查人工标签;评分标准可能需要改进 |
第 6 步:在测试集上进行最终测量
在留出的测试集上运行评审器恰好一次。记录最终 TPR 和 TNR。
看到测试集结果后,不要再迭代。如有需要,请使用新的开发数据返回第 4 步。
步骤 7(可选):估算真实成功率(Rogan-Gladen 校正)
未标注生产数据上的原始评审分数存在偏差。如果需要准确的总体通过率,请根据已知的评审错误进行校正:
theta_hat = (p_obs + TNR - 1) / (TPR + TNR - 1)
其中:
p_obs= 评审判定为通过的未标注轨迹占比TPR、TNR= 根据测试集测得theta_hat= 校正后的真实成功率估计值
将结果限制在 [0, 1] 范围内。当 TPR + TNR - 1 接近 0 时,此方法无效(评审的表现不比随机猜测好)。
示例:
- 评审的 TPR = 0.92,TNR = 0.88
- 500 条生产轨迹:400 条判定为通过 -> p_obs = 0.80
- theta_hat = (0.80 + 0.88 - 1) / (0.92 + 0.88 - 1) = 0.68 / 0.80 = 0.85
- 真实成功率约为 85%,而不是原始的 80%
步骤 8:置信区间
计算 Bootstrap 置信区间。仅有点估计还不够。
import numpy as np
def bootstrap_ci(human_labels, eval_labels, p_obs, n_bootstrap=2000):
"""Bootstrap 95% CI for corrected success rate."""
n = len(human_labels)
estimates = []
for _ in range(n_bootstrap):
idx = np.random.choice(n, size=n, replace=True)
h = np.array(human_labels)[idx]
e = np.array(eval_labels)[idx]
tp = ((h == 'Pass') & (e == 'Pass')).sum()
fn = ((h == 'Pass') & (e == 'Fail')).sum()
tn = ((h == 'Fail') & (e == 'Fail')).sum()
fp = ((h == 'Fail') & (e == 'Pass')).sum()
tpr_b = tp / (tp + fn) if (tp + fn) > 0 else 0
tnr_b = tn / (tn + fp) if (tn + fp) > 0 else 0
denom = tpr_b + tnr_b - 1
if abs(denom) < 1e-6:
continue
theta = (p_obs + tnr_b - 1) / denom
estimates.append(np.clip(theta, 0, 1))
return np.percentile(estimates, 2.5), np.percentile(estimates, 97.5)
lower, upper = bootstrap_ci(test_human, test_eval, p_obs=0.80)
print(f"95% CI: [{lower:.2f}, {upper:.2f}]")
或者使用 judgy(pip install judgy):
from judgy import estimate_success_rate
# judgy expects 0/1 integer labels (1 = Pass, 0 = Fail)
test_labels = [1 if l == 'Pass' else 0 for l in test_human_labels]
test_preds = [1 if l == 'Pass' else 0 for l in test_eval_labels]
unlabeled_preds = [1 if l == 'Pass' else 0 for l in prod_eval_labels]
theta_hat, lower, upper = estimate_success_rate(
test_labels, test_preds, unlabeled_preds
)
print(f"Corrected rate: {theta_hat:.2f}")
print(f"95% CI: [{lower:.2f}, {upper:.2f}]")
实用指南
- 对 LLM 评审固定使用确切的模型版本(采用类似
<model>-<YYYY-MM-DD>的带日期快照 ID,而不是浮动别名)。提供商可能会在不另行通知的情况下更新模型,从而导致无声漂移。 - 更改评审提示词、更换模型,或生产环境中的置信区间意外扩大时,请重新验证。
- 使用约 100 个已标注样例(50 个通过,50 个失败)。少于 60 个时,置信区间会变宽。
- 由一位可信领域专家进行标注是最高效的方式。 如果不可行,可让两位标注人员独立标注 20 到 50 条轨迹,并在继续之前解决分歧。
- 提高 TPR 比提高 TNR 更能缩小置信区间。 校正时会除以
(TPR + TNR - 1),因此较低的 TPR 会缩小分母,并放大估计误差,导致置信区间变宽。
反模式
- 假设评审无需验证就“能正常工作”。 评审可能会持续漏掉失败案例,或将通过的轨迹标记为失败。
- 使用原始准确率或一致率。 应使用 TPR 和 TNR。存在类别不平衡时,原始准确率会产生误导。
- 将开发集/测试集样例用作少样本示例。 这属于数据泄漏。
- 将开发集表现作为最终准确率报告。 开发集数据偏乐观。测试集才能提供无偏估计。
- 使用未经偏差校正的原始评审分数。 如果要报告总体通过率,请应用 Rogan-Gladen 公式(步骤 7)。
- 只报告点估计,不提供置信区间。 对于较小的测试集,校正后的 85% 可能实际上是 78% 到 92%。请报告范围,让利益相关者了解这个数字的可信程度。