From 86d020f99cf0b9f918e421044191c60017d30a5a Mon Sep 17 00:00:00 2001 From: ARC <261443955+arc-uri-el@users.noreply.github.com> Date: Tue, 8 Sep 2026 12:54:31 +0200 Subject: [PATCH 1/2] server : retain replaced branches with a shared prompt prefix Preserve and consult the existing RAM prompt cache when any cached suffix is replaced. The half-prefix-loss heuristic drops independent conversations that share a large system or tool prefix. Extend the existing slot tests with two interleaved shared-prefix branches and exact restored token checks. Assisted-by: GPT 6 Astra --- tools/server/server-context.cpp | 4 +-- tools/server/tests/unit/test_slot_save.py | 30 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tools/server/server-context.cpp b/tools/server/server-context.cpp index 7d636c7923b8..af28bacdea62 100644 --- a/tools/server/server-context.cpp +++ b/tools/server/server-context.cpp @@ -1808,8 +1808,8 @@ struct server_context_impl { f_sim_best, slot_prompt_similarity, f_keep); } - // if we are about to lose a large portion of the existing context - save it in the prompt cache - if (f_keep < 0.5f) { + // A replaced branch can share most of a tool schema and still need its own cached suffix. + if (ret->prompt.tokens.get_common_prefix(task.tokens) < ret->prompt.tokens.size()) { update_cache = true; } } diff --git a/tools/server/tests/unit/test_slot_save.py b/tools/server/tests/unit/test_slot_save.py index 5eca46cb292d..c8d95aa47144 100644 --- a/tools/server/tests/unit/test_slot_save.py +++ b/tools/server/tests/unit/test_slot_save.py @@ -158,6 +158,36 @@ def test_slot_erase(): assert res.body["timings"]["prompt_n"] == 21 # all tokens are processed +def test_ram_cache_interleaved_shared_prefix(): + server.n_slots = 1 + server.cache_ram = 16 + server.n_predict = 8 + server.start() + + prefix = [1] + [10] * 192 + prompts = [prefix + [20] * 48, prefix + [30] * 48] + + def complete(prompt): + res = server.make_request("POST", "/completion", data={ + "prompt": prompt, + "cache_prompt": True, + "n_predict": 8, + "ignore_eos": True, + "return_tokens": True, + "temperature": 0.0, + }) + assert res.status_code == 200 + return res.body + + first = [complete(prompt) for prompt in prompts] + assert first[0]["timings"]["prompt_n"] == len(prompts[0]) + for prompt, expected in zip(prompts, first): + restored = complete(prompt) + assert restored["timings"]["cache_n"] == len(prompt) - 1 + assert restored["timings"]["prompt_n"] == 1 + assert restored["tokens"] == expected["tokens"] + + # # Multimodal server (mmproj loaded) slot save/restore. # From 9cbefdcf068ca21cf57d81cc153bdcede67ea510 Mon Sep 17 00:00:00 2001 From: ARC <261443955+arc-uri-el@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:57:18 +0200 Subject: [PATCH 2/2] tests : compare branch restoration against the same replay shape Take a one-token replay control before displacement. A full-prefill comparison also changes kernel shape and is not an isolation test for RAM restoration. Assisted-by: GPT 6 Astra --- tools/server/tests/unit/test_slot_save.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/server/tests/unit/test_slot_save.py b/tools/server/tests/unit/test_slot_save.py index c8d95aa47144..6e07bdc43c5c 100644 --- a/tools/server/tests/unit/test_slot_save.py +++ b/tools/server/tests/unit/test_slot_save.py @@ -179,8 +179,11 @@ def complete(prompt): assert res.status_code == 200 return res.body - first = [complete(prompt) for prompt in prompts] - assert first[0]["timings"]["prompt_n"] == len(prompts[0]) + first = [] + for prompt in prompts: + complete(prompt) + # Compare the same one-token replay shape before and after displacement. + first.append(complete(prompt)) for prompt, expected in zip(prompts, first): restored = complete(prompt) assert restored["timings"]["cache_n"] == len(prompt) - 1