Lakshya

LLM Systems Engineering · Chapter 4 of 20

Retrieval, technically

Index algorithms and their real trade-offs, what the chunking evidence actually says, and whether long context has replaced RAG. It has not, and the reason is measurable.

9 min read1 diagramAll 20 chapters

Retrieval is where most production AI systems spend their engineering effort, and it is taught almost entirely at the level of library calls. This chapter is the layer underneath: what the index is doing, what the tuning parameters cost, and which of the popular practices survive measurement.

The four index families

THE RECALL CURVE — WHERE EVERY VECTOR-SEARCH COST DECISION LIVES latency recall 0.700.800.900.950.99 0.80 → 0.95 costs ~31% more 0.95 → 0.99 costs 3–5× HNSW PARAMETERS — TWO ARE FROZEN AT BUILD TIME M — edges per node. Recall ↑, memory ↑, build ↓. frozen efConstruction — build-time candidates. frozen efSearch — query-time candidates. the only live knob Edge memory ≈ 4 × M × N × 1.1 bytes, before the vectors. At M=32 and 50M rows that is ~7 GB of graph alone. Start M=16 / efC=100; production M=32 / efC=200; tune efSearch. THE FOUR INDEX FAMILIES HNSW graph, greedy descent all in RAM ceiling ~100-200M / node IVF-PQ partition + compressed tiny memory recall lost to compression DiskANN graph on SSD ~90% less RAM SSD IOPS-bound ScaNN anisotropic quantisation loss weighted by effect on inner product
The recall curve and the HNSW parameters. Note which two parameters are frozen at build time — getting those wrong means a rebuild, not a config change.

The single most useful fact here is that recall is not linear in effort. Moving from 0.80 to 0.95 recall costs roughly 31% more latency; moving from 0.95 to 0.99 costs three to five times. That elbow is where essentially every vector-search cost decision lives, and the right question in a design review is not ‘can we get higher recall’ but ‘does our task actually need the last four points?’

  • HNSW — a multi-layer navigable small-world graph traversed greedily. Best recall-per-millisecond when it fits in RAM, which is the constraint: the graph plus the vectors must be resident, giving a practical ceiling around 100 to 200 million vectors per node. Its two most important parameters are frozen at build time — M, the edges per node, and efConstruction. Only efSearch is tunable per query. And the graph alone, before any vectors, costs roughly 4 × M × N × 1.1 bytes — about 7 GB of edges at M=32 and 50 million rows.
  • IVF-PQ — partition the space into cells, then product-quantise the residuals. Memory footprint is tiny because you store codes rather than vectors, at the cost of recall lost to compression. The right choice when the corpus will not fit in RAM and you can tolerate the loss.
  • DiskANN / Vamana — the graph lives on SSD with compressed vectors in RAM for routing and full vectors read from disk on demand. Around 90% less RAM than HNSW, bounded by SSD IOPS rather than by memory. Reported results include billion-vector corpora at 95% recall in single-digit milliseconds on one node, which is the number that made single-node billion-scale retrieval practical.
  • ScaNN — anisotropic vector quantisation, where the quantisation loss is weighted by its effect on the inner product rather than on reconstruction accuracy. That is the conceptually cleanest idea in the family: you are not trying to reconstruct the vector, you are trying to preserve the ranking.

Chunking: the strongest evidence is a negative result

A peer-reviewed 2025 study evaluated semantic chunking across document retrieval, evidence retrieval and retrieval-based answer generation, and concluded that the computational cost is not justified by consistent performance gains. Fixed-size chunking frequently outperformed semantic strategies on realistically structured documents, and on answer generation the differences were negligible.

There is contradicting evidence, and it is instructive rather than merely conflicting. One end-to-end comparison found recursive splitting beating semantic chunking on final answer accuracy despite slightly lower retrieval recall — because semantic chunks retrieved well but did not carry enough surrounding context for the generator to use.

That mechanism is the thing worth teaching. Retrieval quality and generation quality are not the same objective, and a chunking strategy optimised for the first can hurt the second.

The defensible default: start at roughly 512 tokens with recursive or structural splitting and some overlap. Treat semantic chunking as an optimisation you must justify by measurement on your own corpus, not as a best practice.

Hybrid search and reciprocal rank fusion

BM25 and dense retrieval fail differently. Lexical search nails rare tokens, product codes, identifiers and exact quotes; dense retrieval handles paraphrase and synonymy. Combining them helps because the errors are orthogonal, which is also why the gain is largest out-of-domain.

Reciprocal rank fusion ignores scores entirely and fuses ranks: score(d) = Σr 1 / (k + rankr(d)). The original suggestion was k = 60; a published grid search on a standard benchmark suite found k = 20 optimal for their setup, so treat k as a tunable rather than a constant.

