RAGEngineering Hub
Chapter 7 · concept 4 of 6 · show all
  1. 1What RAG is, and why
    1. 1.1Why models need outside knowledge, and what hallucination means
    2. 1.2What RAG is: anatomy of a request
    3. 1.3RAG vs fine tuning vs long context and prompt caching
    4. 1.4Use cases and the quality, latency and cost triangle
    5. Chapter overview
  2. 2Tokens, cost and your first RAG
    1. 2.1Tokens and context windows for RAG
    2. 2.2The RAG lifecycle and your first RAG in miniature
    3. Chapter overview
  3. 3Getting documents in
    1. 3.1Content sources and file formats
    2. 3.2Parsing, layout and OCR
    3. 3.3Tables, images and mixed content
    4. 3.4Cleaning, normalization and quality gates
    5. 3.5Metadata, document identity and versioning
    6. 3.6Updates, deletes, reindexing and ingestion pipelines
    7. Chapter overview
  4. 4Chunking
    1. 4.1Why we chunk, and the main chunking strategies
    2. 4.2Structure aware chunking and tables
    3. 4.3Chunk size, overlap and token based sizing
    4. 4.4Contextual chunking and late chunking
    5. 4.5Parent child and multi representation indexing
    6. 4.6Chunk metadata, provenance and the chunking debugging playbook
    7. Chapter overview
  5. 5Embeddings
    1. 5.1Embeddings and similarity from first principles
    2. 5.2What embeddings cannot do
    3. 5.3Choosing an embedding model: size, cost, language
    4. 5.4Embedding model migration and index rebuilds
    5. Chapter overview
  6. 6Vector stores and scores
    1. 6.1Vector databases, ANN indexes and choosing a store
    2. 6.2Score calibration and thresholds
    3. 6.3Late interaction and multivector retrieval
    4. Chapter overview
  7. 7Finding the right chunks
    1. 7.1Query understanding, rewriting and expansion
    2. 7.2Dense retrieval and keyword search with BM25
    3. 7.3Hybrid retrieval and rank fusion
    4. 7.4topK, no good match, and metadata filtering
    5. 7.5Routing, diversity, deduplication and caching
    6. 7.6Reranking: two stage, cross encoder and LLM rerankers
    7. Chapter overview
  8. 8When retrieval fails
    1. 8.1Retrieval failure analysis playbook
    2. Chapter overview
  9. 9Building the answer
    1. 9.1Context selection, packing and citations
    2. 9.2Grounding prompts and abstention
    3. 9.3Lost in the middle and context management
    4. 9.4Conflicts, staleness and freshness rules
    5. 9.5Hallucination checks and answer verification
    6. 9.6Conversational RAG, answer UX and RAG APIs
    7. Chapter overview
  10. 10Measuring
    1. 10.1Why measure, and what to measure
    2. 10.2Building a golden dataset
    3. 10.3Retrieval metrics: precision, recall, MRR, nDCG
    4. 10.4Faithfulness and answer correctness
    5. 10.5LLM as judge, and judging the judge
    6. 10.6Offline and online evals, regression tests and slices
    7. Chapter overview
  11. 11Safety and operations
    1. 11.1Prompt injection and poisoned documents
    2. 11.2Access control, privacy and governance
    3. 11.3Index lifecycle operations
    4. 11.4Observability and tracing
    5. 11.5Latency, cost, caching and model routing
    6. 11.6Reliability, degraded modes and launch readiness
    7. Chapter overview
  12. 12Scale and advanced RAG
    1. 12.1Scaling, multi tenancy and enterprise architecture
    2. 12.2Choosing an architecture: naive, advanced, agentic, graph
    3. 12.3Agentic RAG and RAG as an MCP tool
    4. 12.4GraphRAG, structured data and multimodal RAG
    5. Chapter overview

topK, no good match, and metadata filtering

How many chunks to pass on, what to do when none fit, and how filters on version, date and access remove wrong candidates before ranking. Measured recall and token cost per k.

A real question

Should the model get 3 chunks, 10 chunks, or none at all?

Enough to hold the answer and no more. Measure recall at each k, filter out wrong versions and forbidden documents first, and let the system say when nothing fits.

The problem

Why this matters

Send more chunks; the model will find the answer somewhere.
The belief

Send more chunks; the model will find the answer somewhere.

With hybrid search, the top 3 already held all 47 answers in 884 tokens. The top 10 held the same 47 in 2,704 tokens: three times the cost, plus more distractors for the model.
What really happens

With hybrid search, the top 3 already held all 47 answers in 884 tokens. The top 10 held the same 47 in 2,704 tokens: three times the cost, plus more distractors for the model.

Why not the simpler way

k is often set once, to 5 or 10, and never revisited. Too small and answers are missed; too large and every question costs more, takes longer, and gives the model more wrong text to be confused by (RAG-35). Meanwhile, chunks from last year's price list or a restricted runbook compete for the same slots.

The idea

The idea in plain words

Three decisions sit between search and the prompt. How many chunks to keep (k). Which chunks are allowed at all (metadata filters). Whether any chunk is good enough (no good match).

