Fintech

How to Set a Minimum Similarity Score for Retrieval Answers

Antonio Evans8 min read

A line chart with minimum similarity score on the horizontal axis and two falling curves: the share of queries answered in blue and the share of answers that are wrong in red.
Key points

Key points

  1. 1A similarity score measures how close a query vector is to a chunk vector, and the cutoff decides which chunks are allowed to become evidence for the answer.
  2. 2Build a labeled set of a few hundred real queries marked as having a correct passage or not, then score each one with your actual retriever.
  3. 3Sweep the threshold and count misses (correct passage excluded, so the agent hands off) and wrong answers (no correct passage, but the top score passes).
  4. 4Convert both counts to cost with a ratio, because a handoff costs time and a wrong answer costs trust, support load or a compliance incident.

What the score actually measures

Retrieval starts with embeddings: the query and each document chunk become vectors, and the system compares them numerically. Cosine similarity is the usual metric, computed as the dot product of the two vectors divided by the product of their magnitudes, so a perfect match scores 1 and unrelated text scores near 0 (a retrieval settings walkthrough).

Three complications matter before you set a number.

Dot product is not cosine. Dot product and cosine agree only when vectors are normalized to unit length. An unnormalized dot product rewards long vectors as well as similar ones, so the same threshold means different things across index settings.

Hybrid systems change the scale. Many stacks combine a keyword ranker such as BM25 with a semantic score, for example final score equals weight times BM25 plus one minus weight times cosine similarity. That mix is not a similarity in the cosine sense; a 0.75 in a hybrid configuration is not the same filter as a 0.75 in pure vector search. Managed knowledge bases can force this on you: Amazon Bedrock managed knowledge bases always retrieve with hybrid search and do not expose semantic-only search (AWS knowledge base retrieval docs).

Rank fusion produces its own scores. Reciprocal rank fusion combines several retrievers by rank position, not by raw similarity, so the output lives on a scale of its own and any cutoff has to be tuned on that scale.

A study that varied similarity thresholds across open models found that the best threshold differed by model: lower cutoffs around 0.55 worked for two models, a moderate 0.65 for another, and one model also performed well at 0.70 and 0.85 (IEEE conference paper). The practical lesson is that no universal number exists. The correct reading of the table is that the threshold is a property of your retriever, your corpus and your cost structure together.

Retrieval modeWhat the score meansSafe to compare thresholds across modes?
Cosine similarity (normalized)Angle between vectors, 0 to 1Yes, within the same embedding model
Dot product (unnormalized)Magnitude-weighted overlapNo; normalize first or do not reuse cutoffs
Hybrid BM25 plus denseWeighted blend of two scalesNo; calibrate on the blended output
Rank fusionPosition-based aggregateNo; there is no similarity unit

