lumen-rag / docs /case-study.md
WickTech's picture
Space README + Gradio entrypoint
fd3cc1a verified
|
Raw
History Blame Contribute Delete
4.02 kB
# Case study: what chunking and hybrid retrieval actually buy you
Lumen ships an eval harness (`lumen_rag/eval/`) specifically so claims like
"chunking helps" or "hybrid retrieval helps" don't have to stay vibes. This
is the measurement behind the numbers in the README.
## Setup
- **Corpus**: `data/docs/` β€” 7 markdown documents (~2,250 words total), each
covering multiple unrelated handbook topics per file (e.g. `deploys-ops.md`
bundles deployments, on-call, incident response, disaster recovery, plus
three unrelated filler sections). This mirrors a real internal wiki page:
long, multi-topic, with the answer to any given question living in one
paragraph out of several.
- **Eval set**: `data/eval.jsonl` β€” 19 labelled questions, each with the
correct source document id(s).
- **Embedder**: the offline deterministic `HashingEmbedder` (bag-of-words
feature hashing, L2-normalised) β€” no API key, fully reproducible, what CI
and the hosted demo run by default.
- **Metric**: `lumen_rag.eval.harness.evaluate`, doc-level (chunk hits are
collapsed to unique parent documents before scoring), k=5.
- **Reproduce**: `python scripts/benchmark.py`
## Results
| Configuration | recall@5 | precision@5 | MRR | nDCG@5 | hit rate |
|---|---|---|---|---|---|
| naive β€” 1 chunk per doc, vector-only | 0.97 | 0.20 | 0.93 | 0.94 | 1.00 |
| + sentence-aware chunking, vector-only | 0.97 | 0.20 | **0.97** | **0.97** | 1.00 |
| + hybrid (BM25 + Reciprocal Rank Fusion) | 0.97 | 0.20 | **0.97** | **0.97** | 1.00 |
## Reading the numbers honestly
**Recall and hit-rate are already saturated** at 0.97/1.00 in the naive
config β€” with only 7 candidate documents and distinct enough vocabulary
per topic, the correct document almost always lands somewhere in the top 5
regardless of technique. Publishing only recall would (falsely) suggest
chunking doesn't matter here. It does β€” just not on that metric.
**MRR and nDCG@5 are where the effect shows up.** Both measure *where* the
correct document ranks, not just whether it's present. Moving from naive to
chunked lifts MRR from 0.93 to 0.97 β€” a small absolute jump that maps to a
concrete failure mode disappearing: when a whole 300–450 word multi-topic
document is embedded as a single vector, the sections irrelevant to the
query dilute the average, and the correct document occasionally ranks 2nd
or 3rd behind a partial-vocabulary-match decoy instead of 1st. Sentence-aware
chunking (120-word windows, 20-word overlap) embeds each section on its own,
so the answer-bearing chunk competes on its own signal instead of being
outvoted by the rest of the document.
**Hybrid ties chunked-vector, not because RRF doesn't work, but because the
offline `HashingEmbedder` is itself a bag-of-words signal** β€” term-frequency
counts, L2-normalised. That's structurally close to what BM25 computes, so
fusing the two rankers mostly agrees with itself. Hybrid's actual value
proposition β€” catching exact rare-term or numeric matches that a *semantic*
embedding model under-weights in favor of topical similarity β€” needs a real
semantic embedder (`OPENAI_API_KEY` set, `text-embedding-3-small`) and a
larger, noisier corpus to demonstrate honestly. That's flagged as a follow-up
rather than asserted with numbers we didn't measure.
## Takeaways for anyone building on Lumen
1. **Don't just report recall/hit-rate.** They saturate fast on small
corpora and hide ranking-quality regressions. MRR/nDCG catch what recall
misses.
2. **Chunking's benefit scales with document length and topic density**, not
corpus size. A corpus of short, single-topic documents won't show this
effect β€” you need documents where the answer is a minority of the content.
3. **Hybrid retrieval's payoff is embedder-dependent.** With a lexical/hash
embedder it's close to redundant with vector search; with a real semantic
embedder it complements it. Re-run `scripts/benchmark.py` with
`OPENAI_API_KEY` set to see the difference on your own corpus.