I shipped my first RAG prototype in a weekend, and it felt like magic. Then real users started asking real questions, and the magic wore off fast. Naive RAG (embed everything, top-k cosine search, stuff the context window) plateaus quickly. My answers were close but wrong often enough to erode trust. After months of tuning, I moved retrieval accuracy to 94% over a 100K+ document corpus, with search running about 70% faster, now serving 10K+ predictions a day in the production system I built with LangChain and OpenAI. Here is exactly how I got there, what mattered, and what I'd tune first if I started over today.
Key Takeaways
- Naive top-k vector search plateaus fast on large, mixed corpora; the fix is a pipeline, not a bigger model.
- I reached 94% retrieval accuracy on 100K+ documents, 70% faster search, serving 10K+ predictions/day (LangChain + Qdrant + GPT-4 + Redis).
- Practitioners report hybrid search (BM25 + vector) adds roughly 15-30% relevance over pure vector retrieval.
- Cross-encoder reranking on a shortlist can lift precision by up to ~48%, per practitioner reports.
- Start with chunking and reranking before swapping models; they give the biggest return per hour spent.
Why does naive RAG underperform on real corpora?
Naive RAG underperforms because pure vector search optimizes for semantic similarity, not answer relevance, and the two diverge on large corpora. Stanford and Databricks practitioners report retrieval quality, not generation, is the dominant failure point in production RAG. On my 100K+ document corpus, top-k cosine alone returned plausible-looking chunks that missed the exact passage users needed.
The failure modes stack up. Embeddings blur rare keywords, product codes, and exact phrases, so a query for "error E-4012" drifts toward generally similar text. Fixed-size chunks slice sentences mid-thought, stranding the answer across two neighbors. And top-k returns the closest vectors, not the most useful ones. Each gap is small. Together they cap your accuracy well below where the LLM could perform if it just saw the right context.
In production RAG, retrieval quality is the ceiling on answer quality. A frontier model cannot reason its way out of context it never received. Practitioners consistently find that retrieval, not generation, is where most RAG systems leak accuracy.
How should you chunk documents for better retrieval?
Chunk on semantic boundaries, not arbitrary character counts; semantic chunking keeps a complete idea in one retrievable unit. Practitioners report semantic and structure-aware chunking contributes a meaningful share of the 30-50% answer-relevance gains seen when chunking, hybrid search, and reranking are combined. Fixed 512-token windows were my single biggest early mistake.
Here is what changed my results. I stopped splitting on raw token counts and started splitting on structure: headings, list boundaries, and paragraph breaks first, then a semantic split that groups sentences by embedding similarity. I added a 10-15% overlap so a thought that spans a boundary still lands intact in at least one chunk. For tables and code, I kept the whole block together rather than shredding it.
- 1Split on document structure first: headings, sections, list items, then paragraphs.
- 2Apply semantic grouping within sections so related sentences stay together.
- 3Keep a 10-15% overlap between adjacent chunks to preserve context across boundaries.
- 4Never break tables, code blocks, or short definitions across chunks.
- 5Attach metadata (source, section title, date) to every chunk for later filtering.
The metadata point is underrated. Once each chunk carried its section title and source, I could pre-filter by document type before the vector search even ran. That trims the candidate set, sharpens relevance, and shaves latency. It was part of how I got search roughly 70% faster while accuracy climbed, not fell.
What is hybrid search and why does it beat pure vector?
Hybrid search runs keyword retrieval (BM25) and vector retrieval together, then fuses the results, so you catch both exact matches and semantic ones. Practitioners commonly report hybrid search adds about 15-30% relevance over vector-only retrieval. On my corpus, hybrid was the change that finally made product codes, error strings, and acronyms reliably findable.
Vector search and keyword search fail in opposite directions, which is why combining them works. Vectors are great at "explain the refund policy" but weak at "clause 7.3.b". BM25 is the reverse. I fuse the two ranked lists with Reciprocal Rank Fusion, which needs no score calibration and is hard to break. Qdrant, the vector database holding my embeddings, handled the vector side; a sparse index handled keywords. The union recovered the chunks each method alone kept missing.
| Query type | Keyword (BM25) | Vector | Hybrid result |
|---|---|---|---|
| Exact code "E-4012" | Strong | Weak | Found reliably |
| Paraphrased intent | Weak | Strong | Found reliably |
| Rare acronym | Strong | Medium | Found reliably |
| Conceptual question | Medium | Strong | Found reliably |
How does reranking with a cross-encoder improve precision?
Reranking runs a cross-encoder over your retrieved shortlist, scoring each query-document pair jointly instead of by separate embeddings. Practitioners report cross-encoder reranking can lift precision by up to roughly 48% on the candidates that matter most. This was the highest-leverage single step in my pipeline, and it's cheap because it only scores a shortlist.
The trick is the two-stage shape. Hybrid search casts a wide, cheap net and returns maybe 30-50 candidates. The cross-encoder then reads the query and each candidate together, capturing interactions a bi-encoder never sees, and re-sorts them. I keep the top 5-8 after reranking. Because the expensive model only touches a shortlist, latency stays low while the chunks that reach GPT-4 get noticeably sharper.
Reranking decouples recall from precision: let cheap retrieval grab a generous shortlist, then spend a cross-encoder only on those candidates. Practitioners report this two-stage pattern can raise precision by up to ~48% without re-embedding the corpus.
from sentence_transformers import CrossEncoder
# Stage 1: hybrid retrieval returns a generous shortlist (k = 40)
candidates = hybrid_retriever.search(query, k=40) # BM25 + Qdrant, RRF-fused
# Stage 2: cross-encoder reranks the shortlist by joint relevance
reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")
pairs = [(query, c.text) for c in candidates]
scores = reranker.predict(pairs)
ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
top_context = [c.text for c, _ in ranked[:6]] # feed only the best 6 to the LLMWhat about query understanding and context compression?
Query understanding rewrites or expands the user's question before retrieval, and context compression trims retrieved chunks down to only the relevant sentences. Practitioners report these refinements contribute to the combined 30-50% answer-relevance improvement seen across well-tuned pipelines. They matter most on vague, multi-part, or conversational queries where the raw question retrieves poorly.
Two moves earned their keep for me. First, query rewriting: I expand abbreviations and resolve pronouns from chat history so a follow-up like "and the second one?" becomes a standalone query. Second, contextual compression: after reranking, I drop sentences in each chunk that don't relate to the question. That packs more signal into the same token budget, which keeps GPT-4 focused and cuts cost. Redis caches both rewritten queries and frequent results, which is a big part of the 70% latency win.
- 1Rewrite vague queries into standalone, fully-specified questions before retrieval.
- 2Resolve pronouns and references from conversation history for multi-turn chats.
- 3Compress each retrieved chunk to the sentences that actually answer the query.
- 4Cache rewritten queries and hot results in Redis to cut repeat latency.
Which technique delivers the biggest accuracy gain?
Reranking and the full combined pipeline deliver the largest gains, but the honest answer is that the techniques compound. The directional ranges below come from practitioner reports, not a single benchmark. Treat them as relative guidance for where to invest, then measure on your own corpus, because your document mix decides which lever moves most.
Directional ranges; practitioners report. Combine for the largest effect.
Notice the bars aren't additive. You can't stack 25% and 48% and expect 73%; each stage operates on what the previous one passed forward. In my build, the combination, not any single trick, is what carried first-hand accuracy to 94%. The ranges tell you where to look. Your own evaluation set tells you where to stop.
What would I tune first if I started over?
If I rebuilt today, I'd fix retrieval inputs before touching the model, because that's where the cheap, durable wins live. Practitioners consistently report retrieval quality caps RAG accuracy more than generation does. Here is the priority order I'd actually follow, top to bottom, measuring after each change against a fixed evaluation set.
- Build a labeled evaluation set first; you can't improve what you don't measure.
- Fix chunking: switch to structure-aware, semantic splits with light overlap.
- Add hybrid search (BM25 + vector) with Reciprocal Rank Fusion.
- Add a cross-encoder reranker over a 30-50 candidate shortlist.
- Add query rewriting for vague and multi-turn questions.
- Add contextual compression to pack more signal per token.
- Cache rewritten queries and hot results to cut latency.
- Only then consider a larger embedding or generation model.
Frequently asked questions
Is reranking worth the added latency? Yes, in my experience it's the best return per millisecond. Because the cross-encoder only scores a shortlist of 30-50 candidates, the added latency is small while precision gains are large; practitioners report up to ~48% precision lift from this single step.
Do I still need hybrid search if my embeddings are strong? Usually yes. Even strong embeddings blur exact keywords, codes, and rare acronyms. Practitioners report hybrid search adds roughly 15-30% relevance over vector-only retrieval, mostly by recovering the exact-match queries that pure vectors quietly miss.
How do I know my changes actually helped? Measure against a fixed, labeled evaluation set before and after each change. Without one, you're guessing. A held-out set of real questions with known correct sources is the only way I trust an accuracy number like the 94% I reached.
Conclusion: a pipeline, not a prompt
Better RAG accuracy didn't come from a smarter prompt or a bigger model. It came from treating retrieval as a pipeline: semantic chunking, hybrid search, cross-encoder reranking, query rewriting, and compression, each measured against a real evaluation set. That stack is what moved my first-hand accuracy to 94% over 100K+ documents, with search about 70% faster, now serving 10K+ predictions a day. The directional ranges from other practitioners point you at the right levers, but your corpus decides the order. Start with an evaluation set, fix chunking, add reranking, and measure everything. If you're building RAG and stuck on a plateau, start at the top of that checklist and work down. I'd love to hear which lever moved your numbers most.
Sources
- 1Superlinked, Optimizing RAG with Hybrid Search and Reranking - retrieved 2026-06-23
- 2Pinecone, Hybrid search - retrieved 2026-06-23
- 3Cohere, Rerank overview - retrieved 2026-06-23
- 4Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (2020) - retrieved 2026-06-23
Get the next post
New writing on AI engineering, RAG, and shipping real products - straight to your inbox, no noise.
