Hybrid Search: BM25 and Dense Retrieval Combined › BM25: The Classical Baseline
Language AI HandbookAll chapters Hybrid Search: BM25 and Dense Retrieval Combined › BM25: The Classical BaselineOne section · Sections in this chapter2 / 10 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Before dense retrieval existed, keyword-based ranking functions dominated information retrieval. The most durable of these is BM25 (Best Match 25), which dates to the 1990s and remains competitive against many modern systems on keyword-heavy benchmarks. Its staying power is not an accident of inertia: BM25 embodies a set of principled statistical insights about how term occurrence patterns relate to relevance, and those insights remain valid even in the age of large language models.
BM25 is a refinement of TF-IDF. Recall from earlier chapters that TF-IDF scores a term in a document by multiplying how often the term appears in the document (term frequency, or TF) by how rare the term is across all documents (inverse document frequency, or IDF). BM25 keeps this core intuition but fixes two structural problems with raw TF-IDF. The fixes are not cosmetic adjustments: they address basic failure modes that make raw TF-IDF unreliable in practice. Understanding these failure modes is the fastest path to understanding why BM25 is designed the way it is.
Think of BM25 as a more careful accountant than TF-IDF. TF-IDF is like an accountant who counts every dollar of evidence and adds it all up, even if the same dollar appears a hundred times. BM25 is like an accountant who correctly recognizes that after the tenth dollar of the same type, each additional dollar is worth only a fraction of the first. It also adjusts for the fact that longer reports naturally contain more dollars, and corrects for that structural bias. The result is a much fairer assessment of which documents truly contain the most relevant evidence.
BM25 emerged from the Okapi research project at City University London in the early 1990s, led by Stephen Robertson and colleagues. The name "Best Match 25" shows that it was the 25th iteration of a best-match weighting formula developed through systematic empirical testing on the TREC (Text Retrieval Conference) benchmark collections. The series began with simpler TF-IDF variants and evolved through progressively refined models that addressed observed failure modes. The core BM25 formula was described in Robertson et al. (1994) and Robertson and Walker (1994), with the version commonly used today sometimes called BM25 Okapi or BM25F (the F variant incorporating structural document fields). Despite its age, BM25 remains a competitive baseline on many modern information retrieval benchmarks, including BEIR, and is the keyword retrieval component in most production search systems, including Elasticsearch and Apache Solr.
The Two Problems BM25 Solves
The first problem is that raw TF grows without bound. If a document mentions the word "python" 100 times rather than 10 times, raw TF scores it 10 times higher. But in practice the relevance gain from the 50th mention of "python" is negligible compared to the gain from the first. BM25 saturates TF so that each additional occurrence contributes less than the previous one.
To make this concrete, imagine reading a book review. If the review mentions "fascinating" once, that tells you something. If it mentions "fascinating" twenty times, that tells you roughly the same thing, just more emphatically. The hundredth mention of "fascinating" adds no new information. BM25 captures this diminishing return mathematically: the scoring function curves upward steeply at first, then flattens to a ceiling as occurrences accumulate. The ceiling is determined by the hyperparameter , which you will see shortly.
The second problem is that longer documents naturally accumulate more term occurrences and therefore score higher even when they are no more relevant. A textbook chapter is longer than a blog post and will contain any given term more often, but that does not make the textbook chapter more relevant to a two-word query. BM25 applies a document length normalization that penalizes documents longer than average, keeping the playing field level. The strength of this penalty is controlled by the hyperparameter .
These two fixes, saturation and length normalization, are not independent adjustments bolted onto TF-IDF. They interact through a single elegant fraction at the heart of the BM25 formula. Understanding that fraction is the key to understanding the entire formula.
The BM25 Formula
BM25 computes a relevance score for a document given a query by summing term-level contributions. Each term's contribution multiplies a document-frequency weight (IDF) by a saturated term-frequency weight. For a query with terms and a document , BM25 scores the document as:
where:
- : the individual terms in query
- : the raw frequency of term in document (how many times it appears)
- : the length of document in tokens
- : the average document length across the entire corpus
- : the term frequency saturation parameter, typically set to 1.2 or 1.5; it controls how quickly additional occurrences of a term stop adding to the score
- : the length normalization parameter, typically set to 0.75; it controls how strongly longer documents are penalized relative to the average
It is worth pausing to appreciate the structure of this formula before looking at any of its parts in isolation. The outer sum iterates over every query term. For each term, you compute two independent quantities: how rare the term is across the entire corpus (the IDF factor on the left), and how heavily the term appears in this specific document adjusted for document length (the fraction on the right). These two numbers are multiplied together, and you accumulate the result across all query terms. The final BM25 score for a document is therefore a weighted sum of term-level evidence, where rarer terms contribute more heavily.
This structure shows a clear intuitive principle. A query like "transformer" combined with "myocardial" should give high weight to the term "myocardial" (rare) and lower weight to "transformer" (common in this hypothetical corpus). BM25 accomplishes this weighting automatically through IDF, without any manual synonym mapping or domain knowledge.
The IDF component measures how rare a term is across the corpus. Rare terms that appear in few documents receive high IDF weights, while common terms like "the" receive near-zero weights. The IDF term is computed as:
where:
- : the total number of documents in the corpus
- : the number of documents in the corpus that contain term
- : a smoothing constant added to both numerator and denominator to avoid division by zero and to prevent IDF from going negative for terms appearing in every document
- The inside the logarithm ensures the IDF is always non-negative, even when a term appears in all documents
To build intuition for this formula, consider the two extreme cases. When is very small relative to , meaning the term appears in almost no documents, the fraction becomes large, and the logarithm returns a large positive number. This makes sense: a term that appears in only 3 out of 1 million documents is extraordinarily informative when it does appear. When , meaning the term appears in nearly every document, the numerator approaches 0.5 and the denominator approaches , making the fraction nearly zero and the IDF close to . A term that appears in every document tells you nothing about which documents are more relevant.
Understanding the Saturation Term
The fraction within the BM25 sum handles two effects simultaneously: TF saturation and length normalization. These two effects are coupled through a single expression, and understanding their interaction reveals why BM25 is so reliable across diverse corpora. Focusing on this fraction:
This fraction looks intimidating at first glance, but it has a clean structure once you name its moving parts. The numerator scales the raw term frequency by , which is a constant for any given setting of . The denominator adds the raw term frequency to a document-length-dependent constant. That constant is where the two effects live.
Define the denominator's length-dependent constant as:
where:
- and are the BM25 hyperparameters defined above
- : the ratio of document length to average document length; values above 1.0 mean the document is longer than average
Notice what encodes. The term grows as the document grows relative to the average. When and a document is twice the average length, the ratio is 2.0, and this term contributes to the expression inside the outer parentheses. When a document is exactly average length, the ratio is 1.0, and the expression inside the parentheses equals exactly. So equals for an average-length document and grows proportionally for longer documents. This is the length normalization embedded in .
With this substitution, the saturation fraction becomes:
This is now recognizable as a hyperbolic function of (the term frequency). To understand the saturation behavior, consider what happens as term frequency grows:
- As , the fraction approaches , not infinity. This is the saturation ceiling: no matter how many times a term appears, the contribution is bounded above by .
- When , the fraction equals , exactly half the maximum. This means controls the "half-saturation point": the term frequency at which the score reaches half its ceiling.
- itself depends on document length via . Longer documents have a larger , meaning they need more term occurrences to reach the same score as a shorter document. This is the length normalization effect.
The interplay between saturation and length normalization is elegant: a document that is twice as long as average must also have roughly twice the term frequency to reach the same BM25 score as the shorter document. This keeps the scoring fair across documents of different lengths.
The key insight is that BM25 treats the saturation ceiling and the half-saturation point as linked quantities: both are controlled by the same expression. When you tune and , you are not adjusting two independent knobs. You are adjusting a single parameterized family of scoring functions where the saturation speed and the length sensitivity move together in a coordinated way. This coupling is what makes BM25 well-behaved across diverse corpora with different length distributions.
The coupling between saturation and length normalization through makes BM25 a unified formula rather than two separate adjustments patched together. When you increase , you make more sensitive to document length, which simultaneously raises the half-saturation point for longer documents. When you increase , you raise both the saturation ceiling and the scale of , effectively making the saturation happen more slowly everywhere. The two hyperparameters interact in a predictable way.

