Skip to content

Add a standardized, preregistered retrieval benchmark harness#552

Closed
tobocop2 wants to merge 8 commits into
test/retrieval-parityfrom
feat/eval-benchmark
Closed

Add a standardized, preregistered retrieval benchmark harness#552
tobocop2 wants to merge 8 commits into
test/retrieval-parityfrom
feat/eval-benchmark

Conversation

@tobocop2

Copy link
Copy Markdown
Owner

Problem

The retrieval work needs a comparison that survives scrutiny, not a homegrown judge a skeptic can wave away. That means standard metrics, public human-labeled data, and statistics on every claimed difference.

Solution

evals/benchmark compares lilbee against another RAG system on public labeled datasets with the generator and embedding model held constant, so retrieval is the only variable. Tier 1 scores each system's ranked results against human relevance labels with pytrec_eval (nDCG@10, Recall@20, MRR@10) with no model in the loop, so the core numbers are exactly reproducible. Tier 2 layers RAGAS answer metrics plus the existing blind judge on top. Passage datasets carry native TREC qrels; the table and PDF datasets derive retrieval labels from human gold-evidence annotations through one documented function, disclosed in the frozen manifest. That manifest fingerprints the datasets, metrics, and models before a run and refuses a judge equal to the generator; paired-bootstrap confidence intervals and a randomization p-value gate every reported difference, and a difference whose interval crosses zero is reported as not significant.

The heavy scorers and dataset loaders stay in a standalone pod-install requirements file so installing them never moves the shipped lock, and they are imported lazily so the suite runs without them. The harness lives outside the package, so nothing here ships in the wheel.

tobocop2 added 5 commits July 17, 2026 03:26
evals/benchmark compares lilbee against another RAG system on public
labeled datasets with the generator and embedding model held constant, so
retrieval is the only variable. Tier 1 scores each system's ranked results
against human relevance labels with pytrec_eval (nDCG@10, Recall@20,
MRR@10) with no model in the loop; Tier 2 layers RAGAS answer metrics plus
the existing blind judge on top. Passage datasets carry native qrels;
table and PDF datasets derive retrieval labels from human gold-evidence
annotations via one documented function, disclosed in the manifest. A
frozen manifest fingerprints the datasets, metrics, and models before the
run (and refuses a judge equal to the generator); paired-bootstrap CIs and
a randomization p-value gate every reported difference. The heavy scorers
and dataset loaders stay in a standalone pod-install requirements file so
they never move the shipped lock, and are lazily imported so the suite
runs without them.
The repo .gitignore has a blanket *.txt rule, so evals/benchmark/requirements.txt
was silently never committed and a fresh clone could not install the benchmark
deps. Add a negation for it and commit the file.
ensure_fts_index() runs table.optimize() whenever the FTS index already
exists. On a large corpus that call can hit a LanceDB encoding bug and raise
(Arrow list offset overflow), and the failure fell through to leave _fts_ready
False -- silently dropping every subsequent query to vector-only with no error
surfaced. The index itself is complete and still serves queries, so mark hybrid
ready before the best-effort optimize and downgrade an optimize() failure to a
warning. Found while benchmarking retrieval: every hybrid config collapsed to
the vector-only baseline until this was fixed.
@tobocop2
tobocop2 force-pushed the feat/eval-benchmark branch from 1123fc4 to 6aedffb Compare July 18, 2026 02:05
tobocop2 added 3 commits July 17, 2026 23:18
The retrieval benchmark showed no single lexical_fusion_weight wins every
corpus: SciFact wants a strong BM25 arm, NFCorpus a weak one, FiQA none. Rather
than fix one weight, adaptive_fusion (off by default) scales the BM25 arm per
query by how peaked the vector ranking is -- a top hit standing clear of the
field downweights lexical toward zero, a flat ranking keeps it. adaptive_fusion_
margin sets the vector-similarity margin at which the lexical arm is fully
silenced. lexical_fusion_weight becomes the ceiling the rule scales down from,
so the default path is unchanged.
Significance-tested nDCG@10/Recall@20/MRR@10 for hybrid fusion vs the vector-only
baseline on BEIR SciFact, NFCorpus, and FiQA, with the frozen manifest, gzipped
TREC run files, and qrels for independent re-scoring. Hybrid significantly beats
dense on NFCorpus and SciFact and significantly regresses on FiQA; the
corpus-dependent optimal weight is what motivates adaptive fusion.
Adaptive per-query fusion at confidence margin 0.15, scored against dense on the
same three BEIR datasets: significant wins on NFCorpus (+0.0085, p=0.033) and
SciFact (+0.0205, p=0.009), and the smallest FiQA regression of any config
(-0.0184 vs -0.056 at fixed w=1.0). Best single policy found; does not fully
erase FiQA's regression against pure dense.
@tobocop2

Copy link
Copy Markdown
Owner Author

Superseded by the consolidated retrieval PR #557 — review and merge there. Converted to draft to keep it off the review queue; the branch and history stay intact for reference.

@tobocop2
tobocop2 marked this pull request as draft July 18, 2026 04:55
@tobocop2

Copy link
Copy Markdown
Owner Author

Superseded by the consolidated retrieval PR #557, which contains this change. Closing; the branch stays intact for reference.

@tobocop2 tobocop2 closed this Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant