Skip to content

chore: update llama.cpp pin - #1012

Closed
ndizazzo wants to merge 1 commit into
mainfrom
codex/update-llama-pin-20260716
Closed

chore: update llama.cpp pin#1012
ndizazzo wants to merge 1 commit into
mainfrom
codex/update-llama-pin-20260716

Conversation

@ndizazzo

@ndizazzo ndizazzo commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Updates the pinned llama.cpp revision and rebases the 16 downstream Skippy patches, including the MiniMax M2 upstream overlap. Also makes just test-all install website dependencies in fresh worktrees.

Validation: just test-all

Summary by CodeRabbit

  • New Features

    • Added staged model execution, model slicing, multi-part loading, and activation/KV state exchange.
    • Expanded support for additional model families, recurrent models, multimodal workflows, and external decoding.
    • Added configurable sampling, token verification, session reset, trimming, checkpoints, and state restoration.
    • Added native and external MTP draft generation.
    • Added chat templates with reasoning/thinking controls and grammar improvements.
    • Added backend device enumeration, runtime progress events, and mmap/mlock load options.
  • Bug Fixes

    • Website production validation now installs dependencies before building.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The patch series adds the Skippy C ABI and staged execution foundation, expands model-family and activation-sideband support, adds ordered part loading and sampling controls, introduces native and external MTP workflows, and updates runtime events, chat parsing, validation, and patch metadata.

Changes

Skippy staged runtime

Layer / File(s) Summary
Staged ABI and tensor filtering foundation
third_party/llama.cpp/patches/0001-*
Adds the Skippy ABI, stage-aware model loading, filtered graph boundaries, activation handling, and GGUF slice/package operations.
Model-family staged execution and activation sidebands
third_party/llama.cpp/patches/0002-*, 0006-*, 0007-*, 0008-*
Extends staged execution across model families with activation-token, RWKV7, Gemma3n AltUp, and external decode support.
Sampling, checkpoints, and ordered part loading
third_party/llama.cpp/patches/0003-*, 0012-*
Adds ordered GGUF part loading, sampled decoding, session checkpoint/state operations, trimming, and mmap/mlock configuration.
Native and external MTP execution
third_party/llama.cpp/patches/0010-*, 0013-*, 0014-*
Adds MTP graph execution, external draft-model attachment, shared-context handling, and sampled MTP decode APIs.
Runtime events, devices, chat parsing, and validation
Justfile, third_party/llama.cpp/patches/0004-*, 0005-*, 0009-*, 0011-*, 0015-*, 0016-*, upstream.txt
Updates runtime/chat support, parser coverage, patch metadata, upstream tracking, and website build dependency installation.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested labels: Do not merge

Suggested reviewers: i386

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant SkippyABI
  participant llama.cpp
  participant MTP
  Client->>SkippyABI: Open model and create session
  SkippyABI->>llama.cpp: Load filtered model parts
  Client->>SkippyABI: Submit sampled decode
  SkippyABI->>llama.cpp: Execute staged graph
  llama.cpp-->>SkippyABI: Predicted token and activation
  SkippyABI->>MTP: Propose native draft tokens
  MTP-->>SkippyABI: MTP draft
  SkippyABI-->>Client: Return token, activation, and draft
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: updating the pinned llama.cpp revision and downstream patches.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/update-llama-pin-20260716

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ndizazzo ndizazzo changed the title Update llama.cpp pin chore: update llama.cpp pin Jul 16, 2026
@ndizazzo
ndizazzo marked this pull request as ready for review July 16, 2026 23:57
@github-actions

Copy link
Copy Markdown
Contributor

This pull request is currently a draft. Reviews will not take place until the PR is marked as ready for review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
third_party/llama.cpp/patches/0001-Add-Skippy-ABI-and-package-writer-foundation.patch (1)

1246-1261: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Missing null pointer check for logits.

If session->stage_model->config.include_output is false or if llama_get_logits_ith fails to return logits, logits will be nullptr. Dereferencing it in the loop will cause a segmentation fault.