Packing for a trip: decide how many bags you can carry, leave behind what is not allowed on the plane, and if nothing fits the trip, do not go.

How it works

Step by step

  1. Count how often the answer is in the top 1, 3, 5 and 10. Pick the smallest k where the curve flattens.
    1

    Measure recall at each k

    Count how often the answer is in the top 1, 3, 5 and 10. Pick the smallest k where the curve flattens.

  2. Drop chunks from the wrong version, date, language or access role before ranking, so they cannot take a slot.
    2

    Filter first

    Drop chunks from the wrong version, date, language or access role before ranking, so they cannot take a slot.

  3. If nothing passes, pass nothing and say so. A low score cut-off and a prompt that allows “I don't know” work together.
    3

    Allow no good match

    If nothing passes, pass nothing and say so. A low score cut-off and a prompt that allows “I don't know” work together.

In detail

k from data. With vector search alone, our recall at 1, 3, 5 and 10 was 0.638, 0.936, 0.979 and 1.000; with hybrid it was 33, 47, 47 and 47 of 47. A reranker (RAG-31) lets you retrieve 10 and pass 3.

Filters. Version validity (effective_from and effective_to), language, product line, and access roles are metadata on each chunk (RAG-18). In RAG-11, a validity date filter raised the right version at rank 1 from 2 of 5 to 4 of 5 questions. Pre-filtering is exact; filtering inside an ANN index can lower recall when the filter is very narrow (RAG-22).

No good match. A low similarity cut-off blocks off-topic questions (RAG-23). For near-topic questions, the model must be allowed to answer "I don't know based on these documents" (RAG-34).

The code

Try it in Python

from datetime import date

def candidates(chunks, user_roles: set[str], on: date, lang: str | None = None):
    for c in chunks:
        m = c["meta"]
        if m["allowed_roles"] and not user_roles & set(m["allowed_roles"]):
            continue                                   # access first, always
        if m["effective_from"] > on or (m["effective_to"] and m["effective_to"] < on):
            continue                                   # wrong version for this date
        if lang and m["language"] != lang:
            continue
        yield c

def retrieve(question, chunks, user, k=3, min_score=0.60):
    pool = list(candidates(chunks, user.roles, date.today()))
    ranked = hybrid_search(question, pool)
    return [c for c in ranked[:k] if c.vector_score >= min_score]   # may be empty: say so

See it

What we measured

Measured · answers in the top k, and context size

Polder corpus, 34 recursive 512 token chunks, 47 golden questions, hybrid search (BM25 + bge-small, RRF). Tokens counted with our tokenizer over the chunk texts.

k = 1309 tokens33 of 47
k = 3884 tokens47 of 47
k = 51,466 tokens47 of 47
k = 102,704 tokens47 of 47
Version filter (from RAG-11)right version first 2 of 54 of 5

Measured 2026-11-04 with corpus/scripts/measure-parts-4-7.mts; version filter measured 2026-11-03. Token counts are averages per question.

Try it on a real example

Hybrid search on 47 questions: what each k costs and finds

Top
1.309 tokens on average · 33 of 47Cheapest, misses 14 answers.–

Too few: the right chunk is often second or third.

Choosing

Use it when, avoid it when

Use it when
  • k from a recall curve, often 3 to 5 after a reranker
  • Filters on version, date, language and access before ranking
Avoid it when
  • Large k as a safety margin
  • Access checks applied only after ranking or in the prompt

What it costs · Each extra chunk adds about 300 tokens per question on our corpus. Filters cost almost nothing.

In production

Log k, the filters applied and the number of candidates left after filtering for every query. A filter that leaves zero candidates is a bug or a missing document, and should be visible, not silently turned into an empty context. Access filters must use the user's identity from the session, never a value the user can type (RAG-46).

Watch out

Common mistakes

  • More context is safer. It costs more and gives the model more to get wrong.
  • Filters lower recall. Wrong-version chunks were never the answer.
  • An empty result is an error. It is the honest answer when nothing fits.

Check yourself

Remember this

Remember these

  • Choose k from a recall curve on your golden set.
  • On our corpus k = 3 held all 47 answers with hybrid search.
  • Filter by version, date and access before ranking.
  • When nothing fits, pass nothing and let the system say so.

Say it in an interview

  1. 01I pick k from a recall curve; on my corpus hybrid search hit 47 of 47 at k = 3.
  2. 02Going from k = 3 to 10 tripled tokens, 884 to 2,704, for no new answers.
  3. 03I filter by version, date and access before ranking so wrong chunks never take a slot.
  4. 04A validity filter raised the right version first from 2 to 4 of 5 questions.
  5. 05When nothing passes, the system says it does not know instead of guessing.

Quick quiz

Three questions

Question 1

Q1

With hybrid search, going from top 3 to top 10 did what on our corpus?

Question 2

Q2

Why filter by metadata before ranking rather than after?

Question 3

Q3 · from RAG-23

What did a 0.60 similarity cut-off do on our questions?

Saved on this device. No account needed.