我们如何为 Agent 幻觉检测器建基准
摘要:满分不等于能力,回归门不是成绩,循环质疑可以用一场盲标实验回答。这是 HallucC 开源 Phase 1 的完整方法论文档。
核心数字(全部可复现):对抗集 fast 档召回率 93.7%(80 条轨迹),误报率 0%,独立盲标 judge 与作者标签一致率 85.7%(DeepSeek temp=0)。
GitHub 仓库 · 在线排行榜
一、为什么需要这个基准
Agent 的幻觉和单轮对话的幻觉是两回事。错误发生在中间某一步的工具调用上——工具返回「未找到订单」它说「已找到详情」,单位从元记成万元——然后错误沿轨迹一路传播到最终答案。只看最终输出,你永远不知道是哪一步开始错的。
但现有评估体系几乎都在测「最终答案对不对」:
- 英文基准(TRAIL、AgentHallu 等)覆盖了多步轨迹归因,但不覆盖中文场景和中文特有幻觉形态(如中文人名张冠李戴、单位换算编造);
- 中文幻觉基准(HalluQA 等)测的是问答对错,不含
thought→action→observation的完整执行轨迹; - Agent 框架自带 eval 测的是任务完成率,不测过程忠实度——一个 Agent 可以用危险路径碰巧拿到正确答案,然后被记为「成功」。
HallucC-Agent-Bench 专门回答一个问题:你的 Agent 检测器,能不能在一条多步轨迹里把幻觉找出来、定位到步、说清类型?而且能不能离线、零成本、可复现地做这件事?
这不是学术 novelty。这是一个工程团队在造检测器时必须面对的日常问题:我怎么知道我的规则改对了?我怎么知道我的 prompt 迭代没有回退?我怎么向用户证明我的数字不是编的?
二、Planted vs Adversarial:双层基准设计
2.1 核心矛盾:满分 ≠ 能力
所有检测器作者都会面临一个诱惑:构造一组测试用例,跑出 100% 召回率和 0% 误报率,然后把这两个数字写在 README 的第一行。这看起来很漂亮,但它回答了一个错误的问题。
问题在于:如果你同时是用例的构造者、标签的标注者、以及检测器的实现者,你的 100% 可能只是在验证「检测器能抓到自己埋的雷」——这在逻辑上叫同义反复(tautology)。它证明的是实现与文档的一致性,而不是对真实分布的泛化能力。
所以我们做了两套数据集,分别回答两个不同的问题:
| 数据集 | 规模 | 用途 | 核心指标 |
|---|---|---|---|
| 契约回归集 | 20 条 | CI 回归门 | recall = 1.0(设计内) |
| 对抗集 | 80 条 | 能力边界 | recall = 93.7%(真实分布) |
| 合计 | 100 条 | 综合参考 | recall = 94.5% |
2.2 契约回归集:CI 门,不是成绩单
契约回归集的 20 条轨迹由 agent_benchmark.py::_build_cases() 在内存中构建。每条幻觉轨迹的失败模式是按各确定性探测器的精确触发条件手工植入的——不是由检测器自身输出反推的。
具体来说:
- 8 条 clean 轨迹(c1–c8):精心设计为不触发任何探测器。比如 c1_weather 中 observation 与 claim 完全一致;c2_order 中刚性 ID 放进了 task 描述(有来源),不会误触 PARAM_FABRICATION;c3_calc 的算式核验通过且数字少于 5 位。
- 12 条 hallucinated 轨迹(h1–h12):每条植入 1–4 个精确触发的失败模式实例,共 16 个
(code, step)对。其中 h11 是「厨房水槽」用例——单步同时触发 HALLUCINATED_TOOL + PARAM_FABRICATION + OBSERVATION_IGNORED + CLAIM_MISMATCH 四种模式。
在这套数据上,fast 档的结果是:
TP=12 FN=0 FP=0 TN=8
accuracy=1.0 recall=1.0 precision=1.0 F1=1.0 fp_rate=0.0
inst: TP=16 FN=0 FP=0 → inst_recall=1.0 inst_precision=1.0
成本:llm_calls=0 search_calls=0
这是预期结果,不是值得炫耀的成绩。规则探测器对按其精确触发条件构造的用例应全检出、无误报。它验证的是探测器实现与触发条件文档的一致性,而非对真实分布的泛化能力。
它的真正价值是作为 CI 回归门:每次改规则或调 prompt 后跑一遍,确认你没有在不经意间破坏已有能力。tests/test_agent_benchmark.py 用 8 个测试类覆盖了结构完整性、标签独立性(反同义反复)、clean 零误报、hallucinated 精确命中、报告指标、成本断言等路径。
2.3 对抗集:真正的能力边界
对抗集的 80 条轨迹是独立手工标注的,覆盖真实 Agent 执行中会遇到的 14 类失败 shape:数字微调、ID 替换、零值软失败、常识矛盾、单位幻觉、循环绕过、多步传播、SCOPE_DRIFT(目标漂移)、PREMATURE_STOP(过早终止)、参数编造、工具输出忽略、幻觉工具名、交接信息丢失、过度自信断言。
fast 档在这 80 条上的结果:
召回率 93.7% | 误报率 0.0% | 漏检 5 条
漏检原因:全部落在 COVERAGE_GAP
→ SCOPE_DRIFT(中途跑题):LLM-only 模式,需语义判断
→ PREMATURE_STOP(过早终止):同上
→ fast 档纯规则层,设计上不覆盖这两类
5 条漏检样本全部保留在数据集中,附有漏检原因说明。standard 档(LLM 裁判层)补测了 LLM-only 子集(20 条),召回率达到 100%——这说明分层递进架构的设计是有效的:规则层拦截大半,LLM 层只处理规则无法覆盖的语义模式。
/* 分层递进架构 */
输入: trajectory[{step, thought, action, action_input, observation}]
Layer 1: 规则层 (fast) ✓ 0 LLM / 0 搜索 / 毫秒级
├── Schema 校验 → SCHEMA_VIOLATION
├── 参数刚性 ID 检查 → PARAM_FABRICATION
├── 工具注册表查询 → HALLUCINATED_TOOL
├── obs↔claim 相似度 → CLAIM_MISMATCH
├── 循环/重试/冗余检测 → LOOP / RETRY_STORM / REDUNDANT_STEP
├── 常识矛盾 → OVERCONFIDENT_ASSERTION
└── 交接纠正检测 → HANDOFF_LOSS
│
▼ 不确定项向上传递
│
Layer 2: LLM 裁判层 (standard/deep) ⚠ 需 API key
├── 推理连贯性 → reasoning_coherence 维度
├── 任务完成度 → task_completion 维度
├── 目标漂移检测 → SCOPE_DRIFT
└── 过早终止检测 → PREMATURE_STOP
│
▼
│
输出: 六维评分 + 逐步 checks + 失败模式码 + 传播链
2.4 为什么分套而不混为一谈
如果只给一个数字(比如「100 条 recall=94.5%」),读者无法判断这个数字的含金量。分套之后:
- 契约集 1.0 告诉你:检测器的规则实现与其文档描述是一致的(CI 通过)。
- 对抗集 93.7% 告诉你:检测器在面对它没见过的、独立构造的失败样本时,表现如何。
- 两者之间的差距(如果有)告诉你:检测器的泛化边界在哪里。
这种区分在软件工程中很常见——单元测试通过不代表集成测试通过,集成测试通过不代表生产环境没问题。Agent 检测器的评估也应该遵循同样的层级思维。
三、盲标自证:打破循环质疑
3.1 循环性悖论:「检测器抓自家模板」
任何自证基准都面临一个致命质疑:如果你的检测器和你的测试用例出自同一拨人,你怎么证明检测器不是在「背答案」?
这个问题在学术界叫做 circularity(循环性),在工程界更直白:「你写的题你自己考自己,当然满分。」
我们决定正面回应这个质疑,而不是回避它。
3.2 方案:独立的盲标 judge
我们引入了第三个角色——独立 LLM-as-judge,它与检测器、用例作者完全隔离:
Judge 只能看到:
{task, trajectory}+ 工具注册表
Judge 看不到:作者的 expected_failure_modes、检测器的输出结果、任何标签
Judge 的任务:独立判断每一步是否 grounded(基于事实)
技术实现:agent_benchmark_judge.py 使用 DeepSeek(temp=0,确定性输出)对全部 100 条轨迹做盲标。judge 的输入经过严格脱敏——它不知道哪条是 clean、哪条是 hallucinated,也不知道应该在哪一步找到什么失败模式。
3.3 结果
| 指标 | 数值 | 说明 |
|---|---|---|
| Judge Recall | 85.7% | TP=78 / FN=13,与作者标签一致率 |
| Specificity | 100% | TN=9 / FP=0,干净样本零误判 |
| 循环风险裁定 | 低 | 若检测器在「背答案」,judge 应趋近 0%,非 85.7% |
额外发现:judge 将原始 100 条模板证据去重为 41 条独立证据(模板冗余 100→41),说明原始标签中存在一定程度的重复表述——这对后续微调裁判模型是有价值的信息。
注:DeepSeek temp=0 并非完全确定性,单次运行 FN 可能有 ±1 的噪声底。多次运行的均值会更稳定。
3.4 这证明了什么、没证明什么
- 证明了:检测器不是在「背答案」。如果它在背答案,独立 judge 的标注应该与它高度不一致(因为 judge 不知道「标准答案」是什么)。85.7% 的一致率说明检测器捕获的模式与独立判断存在实质性重叠。
- 没证明:检测器达到了「人类水平」或「最优解」。85.7% 意味着仍有 ~14% 的 case 存在分歧——这些分歧可能来自 judge 自身的局限(temp=0 的 DeepSeek 不是完美的裁判),也可能来自检测器确实遗漏了某些边缘情况。这正是后续迭代的方向。
- 诚实声明:这是 Phase 1 的探索性实验,不是大规模统计检验。样本量 100 条不足以给出 p-value 或置信区间。但它足以回答「你的检测器是不是在自嗨」这个 yes/no 问题——答案是 no。
四、我们刻意不做的事
开源过程中有几件事我们明确选择不做。列出它们是因为它们代表了我们的设计取舍,也帮助读者理解这个基准的定位和边界。
-
❌ 不写死 100%
契约回归集 recall=1.0 是设计内的回归门(检测器与标签同源),从不把它当对外成绩宣传。对外只认对抗集的独立标注结果。 -
❌ 不藏失败样本
对抗集里 fast 档漏掉的 5 条(6.3%)保留在数据集中,附漏检原因。欢迎拿去打脸。 -
❌ 不做英文翻译凑数
中文 Agent 生态需要原生的中文轨迹,不是翻译件。双语标记词表支持 EN 边界匹配,但样本本身 CN-first。 -
❌ 不假装全覆盖
COVERAGE_GAP 明确声明 SCOPE_DRIFT 和 PREMATURE_STOP 仅 LLM 档覆盖,fast 档设计不覆盖。不为了数字好看而硬塞规则。 -
❌ 不宣称学术 novelty
本仓库当前定位是「检测器 + 回归基准」,不是论文贡献。planted vs adversarial 的思路在软件测试中是常规实践,我们只是把它应用到了 Agent 幻觉检测这个新场景。
五、如何使用
5.1 安装
# 仅 fast 档(0 依赖)
pip install halluc-detect
# 需 LLM 裁判层(standard / deep 档)
pip install "halluc-detect[llm]"
# 开发模式(仓库内)
git clone https://github.com/fredyee/HallucC-Agent-Bench
cd hallucc && pip install -e .
5.2 跑 Agent 基准
# 文本报告(默认 fast 档,零额度)
halluc-detect bench
# 结构化 JSON(CI 友好)
halluc-detect bench --json
# standard 档(需 [llm] extra + API key)
halluc-detect bench --speed standard
5.3 检测单条轨迹
# stdin 输入
echo '[{"step":1,"action":"search","action_input":"{\"query\":\"订单\"}",
"observation":"未找到","agent_claim":"已找到"}]' \
| halluc-detect detect
# 文件输入
halluc-detect detect trajectory.json --speed fast
# 启用工具 schema 校验
halluc-detect detect trajectory.json --tools demo
5.4 跑盲标 judge
# 全量 100 条(需 [llm] extra + API key)
python agent_benchmark_judge.py
# 抽样冒烟
python agent_benchmark_judge.py --limit 20
六、下一步
Phase 2 · 规划中:公开排行榜
接受第三方检测器提交评测,双轴排名:检测器轴(谁检得准)+ Agent 轴(哪些 Agent 最容易产生幻觉)。在线预览:aihcc.cloud/benchmark
v1.1 · 近期:对抗集扩充至 200 条
引入多 Agent 协作轨迹、更长步数的复杂工作流、跨领域混合场景。目标:将 fast 档召回率稳定在 90%+ 且误报率仍控制在 5% 以内。
v1.2 · 中期:开放标注工具与社区贡献
发布标注规范与 Web 标注界面,接受社区 PR 补充样本。建立样本审核流程保证质量。
v1.3 · 长期:微调专用小裁判模型
基于 judge 盲标数据和标注队列积累的人工复核数据,训练专用的幻觉检测裁判模型。对标 Galileo Luna 的低成本路线——比通用 LLM 便宜一个数量级的裁判。
代码以 MIT 协议开源 · HallucC-Agent-Bench 数据集(100 条轨迹用例)以 CC-BY-4.0 授权
github.com/fredyee/HallucC-Agent-Bench · aihcc.cloud

462

被折叠的 条评论
为什么被折叠?



