Skip to content

feat(server): session-keyed automatic slot save/restore - #29738

Open
simon3z wants to merge 1 commit into
ggml-org:masterfrom
simon3z:auto-slots-save-restore
Open

simon3z wants to merge 1 commit into
ggml-org:masterfrom
simon3z:auto-slots-save-restore

Conversation

@simon3z

@simon3z simon3z commented Sep 30, 2026

Copy link
Copy Markdown

Overview

This PR automates the slots save/restore orchestration to files and life-cycle management (e.g. delete old slots) leveraging the session-id headers sent by most of the clients. This code, besides the added tests, has been tested with Pi ("sendSessionAffinityHeaders": true, "sessionAffinityFormat": "openai") and switches between sessions with different context is automatic and immediate as the prefill phases are avoided by loading the relevant slots from disk.

Additional information

All the additional information about this PR can be found in the issue #29678.

Requirements

No additional requirements introduced.

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: YES - AI (pi agent, qwen3.8-27b) assisted with the implementation, the test additions, and improving the documentation. I reviewed the code and own the design choices. See the Assisted-by line in the commit.

@simon3z
simon3z requested review from a team as code owners September 30, 2026 11:21
@github-actions github-actions Bot added documentation Improvements or additions to documentation server labels Sep 30, 2026
@simon3z

simon3z commented Sep 30, 2026

Copy link
Copy Markdown
Author

Hi @ngxson and @ServeurpersoCom, first time contributing, I wonder if you'd be interested in reviewing and merging this enhancement. Let me know if there is something I should do or change to get this approved. Thank you in advance!

@ServeurpersoCom

Copy link
Copy Markdown
Contributor

I've got a good to-do list; I think I'll be able to take a look at it before the weekend!

@ServeurpersoCom

Copy link
Copy Markdown
Contributor

Hi, one thing bothers me: the session path is active as soon as one of these headers is present, even without --slot-save-path, so it changes the default behavior for clients that already send them.

In that case slot selection ignores prompt similarity and the evicted slot is no longer saved to the RAM cache, so sub-agents sharing a long system prompt or users switching between conversations get more full re-prefills than today. With --slot-save-path set, each session switch also blocks all slots during a synchronous write that can reach several GB.

Have you tried raising --cache-ram for your multi-agent setup? The existing prompt cache already restores evicted conversations by prefix, and the 8 GiB default may simply be too small for your contexts.

Could the whole feature be opt-in behind an explicit flag, so nothing changes for users who don't enable it?

@simon3z
simon3z force-pushed the auto-slots-save-restore branch from 237aa21 to 7197f01 Compare October 1, 2026 11:13
@simon3z

simon3z commented Oct 1, 2026

Copy link
Copy Markdown
Author

Hi, one thing bothers me: the session path is active as soon as one of these headers is present, even without --slot-save-path, so it changes the default behavior for clients that already send them.

Hi @ServeurpersoCom, yes, indeed, I realized I should have addressed that, I prepared a follow up revision (just submitted) where you enable this feature by specifying which headers to use (e.g. --slot-save-sessions x-session-id,session_id,x-session-affinity --slot-save-sessions-max 10).

Have you tried raising --cache-ram for your multi-agent setup? The existing prompt cache already restores evicted conversations by prefix, and the 8 GiB default may simply be too small for your contexts.

Yes, indeed that is helping in some situations, when contexts are fairly similar at the beginning and then fork (e.g. sub-agents), however these are the things that --cache-ram isn't covering (and maybe doesn't even belong there for the amount of space required):

  • Resume long-running sessions over an extended period of times (e.g. you stopped the development of something for hours or days, you used the agent for other development, and then you come back to it)
  • Entirely different sessions (e.g. working almost in parallel to multiple projects or scripts, etc.)
  • Survives across restarts of llama-server and reboots (reduces the "stress" of "oh I need to restart llama-server, etc." because of waiting minutes for the context to be rebuilt)
  • Saves power

