Repository navigation
feat(cache): keep recurrent states where prompts diverge - #2
Merged
Merged
Conversation
The model's recurrent state can only be resumed where a snapshot was saved: at the end of each prompt and at rolling checkpoints. A prompt that shared a long prefix with an earlier one but differed near its end - a new question in the same session, a side agent with the same system prompt - re-prefilled from the start. The server now sends state hints (protocol v7): where the system prompt and tools end, where the last message begins, and where that message's final content parts begin. The engine keeps a state at each, skipping those within four blocks of another. The first, shared by other conversations on the same setup, is a boundary state kept ahead of all other states and of plain KV (at most four, SPLASH_BOUNDARY_STATES). The others start as the oldest ordinary state and become ordinary once a later prompt resumes from them, so a guess never evicts an end-of-turn state. StateCache entries now carry one StateRole instead of a checkpoint flag. Replaying 31 requests captured from an agent harness: 63.5% -> 78.2% of prompt tokens reused, 315 s -> 198 s in total; a new question in a 12K-18K token session went from 30-44 s to 1 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Qwen3.8-Flash-Next is a hybrid model: its recurrent (GDN) state can only be resumed where a state snapshot was saved. The engine saved them at the end of each prompt and at rolling 4096-token checkpoints, so any prompt that shared a long prefix with an earlier one but differed near its end re-prefilled from the start (or from the first 32 tokens). Agent harnesses do that all the time:
This PR makes the engine save states where prompts actually diverge, and keep the most widely shared one:
state_hints: prompt positions where the engine should keep a state.SPLASH_BOUNDARY_STATES).StateCachenow has oneStateRoleper entry (ordinary, checkpoint, hint, boundary) instead of a checkpoint flag.hint_publications,hint_publication_failures,boundary_entries,boundary_capacityandboundary_demotions.Measurements
Replay of 31 requests captured from a real agent harness session (CLI mode, ACP mode, and its memory-extraction subagent), sent one at a time in order, generating one token each, on an M5 Pro 64 GB (macOS 27.0.1):
Requests that changed by more than a second:
#1, npanj#13 and npanj#15 are cold full prefills with the same reuse in both runs. Their differences (−3.0 s, +1.8 s, +1.7 s) are run-to-run variation; in an earlier run of this branch npanj#13 took 43.7 s. Decode speed is unchanged: 28.6–32.7 tok/s across the runs, the same as
mainon this Mac.Remaining misses:
SPLASH_EXPERT_CACHE_GIB=30it holds 32, and the same replay on an earlier version of this branch reused 79.1% in 192 s, at ~6% lower decode speed. That trade is left for a follow-up.Tests
make test-engine(CPU and Metal suites) passes. The twokv2_g12verify tiles are still skipped under shader validation, as before.dev/tests/test_server.py(175 tests) and the engine Python tests (417, 11 skipped) pass;ruff checkandruff format --checkare clean.Follow-ups, not in this PR
normalize_messages) and tokenize once with offsets, instead of finding parts by text in the rendered prompt. That would also cover Anthropic and Responses inputs uniformly.<|im_start|>convention (from the template itself), for other model families.🤖 Generated with Claude Code