加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。

你在做模型对比实验,让 GPT-4 给两组模型的输出打分。结果发现 A 组平均 8.2 分,B 组 8.5 分,差距看起来很明显。但当你换成 Claude 打分时,A 组 7.9 分,B 组 8.0 分,差距几乎消失。这到底该信谁的?
问题在于:LLM 评审员本身也有偏见。它可能天生对某种语气更友好,或对某类答案更宽容。如果不加矫正,直接用评审分数来判断模型好坏,无异于用一把刻度不准的尺子测量长度,结论必然失真。
judgy 解决的就是这个问题。它用统计学中的 Rogan-Gladen 校正方法,从人类标注的小规模测试集出发,估计出评审模型的真实准确率(敏感度和特异度),再把这个偏差从大批量无标签数据的评审结果中剔除,最终给出一个校正后的真实通过率,以及用 Bootstrap 方法计算出的置信区间。
judgy 的核心方法并非为 LLM 量身定制,而是一套在流行病学诊断领域沿用了数十年的经典方法——Rogan-Gladen 校正(1978 年提出)。当医生用某种不够准确的检测手段对大量人群做初筛时,可以用少量已知真实结果的样本(测试集)来估计这个检测的敏感度(TPR,即真阳性率)和特异度(TNR,即真阴性率),再据此校正整体人群的真实患病率估计。
这套方法被 judgy 的作者、美国 UC Berkeley 在读博士 Shreya Shankar 引入 LLM 评审领域。Shreya 同时也是 OVERTON(一个监测生产环境 NLP 系统行为偏移的开源工具)和 DataFramesML 的作者,长期关注 LLM 系统的可观测性和评估可靠性。judgy 是她为同名课程"AI Evals Course"设计的教学工具,代码量和功能范围都刻意保持精简,便于理解和扩展。
想象你要测量一个房间的温度,但你手里只有一支已知会"高估 2 度"的温度计。如果直接读数 25 度,你会以为室温是 25 度,但真实温度是 23 度——偏差是固定的,只需要做一次减法。
LLM 评审的偏差更复杂,因为它对"通过"(阳性)和"拒绝"(阴性)的偏差程度不一样:它可能漏报较多(FN 高,即敏感度低),但对拒绝的判断很准确(TNR 高)。judgy 的核心公式正是为这种非对称偏差设计的:
θ̂ = (p_obs + TNR - 1) / (TPR + TNR - 1)
其中 p_obs 是评审模型在无标签数据上的原始通过率,TPR 和 TNR 是从人类标注测试集估计出的敏感度和特异度。公式的几何含义是:将原始通过率沿敏感度-特异度的偏差方向"投影"回真实通过率。
estimate_success_rate这是 judgy 的主入口函数,工作流程分四步:
第一步:计算评审准确率。用人类标注的测试集,计算评审模型的真阳性率(TPR = 在人类标为"通过"的样本中,评审也判断为"通过"的比例)和真阴性率(TNR = 在人类标为"拒绝"的样本中,评审也判断为"拒绝"的比例)。
第二步:计算原始通过率。在大规模无标签数据上运行评审模型,得到一个原始通过率 p_obs。
第三步:应用校正公式。代入上面的公式,计算校正后的真实通过率 θ̂。
第四步:Bootstrap 置信区间。从测试集中有放回地重复抽样 20000 次,每次重新计算 TPR、TNR 和 θ̂,得到 20000 个 θ̂ 值,取中间 95%(即 2.5% 到 97.5% 分位数)作为 95% 置信区间。
from judgy import estimate_success_rate
test_labels = [1, 1, 0, 0, 1, 0, 1, 0] # 人类标注
test_preds = [1, 0, 0, 1, 1, 0, 1, 0] # LLM 评审在测试集上的判断
unlabeled_preds = [1, 1, 0, 1, 0, 1, 0, 1] # LLM 评审在无标签数据上的判断
theta_hat, lower, upper = estimate_success_rate(
test_labels, test_preds, unlabeled_preds
)
print(f"校正后通过率: {theta_hat:.1%}")
print(f"95% 置信区间: [{lower:.1%}, {upper:.1%}]")
如果 TPR + TNR ≤ 1(即评审模型比随机猜测还差),estimate_success_rate 会主动抛出 ValueError,拒绝给出一个误导性的估计。
synthetic.py提供 generate_test_data 和 generate_unlabeled_data 两个函数,用于生成已知 ground truth 的合成数据,便于:测试校正算法的准确性(已知 TPR/TNR 和真实通过率,验证校正后能否还原)、教学演示和基准实验、调试和回归测试。
plotting.py可选依赖(需安装 judgy[plotting]),提供两个核心图表:
架构风格:极简主义 Python 包,所有业务逻辑在 src/judgy/ 下 4 个文件中完成。__init__.py 只导出 estimate_success_rate 一个核心函数,API 设计得非常克制。
类型标注:core.py 和 synthetic.py 使用完整的 type hint,包括 Union[list, npt.NDArray] 输入兼容和 Tuple[float, float, float] 返回值标注,满足 mypy 严格模式(disallow_untyped_defs: true)。
输入验证:函数入口有详尽的参数校验(空数组、非二进制值、置信度越界、除零检查),每个错误都给出有意义的提示。
数值稳定性:校正后的 θ̂ 被显式 clip 到 [0, 1] 范围,防止浮点运算产生物理上不可能的概率值。
测试覆盖:test_core.py 和 test_synthetic.py 共约 20KB 测试代码,包含边界条件(测试集全正/全负)、数值稳定性(极小样本)和异常输入测试。
依赖极简:核心只需 numpy>=1.20.0,无任何重型 ML 框架依赖,可以轻松集成到任意 Python 项目中。
对 AI 爱好者而言,只要了解"评审"和"通过率"的概念即可使用 judgy,核心 API 一行代码搞定。开发者层面,则需要理解 Rogan-Gladen 校正背后的统计学假设(TPR + TNR > 1,即评审模型必须优于随机),以及 Bootstrap 置信区间的含义。安装只需一行 pip install judgy;进阶开发(可视化、测试)需要 pip install -e .[dev,plotting]。
局限一:需要人工标注测试集。judgy 的校正精度完全取决于人类标注的质量和规模。如果测试集本身有偏,校正结果同样不可靠。Bootstrap 可以量化不确定性,但无法消除标注偏差。
局限二:二分类假设。当前实现只支持二元判断(通过/拒绝),无法处理多级评分(如 1-5 分制)的场景。
局限三:TPR + TNR > 1 的要求。如果 LLM 评审的准确率低于随机猜测,judgy 会拒绝给出估计。
局限四:独立同分布假设。Bootstrap 方法假设测试集和大规模无标签数据来自同一分布。如果分布漂移,置信区间会失真。
在 LLM-as-a-Judge 范式蔚然成风的当下,judgy 提供了一种量化的可信度框架。它不否定 LLM 评审的价值,而是提供了一种诚实地表达不确定性的方式——"我们的系统估计通过率为 72%,95% 置信区间 [65%, 79%]"——而不是给出一个看似精确但实际有偏的点估计。
随着 LLM 评审在 RLHF、模型选择、A/B 测试等场景的广泛应用,这类偏差校正工具的需求只会增长。judgy 作为该领域的先驱性教学工具,虽然规模不大,但填补了一个真实的空白。
GitHub: https://github.com/ai-evals-course/judgy
PyPI: https://pypi.org/project/judgy
作者: Shreya Shankar (UC Berkeley PhD candidate)