TerslerThe little junk rig that could

Source files / install/patches · raw

server-prompt-cache-keep.patch

diff --git a/tools/server/server-context.cpp b/tools/server/server-context.cpp
index f6b27907a..c826dae92 100644
--- a/tools/server/server-context.cpp
+++ b/tools/server/server-context.cpp
@@ -1641,7 +1641,9 @@ private:
                 }
 
                 // if we are about to lose a large portion of the existing context - save it in the prompt cache
-                if (f_keep < 0.5f) {
+                // with several slots, save it even if only the tail is lost: parallel requests with the same
+                // prefix (e.g. subagents with the root agent's system prompt) can then restore it in other slots
+                if (f_keep < 0.5f || (slots.size() > 1 && f_keep < 1.0f)) {
                     update_cache = true;
                 }
             }
@@ -1671,6 +1673,12 @@ private:
             }
         }
 
+        // a requested slot that is empty never passes the similarity check (f_keep = 0/0): still
+        // look in the prompt cache for it
+        if (ret && task.id_slot != -1 && ret->prompt.tokens.empty()) {
+            update_cache = true;
+        }
+
         if (ret) {
             update_cache = update_cache && prompt_cache;
 
@@ -1682,6 +1690,14 @@ private:
 
                 const int64_t t_start = ggml_time_us();
 
+                // idle slots are only saved after this task launched (cache_idle_slots): save them now so
+                // this slot can restore a prefix that another idle slot holds (no copy if already cached)
+                for (server_slot & slot : slots) {
+                    if (&slot != ret && !slot.is_processing()) {
+                        slot.prompt_save(*prompt_cache);
+                    }
+                }
+
                 ret->prompt_save(*prompt_cache);
 
                 if (!ret->prompt_load(*prompt_cache, task.tokens)) {
diff --git a/tools/server/server-task.cpp b/tools/server/server-task.cpp
index 0d3beb313..4bb29db97 100644
--- a/tools/server/server-task.cpp
+++ b/tools/server/server-task.cpp
@@ -1835,9 +1835,6 @@ bool server_prompt_cache::load(server_prompt & prompt, const server_tokens & tok
 
                 return false;
             }
-
-            data.clear();
-            data.shrink_to_fit();
         }
 
         {
@@ -1853,15 +1850,14 @@ bool server_prompt_cache::load(server_prompt & prompt, const server_tokens & tok
 
                     return false;
                 }
-
-                data.clear();
-                data.shrink_to_fit();
             }
         }
 
-        prompt = std::move(it_best->prompt);
+        // keep the entry: other slots (e.g. parallel subagents with the same system prompt) can
+        // restore the same prefix; mark it most recently used so it is evicted last
+        prompt = it_best->prompt.clone();
 
-        states.erase(it_best);
+        states.splice(states.end(), states, it_best);
     }
 
     return true;