A benchmark for RAG evaluation tools

Your eval suite grades the words. Nobody grades the decision.

Before a RAG system writes a word, it decides: is there enough in the context to answer at all? Faithfulness metrics can't see half the ways that decision goes wrong — a refusal asserts nothing, so it's trivially “faithful,” even when refusing was the wrong call. AbstentionBench measures which tools can actually catch it.

The decision

Four quadrants. Two are failures. One is invisible.

Every case freezes a RAG trace — question, retrieved context, and the system's output — with gold labels for the decision. Hover a quadrant for a real case from the dataset.

context ↓ · system →
system ANSWERED
system ABSTAINED
context SUPPORTS an answer
✓ correct decision

Answered a supported question

The context contains the answer and the system gave it.

✗ over-refusal — the invisible one

Refused what it could answer

The answer was right there. The system said “I don't know.” Faithfulness metrics score this as fine.

context does NOT support one
✗ unsupported answer

Answered without support

Nothing in the context backs it — a confident, sourced-looking hallucination.

✓ correct decision

The good “I don't know”

The context can't answer it, and the system said so.

Leaderboard

Can your eval tool see the failure at all?

Task per tool: given (question, context, answer), predict whether the answer/abstain decision was correct. The column that matters is catch rate on over-refusal.

tool
overall accuracy
catches over-refusal
catches unsupported answer
false alarms
The blind spot, mechanically

Why faithfulness can't see over-refusal.

01

The system refuses

“I can't answer that from the provided context.” — but the context contained the answer verbatim.

02

Faithfulness asks its only question

“Is every claim in the answer supported by the context?” A refusal makes no claims. There is nothing to check.

03

Verdict

No unsupported claims found.

FAITHFUL ✓
 
…but the decision was wrong ✗
The fix is to grade the decision, not the words: ask “does the context support an answer?” and “did the system abstain?” — the decision is correct iff they disagree. That two-boolean design is the AbstentionMetric contributed to DeepEval (PR #2843), included here as the abstention_llm adapter.
The hard tier

Thirty cases built to break judges.

Eight archetypes, hand-authored, each kept only after unanimous three-reviewer adversarial label verification (2 of 32 drafts were rejected for label ambiguity — they're not in the dataset). One real example per archetype:

Method & honesty

Built to be checked, not believed.

Construction

  • Core tier (240, 60 per quadrant) — deterministic build from SQuAD 2.0 dev: real questions, real Wikipedia passages, human answerability labels. The unsupported_answered traps are SQuAD's human-annotated plausible answers.
  • Hard tier (30) — hand-authored across 8 archetypes, unanimous 3-reviewer adversarial verification, written rationale per case.
  • Deterministic — fixed seed; python src/build_dataset.py regenerates the dataset byte-for-byte.
  • Licenses — code MIT; dataset CC BY-SA 4.0 (SQuAD 2.0 attribution — Rajpurkar, Jia & Liang, 2018).

Read the numbers honestly

  • Only measured numbers are published. Judges nobody ran show as pending — nothing is estimated.
  • Core-tier answers are templated; phrasing-pattern tools may over-perform on abstention detection. The support judgment and the hard tier carry the discrimination.
  • Contexts are clean Wikipedia paragraphs — real RAG retrieval is noisier.
  • 30 hard cases → per-archetype numbers are directional, not tight.
  • Full limitations in the dataset card.
Run it yourself

One function is all a new judge needs: (q, context, answer) → bool.

Clone the repo, point the harness at your eval tool, and see whether it can grade the decision — not just the words. PRs with new adapter results are welcome.