server: recover from checkpoint on truncation failure for hybrid/recurrent models#20955
Conversation
…rrent models For hybrid models (Qwen3.5, Jamba, Falcon-H1), llama_memory_seq_rm() fails on recurrent layers because partial truncation is not supported. Previously this triggered prompt_clear() which erased ALL cached state, forcing a full re-evaluation of the entire prompt. This commit adds checkpoint-based recovery: when truncation fails, the server restores from the nearest checkpoint before the truncation point and only re-evaluates the delta tokens. Additionally, checkpoint metadata is now persisted alongside slot save/restore files (.checkpoints companion file), and auto-save/restore hooks are added to server startup/shutdown for seamless model hot-swap in router mode. Measured on Qwen3.5-27B with 35858 token context: - Before: prompt_clear + full re-eval = 21054ms - After: checkpoint recovery + delta = 77ms (273x faster) Related: ggml-org#20225, ggml-org#20153
|
Hi @European-tech, thanks for your contribution! Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:
Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below. |
|
This MR works for me on M4 Macbook. I checked Qwen-122B and Nemotron 3 Super. Minor comment: slot auto-save/auto-restore could be an option not unconditional behavior. |
|
This was closed because this mechanism is already implemented, right? |
Problem
When re-using a cached prompt with
TAG_PROMPT_LOGITS, the server tries to truncate the KV cache viallama_memory_seq_rm(slot.id, p0, -1). On hybrid/recurrent models (Qwen3.5, Jamba, Falcon-H1), this call always fails because partial truncation is not supported for recurrent layers. The current fallback isprompt_clear(true), which erases the entire cached state and forces a full prompt re-evaluation from scratch.For long contexts this is devastating: a 35K-token prompt takes ~21 seconds to re-process instead of the sub-100ms it should take from cache.
Root Cause
llama_memory_seq_rm()returnsfalsefor recurrent memory types (Mamba/SSM layers) because they store a compressed state that cannot be partially truncated. The server interprets this as "memory is corrupt" and clears everything — but for hybrid models the memory is perfectly fine, it just doesn't support partial removal.Fix
Instead of clearing all memory on truncation failure, the server now:
llama_state_seq_set_data_ext()withLLAMA_STATE_SEQ_FLAGS_PARTIAL_ONLYFalls back to the original
prompt_clear()only if no suitable checkpoint exists.Additionally: checkpoint persistence across slot save/restore
The built-in
/slotssave/restore API persists KV+recurrent memory viallama_state_seq_{save,load}_file, but does not persist the checkpoint metadata. This PR adds:slot_checkpoints_save/load()helpers that write/read a companion.checkpointsfile next to the slot state fileauto_save_slots()/auto_restore_slots()methods called at server shutdown/startup for seamless model hot-swap in router mode (multi-model--models-dir)Measured Impact
Qwen3.5-27B, 35858 token context, RTX 3090 24GB:
Related Issues
Files Changed
tools/server/server-context.cpp— checkpoint save/load helpers, truncation recovery logic, auto-save/restoretools/server/server-context.h—auto_save_slots()/auto_restore_slots()declarationstools/server/server.cpp— call auto-restore on startup, auto-save on shutdown