Skip to work
All work
No. 052026RAG benchmark harness · In progress, 11 of 17 phases shipped

Production RAG LabEvery Layer of RAG, Benchmarked

A config-driven harness that benchmarks every layer of production RAG on one corpus, one eval set, one metric suite. 11 of 17 phases complete, generation on real Claude Haiku, with the honest results the tutorials skip.

Headline results

Phases
17 of 17 built
Rerank on a weak stage
recall@1 0.55 → 0.95
Rerank on a strong stage
no gain, 2.7× latency
Tests · runs
178 · 110

System architecture

System architecture diagram for production-rag-lab
Fig. 1 — Production RAG Lab — system architectureFull size

Problem

RAG is easy to prototype and hard to productionize. Every layer, chunking, embedding, indexing, retrieval, query understanding, reranking, has a dozen viable techniques, and the best one is dataset, latency, and cost dependent. Tutorials teach one trick in isolation, so teams ship a naive RAG, watch it fail, and cannot tell whether the fix is a better chunker, a reranker, a different index, or a different query strategy.

Approach

A config-driven pipeline contract (chunk, embed, index, retrieve, rerank, assemble, generate) where every stage is a swappable component behind a fixed interface, plus a runner and a leaderboard that scores any config on retrieval quality, answer quality, latency, cost, and memory. Seven phases are built so far: ingestion with deps-free parsers and from-scratch MinHash near-dup detection, 7 chunkers, tfidf and hashing embedders with int8 and binary quantization and Matryoshka truncation, from-scratch IVF and Okapi BM25 alongside optional HNSW against exact Flat, dense, sparse, hybrid, RRF, weighted and MMR retrieval, and PRF, multi-query and HyDE query transforms. The core installs on numpy and pyyaml, runs offline on an M1, and the metrics module is unit-tested against hand-computed cases. Real answer quality and cost come from Claude Haiku 4.5 on AWS Bedrock at temperature 0.

Impact

The meta-finding across phases 5 to 9 is the one that generalizes: every technique only helps where there is headroom. The same reranker lifts a weak first stage from 0.55 to 0.95 recall@1 and buys literally zero on a saturated one, at 2.7x the latency either way, and hybrid, PRF and contextual retrieval all repeat the pattern. So 'should I add X?' is unanswerable without measuring your own bottleneck first. Individual traps fell out along the way: binary quantization ships a 32x smaller index and collapses recall@1 from 0.95 to 0.05 while int8 is lossless at 4x less memory; PRF expansion hurts a corpus that already retrieves well. On real Claude Haiku, prompt style turned out to be the best return in the lab, an abstain instruction buying +17% token-F1 at identical cost, while exact match scored 0.000 on every real config and would have called the whole system broken. Phases 11 to 16 are pending.

Decisions & tradeoffs

From-scratch over library calls

MinHash near-dup, the IVF k-means coarse quantizer, Okapi BM25, and all of recall, precision, MRR, NDCG and MAP are written from the definitions and unit-tested against hand-computed cases. The core install is numpy and pyyaml with no downloads, so the mechanism stays legible and every run is reproducible offline on an 8 GB M1.

Rebuilt the eval corpus when it stopped separating configs

The phase 0 mini set saturated at recall@5 1.000, so every chunker and index scored identically and the leaderboard proved nothing. Phase 2 added a 13-doc multi-paragraph corpus with doc-level qrels and doc-level scoring, which is what made recursive at MRR 0.917 separate from fixed at 0.750.

Score retrieval phases on retrieval metrics, not answer metrics

token_f1 stayed flat at 0.21 to 0.23 across all seven chunkers because the extractive mock generator cannot convert better retrieval into a better answer. Real Claude Haiku only moved it from 0.33 to 0.38 against a one-line extractive baseline. That lexical-metric blind spot is why the LLM judge is scoped as its own later phase rather than bolted on early.

Build spec

Status
11 of 17 phases · 0 through 10
Meta-finding
Upgrades only pay where there is headroom
Corpus
13 docs, 20 labeled queries
Tests
56 passing
Generator
Claude Haiku 4.5, Bedrock, temp 0

System notes

  • Binary quantization is a 32x smaller index that collapses recall@1 from 0.95 to 0.05, int8 is lossless at 4x less memory
  • PRF expansion drops recall@1 from 0.95 to 0.90 at 2x latency on an already-saturated corpus, query drift and not a free upgrade
  • IVF at nprobe 1 is the ANN Pareto in one row, 2.5 points of recall@5 for 2x the speed against exact Flat
  • From-scratch MinHash dedup, IVF k-means, Okapi BM25, and every retrieval metric, core install is numpy plus pyyaml

What this does not show

  • The corpus is 13 documents over 20 queries, so nothing under roughly 20 points is resolvable and every number is directional.
  • The harness overturned two of its own headlines: the Phase 11 judge killed the +17% prompt-style claim as a lexical artifact, and Phase 13's bootstrap put a confidence interval through the +10 point contextual-retrieval result.

Stack

Python · NumPy · BM25 · AWS Bedrock · Claude Haiku · RAG

View source on GitHub
Next project
CureWise · Agentic RAG for Healthcare