🔒️ Proposed fix
 static llama_token skippy_greedy_sample(skippy_session * session) {
     const llama_vocab * vocab = llama_model_get_vocab(session->stage_model->model);
     const int32_t n_vocab = llama_vocab_n_tokens(vocab);
     const float * logits = llama_get_logits_ith(session->ctx, -1);
+    if (logits == nullptr) {
+        return -1;
+    }
 
     llama_token best = 0;
     float best_logit = -std::numeric_limits<float>::infinity();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@third_party/llama.cpp/patches/0001-Add-Skippy-ABI-and-package-writer-foundation.patch`
around lines 1246 - 1261, Update skippy_greedy_sample to handle a null result
from llama_get_logits_ith before iterating over logits; return an appropriate
safe fallback token, preserving the existing greedy selection when logits is
available.
third_party/llama.cpp/patches/0008-Add-external-decode-media-prefill-and-newer-family-s.patch (1)

893-911: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Prevent out-of-bounds memory access if n_embd_inp < n_embd.

If a model's architecture utilizes an n_embd_inp smaller than n_embd, the std::memcpy calls will write past the logical stride of embd_storage for each token, culminating in an out-of-bounds write on the final token. Additionally, the missing bounds check in the final else branch will cause static_cast<size_t>(n_embd_inp - n_embd) to wrap around to a huge value, leading to a crash in std::memset.

Limit the copy size to std::min(n_embd, n_embd_inp) and guard the memset operation.

🔒️ Proposed fix
     if ((input_desc->flags & SKIPPY_ACTIVATION_FLAG_GEMMA3N_ALTUP) != 0) {
         const float * input = static_cast<const float *>(input_payload);
+        const size_t copy_dim = static_cast<size_t>(std::min(n_embd, n_embd_inp));
         for (int32_t i = 0; i < n_tokens; ++i) {
             float * dst = embd_storage.data() + static_cast<size_t>(i)*n_embd_inp;
-            std::memcpy(dst, input + static_cast<size_t>(i)*n_embd, static_cast<size_t>(n_embd)*sizeof(float));
+            std::memcpy(dst, input + static_cast<size_t>(i)*n_embd, copy_dim*sizeof(float));
             if (n_embd_inp > n_embd) {
                 std::memset(dst + n_embd, 0, static_cast<size_t>(n_embd_inp - n_embd)*sizeof(float));
             }
         }
     } else if (n_embd_inp == n_embd) {
         std::memcpy(embd_storage.data(), input_payload, hidden_bytes);
     } else {
         const float * input = static_cast<const float *>(input_payload);
+        const size_t copy_dim = static_cast<size_t>(std::min(n_embd, n_embd_inp));
         for (int32_t i = 0; i < n_tokens; ++i) {
             float * dst = embd_storage.data() + static_cast<size_t>(i)*n_embd_inp;
-            std::memcpy(dst, input + static_cast<size_t>(i)*n_embd, static_cast<size_t>(n_embd)*sizeof(float));
-            std::memset(dst + n_embd, 0, static_cast<size_t>(n_embd_inp - n_embd)*sizeof(float));
+            std::memcpy(dst, input + static_cast<size_t>(i)*n_embd, copy_dim*sizeof(float));
+            if (n_embd_inp > n_embd) {
+                std::memset(dst + n_embd, 0, static_cast<size_t>(n_embd_inp - n_embd)*sizeof(float));
+            }
         }
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@third_party/llama.cpp/patches/0008-Add-external-decode-media-prefill-and-newer-family-s.patch`
around lines 893 - 911, Update the embedding-copy branches in the input payload
handling to copy only std::min(n_embd, n_embd_inp) elements per token,
preventing writes beyond each embd_storage stride. Guard both zero-padding
std::memset calls so they run only when n_embd_inp exceeds the copied embedding
width, avoiding unsigned underflow when it is smaller.
third_party/llama.cpp/patches/0003-Add-staged-sampling-checkpoints-and-part-loading.patch (1)

275-296: 🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift

Critical use-after-free hazard on ctx_gguf and unintended local variable mutation.

This loop contains two severe issues resulting from how the part context is managed:

  1. Use-after-free: The ctx_gguf smart pointer takes ownership of the newly loaded GGUF context and destroys it at the end of the for loop iteration. However, a raw pointer (ctx_gguf.get()) is passed into llama_tensor_weight and stored in weights_map. When llama_model_loader later accesses this weight (e.g., to read tensor data offsets), it will dereference freed memory and crash.
  2. Local variable overwrite: Passing &ctx to part_params.ctx overwrites the local ctx variable (which initially holds the primary file's ggml_context) on every iteration. While contexts.emplace_back(ctx) technically pushes the newly allocated context because of this side-effect, it leaves ctx pointing to the last part's context after the loop and makes the code highly brittle.

To fix both issues, transfer ownership of ctx_gguf to a persistent container that outlives the constructor (such as meta_splits, which upstream llama_model_loader uses for splits) and use an isolated local variable for the part context.

🐛 Proposed fix
-                struct gguf_init_params part_params = {
-                    /*.no_alloc = */ true,
-                    /*.ctx      = */ &ctx,
-                };
-                gguf_context_ptr ctx_gguf { gguf_init_from_file(fname_part, part_params) };
-                if (!ctx_gguf) {
-                    throw std::runtime_error(format("%s: failed to load GGUF part from %s", __func__, fname_part));
-                }
-
-                files.emplace_back(new llama_file(fname_part, "rb", use_direct_io));
-                contexts.emplace_back(ctx);
-
-                for (ggml_tensor * cur = ggml_get_first_tensor(ctx); cur; cur = ggml_get_next_tensor(ctx, cur)) {
+                struct ggml_context * part_meta = nullptr;
+                struct gguf_init_params part_params = {
+                    /*.no_alloc = */ true,
+                    /*.ctx      = */ &part_meta,
+                };
+                gguf_context_ptr ctx_gguf { gguf_init_from_file(fname_part, part_params) };
+                if (!ctx_gguf) {
+                    throw std::runtime_error(format("%s: failed to load GGUF part from %s", __func__, fname_part));
+                }
+
+                gguf_context * part_ctx = ctx_gguf.get();
+                meta_splits.emplace_back(std::move(ctx_gguf)); // Keep GGUF context alive
+
+                files.emplace_back(new llama_file(fname_part, "rb", use_direct_io));
+                contexts.emplace_back(part_meta);
+
+                for (ggml_tensor * cur = ggml_get_first_tensor(part_meta); cur; cur = ggml_get_next_tensor(part_meta, cur)) {
                     std::string tensor_name = std::string(cur->name);
                     if (weights_map.find(tensor_name) != weights_map.end()) {
                         continue;
                     }
                     n_elements += ggml_nelements(cur);
                     n_bytes    += ggml_nbytes(cur);
-                    weights_map.emplace(tensor_name, llama_tensor_weight(files.back().get(), part_idx, ctx_gguf.get(), cur));
+                    weights_map.emplace(tensor_name, llama_tensor_weight(files.back().get(), part_idx, part_ctx, cur));
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@third_party/llama.cpp/patches/0003-Add-staged-sampling-checkpoints-and-part-loading.patch`
around lines 275 - 296, Update the split-loading loop to preserve each part’s
GGUF context beyond the iteration by transferring ctx_gguf ownership into the
loader’s persistent meta_splits container before storing it in weights_map. Use
a separate local ggml_context* for part_params.ctx instead of mutating the
surrounding ctx variable, and store that isolated part context in contexts while
keeping the primary context unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@third_party/llama.cpp/patches/0001-Add-Skippy-ABI-and-package-writer-foundation.patch`:
- Around line 1246-1261: Update skippy_greedy_sample to handle a null result
from llama_get_logits_ith before iterating over logits; return an appropriate
safe fallback token, preserving the existing greedy selection when logits is
available.

In
`@third_party/llama.cpp/patches/0003-Add-staged-sampling-checkpoints-and-part-loading.patch`:
- Around line 275-296: Update the split-loading loop to preserve each part’s
GGUF context beyond the iteration by transferring ctx_gguf ownership into the
loader’s persistent meta_splits container before storing it in weights_map. Use
a separate local ggml_context* for part_params.ctx instead of mutating the
surrounding ctx variable, and store that isolated part context in contexts while
keeping the primary context unchanged.

In
`@third_party/llama.cpp/patches/0008-Add-external-decode-media-prefill-and-newer-family-s.patch`:
- Around line 893-911: Update the embedding-copy branches in the input payload
handling to copy only std::min(n_embd, n_embd_inp) elements per token,
preventing writes beyond each embd_storage stride. Guard both zero-padding
std::memset calls so they run only when n_embd_inp exceeds the copied embedding
width, avoiding unsigned underflow when it is smaller.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0e8b8432-e268-43a6-a36a-eb80be5f16eb

📥 Commits

Reviewing files that changed from the base of the PR and between f13c9dc and 8b7fab6.

📒 Files selected for processing (18)
  • Justfile
  • third_party/llama.cpp/patches/0001-Add-Skippy-ABI-and-package-writer-foundation.patch
  • third_party/llama.cpp/patches/0002-Add-early-staged-model-family-and-chat-support.patch
  • third_party/llama.cpp/patches/0003-Add-staged-sampling-checkpoints-and-part-loading.patch
  • third_party/llama.cpp/patches/0004-Add-lanes-external-media-and-chat-grammar-support.patch
  • third_party/llama.cpp/patches/0005-Add-resident-prefix-cache-and-session-refinements.patch
  • third_party/llama.cpp/patches/0006-Expand-staged-execution-across-dense-and-recurrent-f.patch
  • third_party/llama.cpp/patches/0007-Expand-staged-execution-across-VL-and-broad-model-fa.patch
  • third_party/llama.cpp/patches/0008-Add-external-decode-media-prefill-and-newer-family-s.patch
  • third_party/llama.cpp/patches/0009-Add-chat-grammar-device-enumeration-and-runtime-even.patch
  • third_party/llama.cpp/patches/0010-Add-MTP-execution-support-and-sampling-cleanup.patch
  • third_party/llama.cpp/patches/0011-Pass-reasoning-format-through-stage-chat-templates.patch
  • third_party/llama.cpp/patches/0012-Wire-mmap-and-mlock-runtime-load-options.patch
  • third_party/llama.cpp/patches/0013-Add-external-MTP-draft-sidecar-attachment.patch
  • third_party/llama.cpp/patches/0014-Add-non-frame-native-MTP-decode-ABI.patch
  • third_party/llama.cpp/patches/0015-Fix-stage-activation-graph-input-allocation.patch
  • third_party/llama.cpp/patches/0016-Recognize-thinking-field-in-chat-auto-parser.patch
  • third_party/llama.cpp/upstream.txt

@ndizazzo

Copy link
Copy Markdown
Collaborator Author

#1014 raced me and was merged

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant