RAGEngineering Hub
Chapter 6 · concept 2 of 3 · 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

Score calibration and thresholds

Can a similarity cut-off tell "no good match" from a real answer? We scored 47 answerable and 15 unanswerable questions; the ranges overlap, so a threshold is one guard, not the guard.

A real question

The best chunk scored 0.84. Does that mean the answer is in it?

Not necessarily. On our corpus, a question with no answer scored as high as the best real one. A score threshold can catch questions that are far off topic, but not near misses.

The problem

Why this matters

Pick a cut-off like 0.7: above it the chunk is relevant, below it the system says “I don't know”.
The belief

Pick a cut-off like 0.7: above it the chunk is relevant, below it the system says “I don't know”.

Answerable questions scored 0.57 to 0.84. Questions with no answer scored 0.43 to 0.84. Any cut-off either loses good questions or lets bad ones through.
What really happens

Answerable questions scored 0.57 to 0.84. Questions with no answer scored 0.43 to 0.84. Any cut-off either loses good questions or lets bad ones through.

Why not the simpler way

A RAG system that always answers will make something up when the documents have nothing. The obvious fix is a score cut-off: if the best chunk is not similar enough, say "I don't know". It works for "what is the capital of Australia?" and fails for "does my home insurance cover my car?", which is the kind of question real users ask.

The idea

The idea in plain words

Calibration means a score you can read as a probability: 0.8 means right 80% of the time. Cosine similarity is not calibrated. Its range depends on the model (our multilingual e5 scored an unrelated pair 0.780; bge-small 0.391), on the corpus and on how the question is phrased. BM25 scores are not even bounded: our top BM25 scores ranged from 5.1 to 24.9 across questions.

A thermometer that reads 0.7 tells you nothing until you know whether it is in Celsius, Fahrenheit or a scale its maker invented.

How it works

Step by step

  1. 1

    Collect both kinds

    Use your golden questions, plus questions you know the corpus cannot answer: off topic and near topic.

  2. For each question, record the best chunk's score. Plot the two groups and see where they overlap.
    2

    Look at the top score

    For each question, record the best chunk's score. Plot the two groups and see where they overlap.

  3. Set the cut-off to block only clear misses. Leave near misses to a reranker and a prompt that allows “I don't know”.
    3

    Low cut-off, more checks

    Set the cut-off to block only clear misses. Leave near misses to a reranker and a prompt that allows “I don't know”.

In detail

Measure, then choose. For each question, take the top score. Sweep cut-offs and count two things: answerable questions kept, and unanswerable ones blocked. Pick the cut-off by which mistake costs more in your product.

Better signals than one raw score. A cross-encoder reranker (RAG-31) reads question and chunk together, so its score is a closer look at the same pair; calibrate it on your golden set the same way before trusting it. We did not measure reranker cut-offs here. The gap between the first and second score is another signal. The strongest guard is the answer model itself, told to answer only from the context and to say when it cannot (RAG-34).

Per-model, per-corpus. A cut-off tuned for one embedding model is wrong for the next. Re-tune after every model or corpus change.

The code

Try it in Python

def sweep(top_answerable: list[float], top_unanswerable: list[float]):
    for t in [0.50, 0.55, 0.60, 0.65, 0.70, 0.75]:
        kept = sum(s >= t for s in top_answerable)
        blocked = sum(s < t for s in top_unanswerable)
        print(f"cut-off {t:.2f}: kept {kept}/{len(top_answerable)}, blocked {blocked}/{len(top_unanswerable)}")

# Choose the cut-off from this table, by which mistake your product can afford.

See it

What we measured

Measured · top cosine score per question, and a cut-off sweep

Polder corpus, 34 recursive 512 token chunks, bge-small. 47 answerable golden questions; 15 unanswerable: 5 from the golden set and 10 we wrote (5 off topic, 5 near topic).

Answerable: low / median / high0.57 / 0.71 / 0.84
Unanswerable: low / median / high0.43 / 0.64 / 0.84
Cut-off 0.60: kept · blocked46 of 474 of 15
Cut-off 0.65: kept · blocked36 of 478 of 15
Cut-off 0.70: kept · blocked25 of 4710 of 15
Cut-off 0.75: kept · blocked14 of 4711 of 15

Measured 2026-11-04 with corpus/scripts/measure-parts-4-7.mts. One unanswerable question (the duty manager escalation) has an answer in a restricted document; for a public user it counts as unanswerable.

Try it on a real example

Top similarity for questions the corpus cannot answer

Show
1.Who won the football world cup in 2014? · 0.433No telecom, bank or insurance topic at all.–
2.What is the capital of Australia? · 0.481Off topic.–
3.How do I bake sourdough bread? · 0.495Off topic.–

All three fall below every answerable question (lowest 0.57). A cut-off catches these.

Choosing

Use it when, avoid it when

Use it when
  • A low cut-off to drop clearly off-topic questions
  • Reranker scores, calibrated on your golden set, for finer decisions
Avoid it when
  • One fixed cut-off copied from a tutorial or another model
  • A cut-off as the only way to say I don't know

What it costs · A sweep on the golden set takes minutes. Recalibrate after every model or corpus change.

In production

Log the top score of every query. A drop in the median after a release is an early warning that the corpus or the model changed. Track how often the system abstains: rising abstention can mean a missing document, falling abstention can mean a cut-off that was loosened by mistake. Keep near-topic unanswerable questions in the golden set so every change is tested against them.

Watch out

Common mistakes

  • 0.7 is a standard threshold. There is no standard; it depends on the model and corpus.
  • High score, answer present. The highest score of all here belonged to an unanswerable question.
  • BM25 scores can be thresholded the same way. They are not bounded and vary from query to query.

Check yourself

Remember this

Remember these

  • Raw scores are relative to the model, the corpus and the query.
  • Measure both answerable and unanswerable questions before picking a cut-off.
  • A low cut-off (0.60 here) blocked clear misses and kept 46 of 47 good questions.
  • Near-topic questions need a reranker or the answer model to say “I don't know”.

Say it in an interview

  1. 01Cosine scores are not calibrated; their range depends on model, corpus and query.
  2. 02On my corpus answerable questions scored 0.57 to 0.84 and unanswerable 0.43 to 0.84.
  3. 03A 0.60 cut-off kept 46 of 47 good questions and blocked only the off-topic ones.
  4. 04Near-topic questions need a reranker or the model to abstain, not a stricter cut-off.
  5. 05I keep unanswerable questions in the golden set so every change is tested on them.

Quick quiz

Three questions

Question 1

Q1

At a cut-off of 0.65, what happened on our questions?

Question 2

Q2

Why did "Does home contents insurance cover my car?" score 0.79?

Question 3

Q3 · from RAG-20

Embeddings capture which of these well?

Saved on this device. No account needed.