Skip to content

perf(cache): keep the prompt-cache prefix stable and request/report the cache#20

Open
santhreal wants to merge 2 commits into
GetSmallAI:mainfrom
santhreal:perf/stable-prompt-cache-prefix
Open

perf(cache): keep the prompt-cache prefix stable and request/report the cache#20
santhreal wants to merge 2 commits into
GetSmallAI:mainfrom
santhreal:perf/stable-prompt-cache-prefix

Conversation

@santhreal

Copy link
Copy Markdown
Contributor

The interactive loop rebuilt the position-0 system message every turn to embed a prompt-ranked repo map (Focused map for <user prompt>), whose content changes with each user prompt. Since prompt caching — OpenAI's hosted auto-cache and local llama.cpp/Ollama/vLLM KV reuse alike — matches on the longest shared token prefix, a system message that changes every turn invalidated the entire cached prefix (system + tools + prior turns) on every repo-related turn. The harness even re-runs warmup whenever the system-prompt fingerprint changes, so the churn was already costing real requests.

Fix, two parts:

  1. Keep the prefix stable. run_user_turn now builds msg[0] from a new render_stable_system_prompt (base prompt + static .small-harness/prompt.md only, no focused map), and folds the prompt-focused map into the current user message (below the cache boundary) in the request copy only — so the map still reaches the model for the turn it was built for, durable history keeps the raw prompt, and the cached prefix survives across turns. One-shot/eval/status/compact callers are unchanged.

  2. Actually use and report the cache. Send a stable prompt_cache_key (derived from model + the cacheable system prefix) on hosted requests so a session co-locates on one warm cache shard; omitted for local backends. Read back prompt_tokens_details.cached_tokens, aggregate it into RunResult, and show <n> cached in the per-turn footer when the provider reports a hit — for both the chat-completions and Codex Responses paths.

Tests: prefix stability (full prompt varies by input while the stable prompt carries no focused map), context folds into the last user message not the system prefix, session_cache_key stability/scoping, prompt_cache_key wire serialization, footer cached-token rendering, and Codex response.completed cached-token parsing. cargo fmt/clippy -D warnings clean.

The position-0 system message is the prompt-cache prefix, but it was
rebuilt each turn to include the prompt-focused repo map (ranked by the
current user message). That made the prefix change on every repo-related
turn, invalidating the whole cached prefix -- system, tools, and all
prior turns -- for both hosted prompt caching and local KV/prefix reuse.

Build the system message from a prompt-independent stable prompt and fold
the focused repo map into the current user turn instead, below the cache
boundary. Durable history keeps the user's raw prompt; one-shot/eval
callers are unchanged.
Now that the position-0 system prefix is stable across turns, make the
client actually use the hosted prompt cache instead of merely being able
to resend the same prefix.

- Send a stable prompt_cache_key on every agent-loop request, derived
  from model + the cacheable system prefix (session_cache_key). Hosted
  providers use it to co-locate a session on one warm cache shard; local
  backends omit it.
- Deserialize prompt_tokens_details.cached_tokens from usage, aggregate
  it into RunResult.cached_input_tokens, and surface "<n> cached" in the
  per-turn footer when the provider reports a hit.

Tests: session_cache_key stability/scoping, prompt_cache_key wire
serialization, and footer cached-token rendering.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant