Where we left off

Lesson 14 built a diagnostic for spotting a sparse-favoring query in advance. This lesson builds the mirror: a diagnostic for spotting a dense-favoring one, by directly measuring how much vocabulary a query actually shares with its own correct answer.

The code, piece by piece

STOPWORDS = {"a", "an", "and", ..., "why", ...}
def tokenize(text: str) -> set[str]:
tokens = re.findall(r"[a-z0-9]+", text.lower())
return {token for token in tokens if token not in STOPWORDS}

Function words ("why," "does," "my") show up in nearly every document regardless of topic. Counting them as "shared vocabulary" would be Lesson 3's raw-term-frequency mistake all over again, common words looking like a signal when they're really just noise every document has anyway.

def overlap_ratio(query, document_text) -> float:
shared = tokenize(query) & tokenize(document_text)
return len(shared) / len(tokenize(query))

What fraction of the query's content tokens appear literally anywhere in the document that actually answers it? High overlap: sparse retrieval has real tokens to latch onto. Low overlap: it doesn't, and dense retrieval has to carry the question on meaning alone.

Checkpoint

  • Overlap ratio: the fraction of a query's content tokens (stopwords excluded) that appear in its correct answer, computed directly rather than guessed at from punctuation the way Lesson 14's heuristic did.
  • A high ratio predicts sparse retrieval has real signal; a low one (rarely a literal zero) predicts dense retrieval has to carry it, specifically because the technical vocabulary is missing, not because every single word is.
  • Together, Lessons 14 and 15 give two independent, cheap-to-compute signals for which retriever a query is likely to need, useful for intuition, not a replacement for running and fusing both.

If anything here still feels unclear, ask before moving to Lesson 16.