Measured on a standard benchmark suite: Reciprocal Rank Fusion (RRF) over lexical plus a sparse neural retriever gave about +1.4% over the neural retriever alone and +18% over lexical alone, while a properly tuned linear combination gave +6% and +24% respectively.

So the honest position is: a calibrated linear combination beats RRF, and RRF needs no calibration. Score distributions from a lexical and a dense retriever are not commensurable, and normalising them is fragile and corpus-specific. RRF sidesteps that by throwing away score magnitude. Choose RRF when you cannot afford to maintain a calibration, and a tuned combination when you can.

Rerankers, and the honest range

A cross-encoder jointly encodes the query and the document, so no document embedding can be cached and the cost is one forward pass per candidate. The canonical illustration: scoring 10,000 pairs takes hours with a cross-encoder against seconds to embed them with a bi-encoder. Hence the standard two-stage architecture — retrieve 50 to 100 cheaply, rerank those.

The measured contribution is enormously variable, and that variability is the honest headline: reported lifts range from around eighteen points of NDCG in one pipeline to about two points for 200 milliseconds of added latency in another. That is two orders of magnitude of disagreement.

The resolving insight: a reranker's lift is a property of how bad your first-stage retrieval is. If your embedding model is well matched to the domain, reranking adds little. If it is a generic model on specialist text, reranking rescues it. So the answer to “should we add a reranker” is always “measure it on our corpus”, and anyone quoting a general number is quoting their corpus rather than yours.

Late interaction, and where it is genuinely winning

ColBERT-style late interaction stores one vector per token and scores with MaxSim: for each query token take the maximum dot product over all document tokens, then sum. This preserves token-level matching evidence that pooling into a single vector destroys, which is why it is strong out-of-domain and on long documents.

The cost is storage, and the arithmetic is stark. A million documents at one 768-dimension vector each is about 3 GB. The same million at 200 tokens each with 128-dimension token vectors is about 102 GB — or roughly 6 GB with aggressive residual compression, which is what makes it practical. Centroid-based candidate pruning brings query latency into the tens of milliseconds at scale with no measured quality loss.

Where this is most clearly winning in 2026 is visual document retrieval — scoring page images directly rather than running OCR first — because the token-level machinery maps naturally onto image patches, and it removes an entire lossy preprocessing stage.

Has long context replaced RAG? No, and here is the measurement

This is the most consequential architectural question in applied AI right now, and there are three independent lines of evidence that the advertised window is not the usable window.

  • Effective context length. A benchmark that defines effective length as the longest input at which a model stays above a quality threshold found that although every model tested claims at least 32K, only about half hold up at 32K — and a model advertising 128K frequently has an effective length around half of that.
  • Associative rather than lexical retrieval. A benchmark that rewrites needle-in-a-haystack so the needle and the question share minimal wording — forcing association rather than string matching — found most tested models falling below 50% accuracy at quite modest lengths. Models that ace vanilla needle-in-a-haystack fail this, which means high needle-in-a-haystack scores are close to meaningless as evidence of long-context competence.
  • Context rot. Measured degradation with position and distractor density. One reported example has a frontier model falling from over 99% at short context to around 70% by 32K, with many models dropping below half their own short-context baseline at that length.

The cost side reinforces it: attention is quadratic in prefill, and a cached million-token session is on the order of a hundred gigabytes of KV state, which is the arithmetic from chapter 1 applied at scale.

The synthesis the literature actually supports

Long context wins when evidence is distributed across many documents and the task requires aggregation. No retrieval step can select the right subset when the answer depends on all of it.

Retrieval wins when evidence is sparse and retrieval is accurate, and it is the only option at all for fresh or private data.

The production answer in 2026 is neither. It is retrieve to reduce, then let a long window absorb the rest — retrieval acting as an attention prior rather than a hard filter. You retrieve generously into a large window instead of retrieving precisely into a small one, which removes most of the brittleness of top-k selection while staying well inside the effective context length.

Saying that, with the effective-context-length evidence behind it, is a far better answer than either ‘RAG is dead’ or ‘long context is a gimmick’.

Check yourself

What does the recall curve tell you about tuning?That effort is not linear. 0.80 to 0.95 costs about a third more latency; 0.95 to 0.99 costs three to five times. Ask whether the task needs the last four points.
Which HNSW parameters can you change without a rebuild?Only efSearch. M and efConstruction are frozen at build time, so getting them wrong is a rebuild rather than a config change.
Is semantic chunking worth it?The strongest published evidence says no — fixed-size and recursive splitting often match or beat it, and semantic chunks can retrieve well while generating worse because they carry less surrounding context.
Has long context replaced retrieval?No. Effective context length is frequently about half the advertised window, and associative retrieval collapses where literal matching succeeds. The production answer is retrieval as an attention prior into a large window.
← Serving stacks, and prompt cachingAgents, at the token level →