feat(server): expose swa_full_tokens_ratio as a startup CLI flag - #109
Open
mkornreich wants to merge 1 commit into
Open
feat(server): expose swa_full_tokens_ratio as a startup CLI flag#109mkornreich wants to merge 1 commit into
mkornreich wants to merge 1 commit into
Conversation
EngineConfig.swa_full_tokens_ratio -- the SWA radix cache's window/full pool ratio (and the DSV4 window tier ratio) -- could only be set at runtime via POST /v1/cache/rebuild. So the window pool is first sized at its 0.2 default and only resized afterwards, which (a) cannot grow past a runtime rebuild's tighter budget and (b) needs an out-of-band call after every start. Add a --swa-full-tokens-ratio load-time flag (mirrors --memory-ratio) so the window pool is sized at model load. Validated to (0, 1], matching the /v1/cache/rebuild check; threads through unchanged via ServerArgs(**kwargs). Why it matters: on a sliding-window model, a shared prompt prefix longer than the window is reusable across requests only if its windowed KV is retained, which needs the window pool >= the prefix. Sizing at startup (vs a post-start rebuild) also keeps more full-pool capacity, since it is not bounded by the rebuild's reallocation budget. Adds tests/server/test_swa_full_tokens_ratio_flag.py (default, in-range accept, out-of-range / non-numeric reject). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Author
|
This is a massive improvement for caching! |
mkornreich
pushed a commit
to mkornreich/llm-desktop-electron
that referenced
this pull request
Aug 23, 2026
… with a rebuild fallback The classifier prefix-cache fix (sizing FreeToken's SWA window pool past the ~27k rulebook) was done via a post-start /v1/cache/rebuild. FreeToken now has a --swa-full-tokens-ratio flag (FlashML-org/FreeToken#109) that sizes the window pool at LOAD, which is cleaner and keeps more full-pool capacity (the runtime rebuild is bounded by a double-buffer budget: it gave full pool 100k, the flag gives 113k). run.sh now prefers the flag: if the local FreeToken build has --swa-full-tokens-ratio (detected by grepping the installed args.py), it passes it at launch and skips the rebuild; otherwise it falls back to the post-start rebuild (works on a stock build). config.jsonc managed.swaFullTokensRatio (0.3) drives the flag; numPages/numSwaPages remain the fallback. config.mjs emits FREETOKEN_SWA_RATIO. Verified on the RTX 5070 (8GB): launched with --swa-full-tokens-ratio 0.3 → window pool 34,023, full pool 113,410, no runtime rebuild; a repeated prefix reuses ~46k cached tokens (0.3s vs cold), classifier routes to freetoken:gemma-4-e2b. The flag is installed in the local build's venv; a reinstall without it cleanly falls back. Co-Authored-By: Claude Opus 4.8 <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.
What
Adds a
--swa-full-tokens-ratioCLI flag that setsEngineConfig.swa_full_tokens_ratioat model load — the SWA radix cache's window/full pool ratio (and the DSV4 window-tier ratio). It could previously only be changed at runtime viaPOST /v1/cache/rebuild, so the window pool was always first sized at its0.2default and only resized afterward — which can't grow past a runtime rebuild's tighter double-buffer budget, and needs an out-of-band call after every start.The flag mirrors
--memory-ratio, validates to(0, 1](matching the/v1/cache/rebuildcheck), and threads through unchanged viaServerArgs(**kwargs).Why
On a sliding-window model, a shared prompt prefix longer than the window is reusable across requests only if its windowed KV is retained — which requires the window pool ≥ the prefix. When the pool is smaller than a fixed leading prompt, that prefix is never reused and every request re-prefills it. Sizing the window pool at startup (rather than a post-start rebuild) also keeps more full-pool capacity, since it isn't bounded by the rebuild's reallocation budget. The same ratio drives the DSV4 window tier, so this is not specific to SWA-radix models.
Tested on
Linux, NVIDIA RTX 5070 Laptop (8 GB), driver 595.84, CUDA 13.
Unit test (no GPU):
tests/server/test_swa_full_tokens_ratio_flag.py— default resolves to the config value; an in-range value is accepted; out-of-range / non-numeric values are rejected at parse time (follows theparse_argsmock pattern intest_parser_auto_selection.py).Full-attention model on
main—Qwen/Qwen3-0.6B(no window pool): the flag is accepted and applied (swa_full_tokens_ratio=0.3inServerArgs), the model loads and serves normally — a no-op, as expected.SWA effect —
gemma-4-E2B-it(q4_0 GGUF). The model support is my separate open PR #59, so this A/B is onmain+ #59 + this flag (the flag itself is model-family-independent). Request ≈ 55k tokens (a ~27k fixed leading prefix + ~28k body); a second, near-identical request measures prefix reuse:swa_full_tokens_ratiomainbehavior)Cold first-call prefill is ~39 s either way; the flag changes whether the shared prefix is reused on later calls (the default pool is smaller than the 27k prefix, so it can't be retained).
Notes