THIS EXPLANATION
THE ROOM
CDA·27 Computing, Data & AI 7 MIN · 8 STATIONS

Caching an answer nobody asked for exactly

A Socratic walk-through of caching an answer nobody asked for exactly — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

How do you reuse a stored answer for a question that has never been asked in those words?

An ordinary cache is a dictionary. You hash the key, you find the entry, you serve it. That works beautifully when keys repeat — the same URL, the same query text, the same file path — because the world hands you the identical key again and again.

Now key a cache on what a person typed. "How do I reset my password?" "how to reset password" "I forgot my password, what now". Three keys, one intent, zero hits. The exact-match cache is not slightly less effective here; it is close to useless. So what would it take to hit anyway — and what have you quietly given up the moment you try?

b

Reasoning it through

REASONING #

The first move is to stop keying on the characters and start keying on something that stays put when the wording moves. An embedding model does exactly that: it maps a piece of text to a vector, trained so that texts people judge similar land near each other. Store each answered question as a vector with its answer beside it; when a new question arrives, embed it too and search for the nearest stored vector. If the nearest one is close enough, serve its answer without calling the expensive model at all. That is the whole mechanism — and open implementations such as GPTCache do essentially this.

But notice the phrase doing all the work: close enough. There is no natural boundary in that space, so you must choose a similarity threshold, and the choice is not a tuning detail. It is the entire design, because it is a dial between two different errors. Set it high and you hit rarely, and the cache barely earns the vector search it costs. Set it low and you begin answering questions nobody asked.

Sit with that second error, because it is not the familiar cache problem. A conventional cache's failure is stale — the right entry, out of date. This one's failure is wrong entry, confidently served, and it looks perfectly plausible to the reader. Worse, the errors are not randomly distributed. Ask yourself which pairs of sentences are close in an embedding space but opposite in meaning. "How do I enable two-factor authentication" and "how do I disable two-factor authentication" differ by one morpheme. So do questions differing only in a number, a date, a name, or a negation — and these are exactly the edits that flip the correct answer while barely moving the vector. Embedding models trained on similarity objectives are known to handle negation poorly; how badly varies by model, and it is an active area of work rather than a solved one, but the direction of the weakness is well established.

There is a second problem hiding in the key. Is the question really the whole key? "What is my balance" means something different for each user. So does any question whose answer depends on the tenant, the permissions of the asker, the retrieved documents, the system prompt, the tool set, or the model version. If those are not part of the key, the cache does not merely go stale — it serves one user's answer to another, which is a data-leak rather than a performance bug. The honest key is the embedding plus every scope the answer depended on, and scopes that are hashed exactly rather than compared by similarity.

Then the ordinary caching problems arrive on top: entries age, so a stored answer about a price, a policy, or a schedule must expire; and a hit is not free, since it costs an embedding call and an approximate-nearest-neighbour search. Semantic caching pays when the call being avoided is far more expensive than that — which for a large model it usually is, in both money and latency.

Is there a way out of the threshold dilemma? Partly. The strongest practical move is to stop treating similarity as the decision and treat it as a shortlist: retrieve the few nearest candidates, then have something cheap actually check equivalence — a small model asked "do these two questions have the same answer?", or a rule that refuses any pair differing in a negation, a numeral, or a named entity. That converts one fuzzy score into a retrieval step plus a verification step, which is a much better-behaved shape.

c

The analogy

THE ANALOGY #
THE FIGURE

Think of a librarian with a good memory but no time. Someone asks a question; rather than research it, she recalls that a question like this came up last week and repeats the answer she gave then. When the resemblance is real, she has saved everyone an afternoon.

WHERE IT BREAKS DOWN

The librarian actually reads both questions and notices the word "not" — whereas a similarity score has no notion of what the sentences claim, only of how alike they look, which is why the dangerous near-misses are precisely the pairs that look almost identical and mean the opposite.

d

Clarifying the model

THE MODEL #

Three refinements.

First, the threshold is a classifier boundary, not a preference. Every value of it produces a rate of missed reuse and a rate of wrong reuse, and you cannot lower one without raising the other from the same evidence. That means it should be chosen against a labelled set of question pairs you have actually judged, and re-checked whenever the embedding model changes — similarity scores are not comparable across models.

Second, the two errors are not equally costly. A missed hit costs money; a wrong hit costs trust, and in some domains a great deal more. That asymmetry argues for a high threshold plus a verification step, and for excluding whole classes of question — anything personal, live, or high-stakes — rather than hunting for one number safe for all of them.

Third, a common misconception: that a hit means the questions were the same. It means their representations were near. Those are different claims, and the gap between them is where every interesting failure of this technique lives.

e

A picture of it

THE PICTURE #
Caching an answer nobody asked for exactly
Caching an answer nobody asked for exactly Follow the arrows from the start marker: every question becomes a vector, then a nearest-neighbour lookup, and the two edges leaving that state are the only real decision -- above the threshold, or below it. The back edge from recompute shows the cache growing. The two states hanging off reuse are the failure modes, and note that they are reached from a hit: this cache's characteristic damage happens on the path that looks like success. {"generator":"mermaid-svg-renderer@3.2.1","source":"../Socrates/.diagram-cache/_src/caching-an-answer-nobody-asked-for-exactly.md","sourceIndex":1,"sourceLine":4,"sourceHash":"9ecf9482d251782eedc3ba0a63b265211ff3f96cb1c7f32a3916f4b92e14435f","diagramType":"stateDiagram","layoutVariant":"source","repairedDuplicateIds":[],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":880,"height":1002},"qa":{"passed":true,"findings":[]}} similarity search overstored questions score above the threshold score below the threshold the new pair joins thecandidates threshold too low, orscope left out of the key entry outlived the facts itencoded New question turned into avector Nearest stored entry retrieved Reuse: the stored answer isserved Recompute: the model is calledand the pair stored Wrong reuse: a differentquestion got this answer Stale reuse: the facts movedunder the entry Negation, a number, a nameA one-word edit that flips theanswerbarely moves the vector

How to readFollow the arrows from the start marker: every question becomes a vector, then a nearest-neighbour lookup, and the two edges leaving that state are the only real decision — above the threshold, or below it. The back edge from recompute shows the cache growing. The two states hanging off reuse are the failure modes, and note that they are reached from a hit: this cache's characteristic damage happens on the path that looks like success.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

Semantic caching works by replacing an exact key with a nearby one, which means it buys hit rate with the possibility of answering a question that was never asked. The threshold is not a knob to tune for throughput; it is where you decide how much wrongness to accept, the wrongness is concentrated in near-identical pairs that mean opposite things, and the sturdier designs treat similarity as a shortlist to be verified rather than as the answer itself.

g

Where to go next

ONWARD #
  • Approximate nearest-neighbour indexes, and how their own recall setting compounds with the threshold.
  • Verification with a cheap model, and whether it can be trusted to judge equivalence.
  • Cache scoping in multi-tenant systems, where a wrong hit becomes a disclosure rather than an error.
h

Key terms

TERMS #
TermWhat it means
Embeddinga vector representation of text produced so that texts with similar meaning land near each other.
Cosine similaritythe usual measure of nearness between two embeddings, based on the angle between them.
Similarity thresholdthe score above which a stored answer is considered reusable; the dial between missed reuse and wrong reuse.
Approximate nearest neighbour (ANN)an index that finds near vectors quickly by accepting a small chance of missing the true nearest.
Cache scopethe additional key material (user, tenant, model version, retrieved documents) that must match exactly for a stored answer to be reusable.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4