The visualization makes the saturation property concrete. With (bottom curve), the score saturates almost immediately: going from 1 occurrence to 5 occurrences barely moves the score. With (top curve), the score continues growing through 10 or more occurrences, giving more credit to documents with many term repetitions. The default sits between these extremes, saturating moderately and making each of the first few occurrences count while capping the contribution of very high frequencies.

The logarithmic x-axis reveals the full range of IDF behavior. A term appearing in 10 out of 10,000 documents (0.1% of the corpus) receives an IDF of roughly 6.9, while a term appearing in 9,000 documents (90% of the corpus) receives an IDF near zero. This nonlinear weighting means that going from "appears in 10 documents" to "appears in 100 documents" causes a significant IDF drop, while going from "appears in 5,000 to 9,000 documents" causes almost no change because both are already near zero. BM25 is most sensitive to term rarity at the rare end of the spectrum.
A Worked Numerical Example
To make the BM25 formula completely concrete, let us trace through all computations step by step on a tiny corpus. This kind of worked example is invaluable because the formula combines several interacting quantities, and watching them interact numerically builds intuition that the formula alone cannot convey.
Consider a tiny corpus with three documents:
- : "the cat sat on the mat" (6 tokens)
- : "the cat sat on the cat mat mat cat" (9 tokens)
- : "the dog chased the cat across the yard" (8 tokens)
Average document length: tokens.
Query: "cat mat"
Step 1: Compute IDF for each query term.
For term "cat": appears in all 3 documents, so , .
Since "cat" appears in every document, its IDF is very low. This shows that it is not a discriminating term for this query. Every document contains "cat," so knowing a document contains "cat" tells you almost nothing about which document is most relevant. The IDF correctly suppresses its influence.
For term "mat": appears in and , so .
"mat" is rarer (absent from ), so it receives a higher IDF weight. This makes sense: knowing a document contains "mat" is more informative than knowing it contains "cat," because "mat" narrows the field.
Step 2: Compute the length-dependent constant for .
Using , , , :
The ratio tells us is about 17% longer than average. The constant is larger than it would be for an average-length document (where would equal ). This larger raises the half-saturation threshold, meaning needs more term occurrences to reach the same score as an average-length document.
Step 3: Compute TF contributions for "cat" in and .
TF contribution of "cat" in (frequency = 3):
For : .
TF contribution of "cat" in (frequency = 1):
Step 4: Assemble the full BM25 scores.
For (cat: f=1, mat: f=1):
For (cat: f=3, mat: f=2), first computing the mat TF contribution:
For (cat: f=1, mat: f=0), :
The final ranking is , which matches our intuition perfectly. contains "cat" three times and "mat" twice in a document only slightly longer than average. contains both terms once each. contains "cat" but no "mat" at all. The BM25 formula has automatically combined term frequency evidence, rarity evidence, and document length adjustment into a single, principled score.
gets a higher TF score for "cat" despite its longer length, because its term frequency (3) is much higher than 's (1). The length penalty embodied in slows but does not stop the gain from additional occurrences. The "mat" term, being rarer (IDF = 0.470 vs. 0.134 for "cat"), contributes more per occurrence to the final score than "cat" does. This automatic rarity weighting is BM25's key advantage over simple term counting.

This plot makes the length normalization effect visible. At (no length normalization), all four document lengths receive the same TF contribution score: length is completely ignored. As increases toward 1.0, the curves spread apart. Documents shorter than average (length ratio 0.5) receive a bonus: their TF contributions rise. Documents longer than average (length ratio 2.0) are penalized: their TF contributions fall. At the default (dashed vertical line), the curves are moderately separated, applying a partial correction for length without fully leveling the field.