Treat the number as an evidence-admission policy rather than a cost knob. A passage that scores 0.79 against a policy question can still describe the wrong customer tier, pass a 0.75 cutoff and be treated by the model as authoritative, producing a fluent wrong answer with no error anywhere in the pipeline (DigitalOcean's analysis of thresholds).

Why chunking and freshness shift the threshold

The score is a function of the chunk that produced it. Fixed-size splitting can cut a sentence or idea in half, which lowers the score a genuinely relevant passage achieves; recursive or sentence-aware splitting tries paragraph breaks first, then sentence ends, producing cleaner boundaries (chunking strategy comparison). Semantic chunking goes further, embedding each sentence and placing a boundary where similarity between adjacent sentences drops, which produces more coherent chunks but adds an embedding call per sentence at index time. In practice that means the same content can score meaningfully higher under semantic chunking than under fixed windows, so a threshold tuned on the old index is invalid after a rechunk. The Bedrock knowledge base documentation distinguishes standard, hierarchical and semantic chunking for exactly this reason (AWS chunking guide).

Freshness matters for a subtler reason. An index is a point-in-time snapshot, and stale embeddings can degrade retrieval accuracy, with one vendor estimating up to 20 percent degradation and no built-in uncertainty signal reaching the user (Atlan on knowledge base staleness). When documents drift, some queries that used to match now score lower. The score distribution moves under a fixed threshold, so recalibrate after major content refreshes, not only at launch. Vendor guidance also suggests re-embedding once roughly 10 to 15 percent of the corpus has changed (Kapa on keeping a RAG index in sync).

A practical sequence: lock the chunking strategy, build the index, then tune the threshold. Tuning on an index you are about to rebuild wastes the work.

Build a labeled query set

You cannot choose a threshold without knowing, per query, whether a correct passage exists in the corpus. That is the ground-truth side of retrieval evaluation: recall at k with known relevant documents, or relevance labels applied by hand or by a judge model (Evidently's RAG evaluation guide).

Steps that work:

  1. Sample real queries. Pull from search logs, support tickets, chat transcripts and agent handoffs. Aim for a few hundred. The distribution should match production, not the demo.
  2. Include unanswerable queries on purpose. Questions about features you do not offer, competitors, or policies from a different product are essential. Without them you cannot estimate wrong answers at all.
  3. Label correctness of the top passage. For each query, mark whether a passage in the corpus answers it and which one. A binary label is enough to start. If two people disagree often, tighten the definition of "correct."
  4. Freeze the set. Store queries, labels, the index snapshot identifier and chunking configuration together. When you re-index, re-run the same set.

Manual labeling is slow but trustworthy. LLM-judged relevance can scale the set once your hand labels show the judge agrees with people on a sample; use it to expand coverage, not to replace the first hundred labels. For medical or legal content, the bar for "correct" should be set by a domain reviewer, since an answer that cites the right passage but applies it to the wrong population is still wrong. A retrospective triage study that combined retrieval with multi-evidence clinical reasoning is a useful model of how carefully that domain separates retrieval quality from final answer quality (JMIR Medical Informatics study).

Define miss and wrong answer precisely

The threshold comparison has to happen on a specific number. Decide which one before sweeping:

  • The top-1 score (what the agent would look at first).
  • The top-k maximum over what you would actually send to the model.
  • The reranked score if you rerank, since rerankers rescore candidates on their own scale.

If any retrieved passage passes the cutoff and is sent to the generator, use the maximum score among the sent passages. Then the two error counts are:

  • Miss: a correct passage exists in the corpus but its score falls below the cutoff. The agent hands off or refuses.
  • Wrong answer risk: no correct passage exists above the cutoff, but the top score passes. The agent answers from irrelevant evidence.

There is a third category worth counting separately: correct passage exists and passes, but an irrelevant passage also passes and dominates the answer. This is the failure mode the 0.79 example illustrates, and it is invisible if you only look at the top score.

Sweep the threshold and count both errors

With a labeled set and a fixed score definition, the sweep is mechanical. Compute per-query scores once, store them, then evaluate every candidate cutoff against the stored numbers.

# rows: {"query_id":..., "has_correct": bool, "top_score": float, "correct_score": float|None}
def sweep(rows, thresholds):
    out = []
    for t in thresholds:
        misses = sum(1 for r in rows if r["has_correct"] and (r["correct_score"] or 0) < t)
        wrong  = sum(1 for r in rows if not r["has_correct"] and r["top_score"] >= t)
        answered = sum(1 for r in rows if r["top_score"] >= t)
        out.append({"threshold": t, "misses": misses, "wrong": wrong,
                    "answered": answered, "answer_rate": answered/len(rows)})
    return out

Worked example with numbers. Suppose 400 labeled queries, 300 of which have a correct passage and 100 of which do not. Costs: a miss requires a handoff to a human agent, which you value at 6 minutes of agent time; a wrong answer costs a support ticket and a trust hit, which you value at 15 minutes plus escalation risk. Run the sweep:

ThresholdMisses (of 300)Wrong answers (of 100)Weighted cost (misses × 6 + wrong × 15 minutes)
0.60124172 + 615 = 687
0.703918234 + 270 = 504
0.80847504 + 105 = 609
0.851213726 + 45 = 771

At these invented weights, 0.70 wins. Move the wrong-answer cost to 60 minutes (a compliance incident in a regulated workflow) and the table flips: 0.80 costs 504 + 420 = 924 against 234 + 1080 = 1,314 at 0.70, so the stricter cutoff is correct. That is the whole decision rule: the right threshold is the one that minimizes weighted cost, and the weights come from your operation, not from a blog post. The same logic explains why legal and compliance workloads are often tuned to a much narrower band than conversational help desks.

Two refinements:

  • Report the operating point, not just the score. State the answer rate, the miss rate among answerable queries and the wrong-answer rate among unanswerable ones, so product owners can argue about costs rather than about the number.
  • Evaluate in segments. Split by query type (account questions, policy questions, billing disputes) and check whether one threshold serves all of them. Often you need a per-intent cutoff or a different handoff path for unanswerable queries.

Sweep on a held-out slice. If you pick the cutoff that minimizes cost on the same 400 queries you tuned on, you have fit the noise. Label 500, tune on 300, confirm on 200.

Instrument production once the threshold ships

The sweep gives you a starting number. Production tells you whether it holds. Log three things for every request: the top score, the decision (answer or handoff), and an outcome signal. Outcome signals include user thumbs, follow-up tickets within 24 hours, escalation to a human after an answer, and explicit correction phrases in the next turn.

Then watch the score distribution itself. If the median top score for answered queries falls after a content refresh, or if the share of queries near the cutoff grows, you have drift. Store the threshold with the index version in your deployment configuration so that a rollback test cannot silently pair an old cutoff with a new index.

One more control: keep an unanswerable probe set in production monitoring. Send it through the live pipeline periodically and count how many pass the cutoff. That number should stay low, and if it creeps up, wide admission of irrelevant evidence is the likely cause.

Where the choice lives in your stack

The threshold is one parameter in a larger admission policy: chunking, embedding model, retrieval mode, reranking and cutoff interact, and changing any one invalidates the tuning. If you are assembling the pipeline and would rather not maintain separate clients for embeddings, rerankers and generators, Quanta Inference exposes text, embedding and reranking-capable models through one OpenAI-compatible API key with prepaid US-dollar pricing, so the sweep runs against the same endpoint you ship.

If the decision instead needs a second opinion on cost weights (what a handoff actually costs your team, what a wrong answer costs in your market), a short consulting call will map those numbers to a threshold and a monitoring plan.

FAQ

FAQ

Is there a default similarity threshold I can start with?

Not one that transfers safely. Cosine cutoffs around 0.75 to 0.85 appear in practitioner guidance for conversational and compliance settings respectively, but published experiments show the best threshold varies by model across roughly 0.55 to 0.85 on the same task family (IEEE paper). Use those bands only as the range for your first sweep.

How many labeled queries do I need?

A few hundred is enough to rank candidate thresholds, provided unanswerable queries are well represented. Label about 500, tune on roughly 300 and confirm on the rest. If your segments (billing, policy, account) behave differently, you need enough per segment to see the difference, not just an overall total.

Does a higher threshold always reduce wrong answers?

It reduces wrong answers that come from weak matches, but it can increase a different error: irrelevant-but-high-scoring passages still pass at 0.9. Tighten the citation requirement in the prompt and log which passage the answer actually used, or the sweep will overstate how safe a high cutoff is.

Should I tune the cutoff before or after reranking?

After. A reranker rescores candidates on its own scale, so a cutoff chosen on first-stage scores does not carry over. Run the sweep on the final score the generator sees, including max-score aggregation if you send several passages.

What do I do when the best threshold differs by customer segment?

Use per-intent thresholds or route risky intents to stricter cutoffs while keeping a looser cutoff for low-stakes questions. Report each segment's miss and wrong-answer rates so reviewers see the trade-off rather than a single blended number.

Sources

Sources

  1. A Deep Dive into Retrieval Settings for RAG Systems
  2. Query a knowledge base and retrieve data - Amazon Bedrock
  3. Similarity Thresholds in Retrieval-Augmented Generation
  4. Why a Similarity Threshold Is a Data-Quality Control, Not ...
  5. What chunking strategies exist and how to choose one?
  6. How content chunking works for knowledge bases
  7. LLM Knowledge Base Staleness: Scoring, Causes, and ...
  8. How to Keep a RAG Knowledge Base in Sync ...
  9. A complete guide to RAG evaluation: metrics, testing and ...
  10. Multi-Evidence Clinical Reasoning With Retrieval ...
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles