An exact-match cache is useless in front of an agent - no two users phrase a question identically. A semantic cache embeds the query and serves a stored answer when the nearest cached query is close enough. The threshold is the whole design: too high and you never hit, too low and you confidently serve the wrong answer. Measuring the trade-off means replaying a query log and counting.
Queries arrive in order. For each one:
Cosine similarity of a and b is ∥a∥∥b∥a⋅b; if either vector is all zeros, define the similarity as 0.0.
Implement:
def semantic_cache(queries, threshold):
Return:
Returns the five-key dict. Do not use numpy-specific printing anywhere; every float in the output is rounded.
qs = [{"id": "q1", "vec": [1.0, 0.0]},
{"id": "q2", "vec": [2.0, 0.0]},
{"id": "q3", "vec": [0.0, 1.0]}]
out = semantic_cache(qs, 0.9)
print(out["hits"], out["misses"], out["hit_rate"]) # 1 2 0.3333
print(out["hit_map"]) # [['q2', 'q1']]
q2 points the same way as q1 (similarity 1.0) so it hits; q3 is orthogonal (0.0) and misses.
qs = [{'id':'q1','vec':[1.0,0.0]},{'id':'q2','vec':[2.0,0.0]},{'id':'q3','vec':[0.0,1.0]}]
out = semantic_cache(qs, 0.9)
print(out['hits'], out['misses'], out['hit_rate'])
print(out['hit_map'])1 2 0.3333 [['q2', 'q1']]
q1 arrives to an empty cache, so it must miss and is inserted. q2 is a scalar multiple of q1, giving cosine similarity 1.0 >= 0.9 - a hit served by q1, and it is not inserted. q3 is orthogonal to q1 (similarity 0.0), so it misses and is inserted. One hit out of three queries is a hit rate of 0.3333.
0 <= len(queries) <= 500; vectors are 1 to 64 dimensions>=, so a similarity exactly equal to the threshold is a hithit_rate is rounded to 4 dp and is 0.0 for an empty log0.0 with everything