Maybe the sweet spot is combining both.

Could the whole feature be opt-in behind an explicit flag, so nothing changes for users who don't enable it?

Definitely! Just updated the patch (details in the first paragraph of this comment).

Thank you for the review and your time!

@ServeurpersoCom

Copy link
Copy Markdown
Contributor

Thanks, the opt-in looks good! Looking closer though, there are quite a few edge cases:

  • at startup the old session files get pruned but never added to the sessions map, so the cap doesn't apply to them
  • that cleanup runs as soon as --slot-save-path is set, even without the new flag, and fs::remove can throw there
  • only the target context is restored, the draft/MTP one keeps the previous slot's KV, so speculative decoding gets much slower after a restore
  • no context checkpoints either, so hybrid/SWA models re-prefill everything once the client rewrites history
  • in router mode all models share the same save path, same id means same file
  • the session id shows up in /slots and in responses, so anyone can grab someone else's session
  • saving is synchronous, so every session switch freezes all slots for the whole write
  • a couple of -Wsign-compare warnings

Since the RAM prompt cache already handles the draft and the checkpoints, maybe the sweet spot you mentioned is just letting it spill evicted entries to disk? That would cover your use cases without needing a session id at all.

@ServeurpersoCom

Copy link
Copy Markdown
Contributor

Quick follow-up on my last suggestion: there's already #28092 doing this, but it got too complex. As @ngxson said in his reply there, he has his own version based on chained hashes of token blocks, and he wants to do some refactoring first before implementing the feature. So it's probably worth waiting for that rather than building a third approach in parallel.

A client can tag completion requests with a session id. The server
then tracks which slot holds the session's KV state and, when that
slot is taken by another request, saves the state to
--slot-save-path and restores it on the next request for the same
session, without explicit save/restore endpoint calls. An evicted
conversation resumes immediately instead of re-prefilling the whole
prompt, which can cost tens of seconds on long contexts.

- Opt-in flag --slot-save-sessions HEADERS: comma-separated HTTP
  headers in priority order from which the session id can be read;
  without the flag the session id (body field or headers) is
  ignored, so existing --slot-save-path deployments are unchanged
- When enabled, the body field session_id is always accepted and
  takes priority over headers; body and header must agree when both
  are present, and the id must be a valid file name, else 400
- Track sessions in a LRU registry alongside the slot stamps; clear
  it on model load
- Save files are named llama-session-<id>.bin; when speculative
  decoding is active, the draft context state is saved alongside as
  llama-session-<id>.dft, and both are restored together
- At startup, files left by previous runs are indexed into the
  registry, so the cap counts disk and RAM sessions alike, and the
  oldest beyond the cap are deleted
- On shutdown, sleep, and model reload, the sessions still held in
  slot memory are flushed to disk
- New flag --slot-save-sessions-max N (default 128) caps how many
  sessions are kept
- Reuse the existing slot save/restore file format; factor the
  manual endpoints onto shared slot_save_to_file and
  slot_restore_from_file helpers
- Without --slot-save-path the session id still pins the slot in
  memory
- Expose session_id in completion responses and in GET /slots
- Extend test_slot_save.py with thirteen session scenarios (autosave,
  headers, conflict, invalid id, restart, shutdown flush, sleep flush, no save
  path, no flag, max sessions, sweep, sweep gating, dft pair); all
  22 tests pass

Fixes ggml-org#29678

Assisted-by: Pi-Agent nvidia-rtx-5070ti/qwen3.8-27b
Signed-off-by: Federico Simoncelli <federico.simoncelli@gmail.com>
@simon3z

simon3z commented Nov 1, 2026

Copy link
Copy Markdown
Author

@ServeurpersoCom do you think #28092 is going to be prioritized any time soon?
I have been rebasing/using this patch for a while, it's self-contained and builds on top of an existing feature (save/restore slots). I wonder if it would make sense to get this included while we wait for the more advanced #28092 which seems quite complex to get finalized.
What do you think?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation server

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants