Skip to content

Commit 403ee88

Browse files
fix(llama-cpp): refresh server patch contexts
The new llama.cpp pin moves reset, checkpoint, batch, and decode code. The old combined patches stop before the backend can compile. Keep the structural patches focused and apply moved batch edits after the upstream and TTS patches. Assisted-by: Codex:gpt-5
1 parent 9dde75e commit 403ee88

4 files changed

Lines changed: 75 additions & 71 deletions

File tree

backend/cpp/llama-cpp/patches/0001-add-server-task-type-score.patch

Lines changed: 2 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ index 3b5f6a1..d0e18e6 100644
9696
bool has_next_token = true;
9797
bool has_new_line = false;
9898
bool truncated = false;
99-
@@ -351,6 +378,10 @@ struct server_slot {
99+
@@ -351,4 +378,8 @@ struct server_slot {
100100
}
101101
generated_tokens.clear();
102102
generated_token_probs.clear();
@@ -105,8 +105,6 @@ index 3b5f6a1..d0e18e6 100644
105105
+ score_suffix_pending = false;
106106
+ score_divergence = -1;
107107
json_schema = json();
108-
109-
// clear speculative decoding stats
110108
@@ -2271,6 +2302,229 @@ private:
111109
queue_results.send(std::move(res));
112110
}
@@ -376,7 +374,7 @@ index 3b5f6a1..d0e18e6 100644
376374
const auto n_cache_reuse = slot.task->params.n_cache_reuse;
377375

378376
const bool can_cache_reuse =
379-
@@ -3455,8 +3727,12 @@ private:
377+
@@ -3366,8 +3638,12 @@ private:
380378

381379
bool do_checkpoint = params_base.n_ctx_checkpoints > 0;
382380

@@ -391,58 +389,6 @@ index 3b5f6a1..d0e18e6 100644
391389

392390
// make a checkpoint of the parts of the memory that cannot be rolled back.
393391
// checkpoints are created only if:
394-
@@ -3523,10 +3799,17 @@ private:
395-
// embedding requires all tokens in the batch to be output;
396-
// MTP also wants logits at every prompt position so the
397-
// streaming hook can mirror t_h_nextn into ctx_dft.
398-
+ // score tasks need outputs at the positions that predict
399-
+ // each candidate token (the token at index i predicts the
400-
+ // task token at index i+1).
401-
+ const bool need_score_logit =
402-
+ slot.task->type == SERVER_TASK_TYPE_SCORE &&
403-
+ slot.prompt.n_tokens() + 1 >= slot.task->n_score_prompt &&
404-
+ slot.prompt.n_tokens() + 1 < slot.task->n_tokens();
405-
add_ok &= batch.add(slot.id,
406-
cur_tok,
407-
slot.prompt.tokens.pos_next(),
408-
- slot.need_embd());
409-
+ slot.need_embd() || need_score_logit);
410-
slot.prompt.tokens.push_back(cur_tok);
411-
412-
slot.n_prompt_tokens_processed++;
413-
@@ -3541,6 +3824,32 @@ private:
414-
}
415-
}
416-
417-
+ // score tasks: break at the shared-prompt boundary so the checkpoint
418-
+ // below lands exactly there — the other candidates of the same
419-
+ // scoring call re-process only their own tokens. Also break at the
420-
+ // point where this task diverged from the previous cache: after a
421-
+ // forced re-prefill a checkpoint there serves the next scoring call
422-
+ // over the same stable prefix (e.g. a classifier's option list).
423-
+ // The caller-declared stable-prefix boundary is the strongest of
424-
+ // these: a checkpoint there is at or before every future task's
425-
+ // divergence within the same option list, so it always survives
426-
+ // and always restores.
427-
+ if (do_checkpoint && slot.task->type == SERVER_TASK_TYPE_SCORE &&
428-
+ (slot.prompt.n_tokens() == slot.task->n_score_prompt - 1 ||
429-
+ (slot.task->n_stable_prompt > 0 &&
430-
+ slot.prompt.n_tokens() == slot.task->n_stable_prompt &&
431-
+ slot.prompt.n_tokens() < slot.task->n_score_prompt - 1) ||
432-
+ (slot.prompt.n_tokens() == slot.score_divergence &&
433-
+ slot.prompt.n_tokens() < slot.task->n_score_prompt - 1))) {
434-
+ bool have_ckpt = false;
435-
+ for (const auto & ckpt : slot.prompt.checkpoints) {
436-
+ have_ckpt |= ckpt.n_tokens == slot.prompt.n_tokens();
437-
+ }
438-
+ if (!have_ckpt) {
439-
+ break;
440-
+ }
441-
+ }
442-
+
443-
// process the last few tokens of the prompt separately in order to allow for a checkpoint to be created.
444-
// create checkpoints that many tokens before the end of the prompt:
445-
// - 4 + n_ubatch
446392
@@ -3573,6 +3882,15 @@ private:
447393
const bool is_user_start = spans.is_user_start(n_tokens_start);
448394
const bool is_last_user_message = n_tokens_start == last_user_pos;

backend/cpp/llama-cpp/patches/0002-add-server-task-type-tts.patch

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -468,21 +468,6 @@ index 9069463fe..b7fa1e534 100644
468468
{
469469
// special case: if input is provided via CLI, tokenize it first
470470
// otherwise, no need to tokenize as it's already done inside the HTTP thread
471-
@@ -3092,6 +3174,14 @@ private:
472-
abort_all_slots("pre_decode() failed: " + std::string(e.what()));
473-
}
474-
475-
+ // note: TTS slots bypass the shared batch entirely
476-
+ try {
477-
+ process_tts_slots();
478-
+ } catch (const std::exception & e) {
479-
+ SRV_ERR("process_tts_slots() failed: %s\n", e.what());
480-
+ abort_all_slots("process_tts_slots() failed: " + std::string(e.what()));
481-
+ }
482-
+
483-
GGML_ASSERT(batch.slot_batched || batch.size() == 0);
484-
485-
if (batch.slot_batched) {
486471
@@ -3162,10 +3252,77 @@ private:
487472
}
488473
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
diff --git a/tools/server/server-context.cpp b/tools/server/server-context.cpp
2+
--- a/tools/server/server-context.cpp
3+
+++ b/tools/server/server-context.cpp
4+
@@ -3083,9 +3083,17 @@ private:
5+
abort_all_slots("pre_decode() failed: " + std::string(e.what()));
6+
7+
// the batch is half-built and not rendered, skip now to avoid UB
8+
return;
9+
}
10+
11+
+ // note: TTS slots bypass the shared batch entirely
12+
+ try {
13+
+ process_tts_slots();
14+
+ } catch (const std::exception & e) {
15+
+ SRV_ERR("process_tts_slots() failed: %s\n", e.what());
16+
+ abort_all_slots("process_tts_slots() failed: " + std::string(e.what()));
17+
+ }
18+
+
19+
GGML_ASSERT(batch.slot_batched || batch.size() == 0);
20+
21+
if (batch.slot_batched) {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
diff --git a/tools/server/server-context.cpp b/tools/server/server-context.cpp
2+
--- a/tools/server/server-context.cpp
3+
+++ b/tools/server/server-context.cpp
4+
@@ -3877,13 +3877,46 @@ private:
5+
// embedding requires all tokens in the batch to be output;
6+
// MTP also wants logits at every prompt position so the
7+
// streaming hook can mirror t_h_nextn into ctx_dft.
8+
+ // score tasks need outputs at the positions that predict
9+
+ // each candidate token (the token at index i predicts the
10+
+ // task token at index i+1).
11+
+ const bool need_score_logit =
12+
+ slot.task->type == SERVER_TASK_TYPE_SCORE &&
13+
+ slot.prompt.n_tokens() + 1 >= slot.task->n_score_prompt &&
14+
+ slot.prompt.n_tokens() + 1 < slot.task->n_tokens();
15+
add_ok &= batch.add(slot.id,
16+
cur_tok,
17+
/* pos = */ slot.prompt.tokens.pos_next(),
18+
- /* output = */ slot.need_embd(),
19+
+ /* output = */ slot.need_embd() || need_score_logit,
20+
/* is_prompt = */ true);
21+
slot.prompt.tokens.push_back(cur_tok);
22+
+
23+
+ // score tasks: break at the shared-prompt boundary so the checkpoint
24+
+ // below lands exactly there — the other candidates of the same
25+
+ // scoring call re-process only their own tokens. Also break at the
26+
+ // point where this task diverged from the previous cache: after a
27+
+ // forced re-prefill a checkpoint there serves the next scoring call
28+
+ // over the same stable prefix (e.g. a classifier's option list).
29+
+ // The caller-declared stable-prefix boundary is the strongest of
30+
+ // these: a checkpoint there is at or before every future task's
31+
+ // divergence within the same option list, so it always survives
32+
+ // and always restores.
33+
+ if (do_checkpoint && slot.task->type == SERVER_TASK_TYPE_SCORE &&
34+
+ (slot.prompt.n_tokens() == slot.task->n_score_prompt - 1 ||
35+
+ (slot.task->n_stable_prompt > 0 &&
36+
+ slot.prompt.n_tokens() == slot.task->n_stable_prompt &&
37+
+ slot.prompt.n_tokens() < slot.task->n_score_prompt - 1) ||
38+
+ (slot.prompt.n_tokens() == slot.score_divergence &&
39+
+ slot.prompt.n_tokens() < slot.task->n_score_prompt - 1))) {
40+
+ bool have_ckpt = false;
41+
+ for (const auto & ckpt : slot.prompt.checkpoints) {
42+
+ have_ckpt |= ckpt.n_tokens == slot.prompt.n_tokens();
43+
+ }
44+
+ if (!have_ckpt) {
45+
+ break;
46+
+ }
47+
+ }
48+
-
49+
+
50+
// break at the last user message, or at user messages at least min step past the last checkpoint
51+
if (do_checkpoint && spans.is_user_start(slot.prompt.n_tokens())) {
52+
const auto pos = slot.prompt.n_tokens();

0 commit comments

Comments
 (0)