Reusing answers: a response cache per project, exact match, opt-in with a TTL

llmgw keys cache --project P --ttl 1h [--any] | --off, and Cache answers… on
the console's project menu. The same request — project, endpoint, canonical
model and the body without stream, stream_options, user, metadata, store and
service_tier, keys sorted — is answered from the gateway's memory for the
TTL. Only reproducible answers (temperature 0 or a seed; embeddings, rerank,
score) unless --any; only a whole 200 from the model asked for, not a
fallback's, a canary's, or one a guardrail changed.

Looked up after the limits and the input guardrails; the output policy
judges a reused answer; no_store and stored conversations bypass it.
Streamed answers are kept put back together and streamed back as chunks.
x-llmgw-cache: hit|miss|bypass, Age on a hit, Cache-Control: no-cache or
x-llmgw-cache: no to bypass. A hit is recorded with no tokens and no cost,
marked cache_hit (migration 0027) and shown by ctl request. An LRU bounded
by router.cache.max_bytes and max_entry_bytes; llmgw_cache_requests_total,
llmgw_cache_bytes, llmgw_cache_entries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilker ManapandClaude Opus 5.5 committed 2026-10-04 23:50:53 +02:00
1 parent 30f7f3474a
commit 44f3a9e31d
27 files changed
+2066 -11

No files matched your search

@@ -0,0 +1,10 @@
-- Reusing answers, for a project that asks: how long one is reused, and
-- whether any request's answer is, or only those that come out the same
-- every time (temperature 0, or a seed). Off for every project until set.
-- The answers themselves are held in each gateway's memory, never here.
ALTER TABLE projects ADD COLUMN cache_ttl_seconds INTEGER;
ALTER TABLE projects ADD COLUMN cache_any INTEGER NOT NULL DEFAULT 0;
-- A request answered from that cache: nothing was generated for it, so it
-- carries no tokens and costs nothing, and this says why.
ALTER TABLE usage ADD COLUMN cache_hit INTEGER NOT NULL DEFAULT 0;