Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path →
DPR,
explained.
Ask "how tall is the tallest mountain?" and the answer passage might never say "tallest" — it says "Everest, 8,849 m." Keyword search (BM25) shrugs: no shared words, no match. DPR fixed this by teaching a model to match on meaning — encode questions and passages into vectors and pair them by dot product. But the quiet genius is in the training: a trick called in-batch negatives that squeezes B² comparisons out of a batch of B, turning what looks like a data-hungry problem into a nearly free one. Here's the dual encoder, and the free lunch that trains it.
What changes against unsupervised embeddings: retrieval gets trained
Rungs 1 to 3 produce general-purpose vectors, and rungs 4 and 5 index them efficiently. None of them is trained on the task. For question answering that is a real mismatch, because a question and the passage that answers it are often not similar texts at all — they share little vocabulary and differ in form. Which is why keyword scoring had remained a stubbornly strong baseline: general similarity is not the relation you want.
The change is to train two encoders jointly on question-passage pairs — one for questions, one for passages, into a shared space where the inner product is high exactly when the passage answers the question. A learned relation, not a generic one, and a clean demonstration (after earlier work such as ORQA) that dense retrieval beats strong keyword matching on open-domain question answering.
The training trick is the rung's most reusable content, because the obvious obstacle is negatives: a contrastive objective needs wrong answers, and collecting them is expensive. The observation is that a batch of pairs already contains them — for any question, the passages belonging to the other questions in the batch are almost certainly not its answer. A batch of B pairs therefore yields B×(B−1) negatives for free, and the whole comparison is one matrix multiplication of the batch against itself. The vision ladder's contrastive rung is the same accounting applied to crops of an image, and it is why both papers care so much about batch size.
Matching on meaning
Open-domain question answering starts with a retrieval step: pull a handful of relevant passages from millions, then read them for the answer. For years that first step was BM25 — sparse, keyword-based scoring. It's fast and strong, but it has a fatal blind spot: it matches on words, not meaning. When the question and the answer passage phrase things differently — the vocabulary mismatch problem — BM25 misses.
DPR replaces keyword matching with dense matching. It learns to map both questions and passages into the same vector space so that a question sits close to the passages that answer it, regardless of shared words. "Tallest mountain" and "Everest" land near each other because they mean related things. Retrieval becomes: encode the question, find the nearest passage vectors. Simple — the work is in learning that space, and that's where the paper's cleverness lives.
Encode questions and passages into a shared vector space with two encoders, match by dot product, and train it cheaply by reusing every other passage in the batch as a negative.
The dual encoder
DPR uses two separate BERT encoders: one turns a question into a vector, the other turns a passage into a vector. Similarity is just their dot product. This dual-encoder (or bi-encoder) design has a decisive practical property: because a passage's vector doesn't depend on the question, you can encode all passages once, offline, store them in a vector index, and at query time only encode the question and do a fast nearest-neighbor search.
That independence is what makes dense retrieval scale to millions of passages — it's the same reason Sentence-BERT uses a bi-encoder rather than scoring every pair jointly. The cost is that question and passage never "see" each other during encoding, so the model must pack all the matching signal into the vectors themselves. Training has to be good enough to make that work — which brings us to the hard part: where do the negative examples come from?
The free lunch
To learn a good space, the model needs to see not just which passage is right for a question (the positive) but many that are wrong (negatives) — and it must push those away. Mining hard negatives for every question is expensive. DPR's trick, in-batch negatives, gets them almost for free.
The insight: in a batch of B pairs, every passage was going to be encoded anyway. So compute the full B×B similarity matrix. For question i, passage i is the positive; the other B−1 passages — the positives of the other questions — are perfectly good negatives, because a passage answering a different question is (almost always) wrong for this one. Training is then a simple in-batch classification: for each row, softmax over the B passages and push probability onto the diagonal. One batch yields B positives and B×(B−1) negatives at nearly zero extra cost.
B squared from B
Let a batch have B pairs, with question vectors qᵢ and passage vectors pⱼ. The similarity matrix and the negative count are:
A batch of 128 pairs yields 128 positives and 128·127 = 16,256 negatives — from encoding just 128 questions and 128 passages. The negatives scale as B², the encoding cost as B.
The loss is the negative log-likelihood of the positive under a softmax over each row — a contrastive objective that pulls the positive up and pushes the in-batch negatives down:
Maximizing the positive's share of the row's softmax makes the diagonal dominate — so at inference the top passage by dot product is the right one. Bigger batches mean more negatives per positive, which is why DPR benefits from large batch sizes. The runnable version below builds the B×B matrix and shows the diagonal winning.
How DPR is trained and served, step by step
Dense Passage Retrieval (Karpukhin, Oğuz, Min, Lewis, Wu, Edunov, Chen and Yih, EMNLP 2020) is a recipe more than an architecture: two off-the-shelf BERT encoders, a fixed passage format, a particular choice of negatives and a vector index. Each choice was tested, and the steps below are the configuration that won.
- Cut Wikipedia into passages. The English Wikipedia dump of 20 December 2018, stripped of tables, infoboxes, lists and disambiguation pages, is split into disjoint 100-word blocks: 21,015,324 passages. Each passage is prefixed with its article title and a [SEP] token.
- Encode with two BERTs. A question encoder EQ and a passage encoder EP, each an independent BERT-base (uncased), output the [CLS] vector, 768 numbers. Similarity is the plain dot product EQ(q) · EP(p).
- Find positives. For Natural Questions and SQuAD, the passage that matches the gold context is the positive. TriviaQA, WebQuestions and CuratedTREC have no gold passage, so the highest-ranked BM25 passage containing the answer is used instead, and questions with no such passage in the top 100 are dropped.
- Assemble negatives. Each question gets one BM25 hard negative: a top-ranked BM25 passage that does not contain the answer but matches most of the question's tokens. In a batch of B questions, every question is scored against all B gold passages and all B hard negatives, so it sees B − 1 in-batch negatives plus B hard ones.
- Optimise. Batch size 128, Adam at a learning rate of 10^−5 with linear warm-up and decay, dropout 0.1, up to 40 epochs on the large datasets and 100 on the small ones (WebQuestions and CuratedTREC). A multi-dataset model is trained on the union of every training set except SQuAD.
- Index offline. Encode all 21 million passages once — the paper reports about 8.8 hours on 8 GPUs — and load the vectors into FAISS for maximum-inner-product search.
- Retrieve and read. At query time encode only the question, take the top k passages, and hand them to a BERT-based reader that scores each passage and extracts an answer span. With FAISS the paper retrieved the top 100 passages for 995 questions per second, against 23.7 questions per second per CPU thread for a Lucene BM25 index.
- Optionally fuse with BM25. The hybrid takes the top 2,000 passages from each system and re-ranks the union by BM25(q, p) + λ · sim(q, p), with λ = 1.1.
The negative-type ablation, run on the Natural Questions development set, is what fixed steps 4 and 5. Random passages, BM25 passages and other questions' gold passages were each tried as negatives without in-batch reuse and ended up close to one another; reusing the batch's gold passages was clearly better and improved as the batch grew; and one BM25 hard negative per question on top added the largest single gain. A second BM25 negative did not help further.
The DPR loss with in-batch and BM25 negatives
Li = −log exp s(qi, pi^+) / [ exp s(qi, pi^+) + Σj exp s(qi, pj^−) ]
S = Q · [P^+ ; P^BM25]^⊤ is B × 2B, so each question has 2B − 1 negatives
hybrid re-rank: BM25(q, p) + λ · s(q, p), λ = 1.1
EQ, EP— two separate BERT-base encoders, each returning its [CLS] vector of 768 numbers.pi^+— question i's positive: the gold context where one exists, otherwise the top BM25 passage that contains the answer.pj^−— every other passage scored in the batch: the other B − 1 gold passages and all B BM25 negatives.S— the whole batch's scores in one matrix product of question vectors against passage vectors.λ— the weight that puts the dense score on a scale comparable with BM25 in the hybrid.
At the extremes: with B = 1 and no hard negative the softmax has a single entry, the loss is always zero and nothing is learned; with in-batch negatives only, the model learns to reject passages about unrelated questions but rarely meets a plausible wrong one. That is why adding one BM25 negative per question moved top-20 accuracy on the Natural Questions development set from 73.0 to 78.0 at batch size 128. The paper also tried cosine and Euclidean similarity and a triplet loss: the dot product and Euclidean distance performed about the same, both beat cosine, and the triplet loss changed little.
DPR against BM25, dataset by dataset
Retrieval is measured as top-k accuracy: the share of test questions for which at least one of the top k retrieved passages contains the answer. The baseline is Lucene BM25 over the same 21 million passages, and the rows below are the single-dataset DPR models.
| Dataset | BM25 top-20 | DPR top-20 | BM25 top-100 | DPR top-100 |
|---|---|---|---|---|
| Natural Questions | 59.1 | 78.4 | 73.7 | 85.4 |
| TriviaQA | 66.9 | 79.4 | 76.7 | 85.0 |
| WebQuestions | 55.0 | 73.2 | 71.1 | 81.4 |
| CuratedTREC | 70.9 | 79.8 | 84.1 | 89.1 |
| SQuAD v1.1 | 68.8 | 63.2 | 80.0 | 77.2 |
On four datasets the gain at top-20 is 9 to 19 points. SQuAD is the negative result, and the paper explains it: annotators wrote the questions while looking at the passage, so question and passage share many words, which favours BM25; and the training questions come from only about 500 Wikipedia articles, so the encoder learns from a narrow slice. Fusing the two scores recovered it, with the hybrid reaching 71.5 at top-20.
Two further results made dense retrieval practical. Trained on only 1,000 Natural Questions examples, DPR already beat BM25 at top-20, so the method did not need massive supervision. And better passages carried through to answers: with the paper's extractive reader, exact match on Natural Questions was 41.5 with DPR's passages against 32.6 with BM25's, ahead of the earlier dense-retrieval systems ORQA (33.3) and REALM (40.4), both of which needed extra pretraining.
What the authors admit, and what happened next
In-batch negatives are cheap and easy: a random passage is almost always obviously wrong, so the model learns to reject the obvious and not to discriminate among plausible candidates. The paper addresses this by mixing in hard negatives — high-scoring wrong passages retrieved by a keyword system — and the improvement from doing so is large. The general lesson is worth more than the detail: a contrastive model is only as good as its hardest negatives, and free negatives are free because they are easy.
The other limitation is that the relation is trained, and therefore tied to the distribution it was trained on. Dense retrievers of this kind were repeatedly found to generalise worse than keyword scoring on out-of-domain collections — which is an unfashionable result that has held up, and the reason hybrid retrieval (dense plus keyword, scores combined) is the default production answer rather than a compromise.
How it held up: it established the dual-encoder-plus-vector-index architecture that every retrieval system on this site uses, and it made "train the retriever" an obvious step rather than an exotic one. Its own weakness — that compressing a passage into one vector loses term-level detail — is what rung 7 attacks directly.
In-batch negatives, from scratch
DPR scores every question against every passage in the batch — a B×B dot-product matrix. The diagonal is each question's positive passage; the off-diagonal entries are free negatives, so a batch of B gives B×(B−1) of them with no extra encoding. On a well-separated batch the diagonal similarity beats every negative in its row, retrieval by dot product picks the aligned passage, and in-batch accuracy is perfect. Change the embeddings or the batch and watch the matrix and the ranking shift.
Write the body of in_batch_accuracy. Everything else in the file is
already written; this is the function the paper is about. Press ▶ Run to check it against
the 5 assertions below — they start red.
- The similarity matrix is B x B (every query scored against every passage)
- In-batch negatives are free: a batch of B gives B*(B-1) negatives
- Dense retrieval ranks the aligned passage first by dot product
- The positive (diagonal) similarity exceeds every negative in its row
- In-batch training reaches perfect accuracy on separable embeddings
The retrieval default
DPR is a foundation stone of modern retrieval-augmented generation. The pattern it standardized — dual-encoder embeddings, dot-product matching, a vector index for fast search — is exactly how "chat with your documents" systems retrieve today. Every embedding-based retriever and vector database owes something to the recipe DPR made work, and in-batch negatives became a default technique for training contrastive embedding models well beyond QA.
It also marked a boundary later work pushed on. A single dense vector per passage can blur fine detail, which motivated late-interaction methods like ColBERT that keep per-token vectors, and hybrid systems that combine dense retrieval with BM25 to recover exact-match strengths. But the core lesson endures: match on meaning, encode passages offline, and train with cheap in-batch negatives. DPR turned retrieval from a keyword-matching problem into a representation-learning one — and that shift underlies the whole retrieval stack we build on now.
In-batch negatives are "easy" negatives — random other passages, usually obviously wrong. DPR found that adding a few hard negatives (e.g. high-BM25 passages that look relevant but aren't) on top of the in-batch ones sharpened the model further, since it forced finer distinctions.
Questions people ask about Dense Passage Retrieval
How does DPR use BM25 hard negatives?
For each training question, DPR retrieves passages with BM25 and picks a top-ranked one that does not contain the answer but matches most of the question's words: a passage that looks right and is wrong. That passage joins the batch as a hard negative. Because every question in a batch is scored against every passage in the batch, each question sees its own BM25 negative plus every other question's, alongside the other questions' gold passages; with batch size 128 that is 127 in-batch negatives and 128 BM25 negatives. On the Natural Questions development set, adding one BM25 negative per question raised top-20 retrieval accuracy from 73.0 to 78.0, and a second one did not help. Random passages are easy to reject; hard negatives force the fine distinctions.
Why does BM25 beat DPR on SQuAD?
SQuAD questions were written by annotators who were looking at the passage, so they reuse its exact words, which is the situation keyword matching handles best. The DPR paper also notes that SQuAD's training questions come from only about 500 Wikipedia articles, so a dense encoder trained on them learns from a narrow, biased slice of topics while retrieval runs over all 21 million passages. The result is the paper's one dataset where BM25 won: top-20 accuracy of 68.8 against 63.2 for DPR, and 80.0 against 77.2 at top-100. Combining the two scores recovered the loss, with the hybrid reaching 71.5 at top-20. Later benchmarks such as BEIR found the same pattern more broadly: lexical overlap and domain shift both favour BM25, which is why hybrid retrieval is common in production.
How many training examples does DPR need to beat BM25?
Surprisingly few. In the DPR paper's sample-efficiency experiment on Natural Questions, a dense retriever trained on only 1,000 question-passage pairs already exceeded BM25's top-20 retrieval accuracy, and accuracy kept rising as more of the roughly 59,000 training questions were added. The paper credits strong pretrained BERT encoders: they already represent meaning well, and fine-tuning only has to align questions with answering passages. It also found that an encoder trained on Natural Questions alone transferred to WebQuestions and CuratedTREC without further training, somewhat below in-domain training but still ahead of BM25. Robustness on very different corpora proved more limited, which later benchmarks such as BEIR documented, so a little in-domain data still goes a long way.
Does DPR use the CLS token or mean pooling, and why the dot product?
DPR uses the [CLS] output of each of two separate BERT-base encoders, one for questions and one for passages, giving 768-dimensional vectors. It scores with the plain dot product because passage vectors can then be searched with maximum inner product search in FAISS, and because in the paper's ablation the dot product and Euclidean distance performed about equally while cosine similarity did worse. Replacing the softmax loss with a triplet loss also made little difference. The two encoders do not share weights, so each can specialise for its side. Every passage is encoded once, offline, with its Wikipedia article title prepended, and only the question encoder runs at query time.
How does DPR's hybrid with BM25 work?
The DPR paper's hybrid takes the top 2,000 passages from BM25 and the top 2,000 from the dense index, and re-ranks their union by a linear combination of the two scores, BM25(q, p) + λ · sim(q, p), with λ = 1.1. It helped most where BM25 was strong: on SQuAD it lifted top-20 accuracy from 63.2 for DPR alone to 71.5, while on Natural Questions it came out slightly below DPR alone. The two retrievers fail differently — BM25 on paraphrase, dense retrieval on rare exact strings such as names and codes — so combining them is cheap insurance. Many production systems now fuse the two rankings, for example with reciprocal rank fusion, rather than the raw scores, which avoids tuning a weight like λ.
4 questions to test what you just read
Work each one out before you open it — a number, a prediction or a reason, not a definition. Producing the answer is what makes it stick. Your progress is kept on this device.
With batch size 128 and one BM25 negative per question shared across the batch, how many negatives does each question’s softmax contain?
Show answer
The score matrix is 128 × 256: 128 gold passages and 128 BM25 negatives. One column is the question’s own positive, so it has 127 + 128 = 255 negatives — from encoding just 256 passages for the whole batch.
Stored as 768 float32 values each, how much memory do all 21,015,324 passage vectors need in a flat index?
Show answer
21,015,324 × 768 × 4 bytes ≈ 64.6 GB, about 60 GiB. A single-vector index over Wikipedia already needs a large server, which is why compression such as product quantization is attractive at this scale.
On Natural Questions, top-20 accuracy rose from 59.1 with BM25 to 78.4 with DPR. What share of BM25’s failures did DPR fix?
Show answer
BM25 failed on 100 − 59.1 = 40.9% of questions; DPR fails on 21.6%. It removed (40.9 − 21.6) / 40.9 ≈ 47% of the failures — nearly half, which is a more telling way to read a 19-point gain.
What training signal does DPR get with B = 1 and no hard negative, and why do in-batch negatives alone leave the model weak on plausible distractors?
Show answer
With B = 1 the softmax has one entry, its probability is always 1, the loss is 0 and nothing is learned. With in-batch negatives only, the wrong passages answer unrelated questions and are easy to reject, so the model rarely has to separate a passage that merely shares the question’s words from one that answers it. One BM25 negative per question supplies exactly those cases.
From a word vector to RAG
The longest ladder here, and the most linear: nine papers that carry one idea — text as geometry — from a 2013 word embedding to a graph-structured retrieval system.
- 1Word2Vec2013
- 2GloVe2014
- 3Sentence-BERT2019
- 4Product Quantization2011
- 5HNSW2016
- 6Dense Passage Retrieval2020
- 7ColBERT2020
- 8Retrieval-Augmented Generation2020
- 9GraphRAG2024
Explore the topic
See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.
More Paper Breakdowns
- Attention Is All You NeedThe paper that introduced the Transformer — the architecture underneath GPT, BERT, Claude, and Gemini. Self-attention, Query/Key/Value, multi-head attention, positional encoding, and the real BLEU results, explained in depth with analogies and animated visuals, not just equations.Read →
- Retrieval-Augmented GenerationThe paper behind every "chat with your docs" product. Pair a generator with a neural retriever so the model looks knowledge up instead of memorizing it — dense retrieval, top-k documents, RAG-Sequence vs RAG-Token, and why retrieval cuts hallucination.Read →
- Word2VecHow words became math. Dense word vectors learned from the company a word keeps, so king − man + woman lands near queen. Skip-gram, CBOW, the distributional hypothesis, and the origin of every embedding model powering search and RAG.Read →
- ResNetThe skip connection that made deep learning deep. Why stacking layers made networks worse, and how residual learning let them reach 150+ layers and win ImageNet — the identity shortcut every Transformer still uses inside every block.Read →
- Vision Transformer (ViT)When an image became 16×16 words. Cut a picture into patches, treat each patch as a token, and feed them to a plain Transformer — no convolutions. Patch embeddings, the class token, and why data scale lets attention beat the CNNs that ruled computer vision for a decade.Read →
- Latent DiffusionThe paper behind Stable Diffusion. Compress an image into a small latent space with a VAE, run the diffusion denoising there instead of on pixels for a tens-of-times efficiency win, and steer it with text via cross-attention. The architecture that put text-to-image generation on consumer GPUs.Read →