Commit 0f35d6d7b for llama.cpp

commit 0f35d6d7b0f548993d4323eb1df8e7ca4cf039c5
Author: randomized <286843573@qq.com>
Date:   Tue Nov 3 23:53:57 2026 +0800

    spec : save and restore MTP hidden state (#30141)

    * speculative : save and restore MTP hidden state

    Assisted-by: Codex

    * tests : remove MTP state test

    Assisted-by: Codex

    * speculative : simplify MTP checkpoint state

    Save only the boundary hidden row; verification rows are rebuilt on the supported restore paths.

    Assisted-by: GPT-6

    ---------

    Co-authored-by: zouyongxing <zouyongxing@bytedance.com>

diff --git a/common/speculative.cpp b/common/speculative.cpp
index 14fee2b2c..f82dc879f 100644
--- a/common/speculative.cpp
+++ b/common/speculative.cpp
@@ -1967,6 +1967,29 @@ struct common_speculative_impl_draft_mtp : public common_speculative_impl {
         const size_t row_bytes = (size_t) n_embd * sizeof(float);
         std::memcpy(pending_h[seq_id].data(), verify_h[seq_id].data() + (size_t) i_h * n_embd, row_bytes);
     }
+
+    bool get_state(llama_seq_id seq_id, std::vector<uint8_t> & data) const override {
+        if (seq_id < 0 || seq_id >= (llama_seq_id) n_seq) {
+            return false;
+        }
+
+        const size_t row_bytes = (size_t) n_embd * sizeof(float);
+        data.resize(row_bytes);
+        std::memcpy(data.data(), pending_h[seq_id].data(), row_bytes);
+        return true;
+    }
+
+    void set_state(llama_seq_id seq_id, const std::vector<uint8_t> & data) override {
+        if (seq_id < 0 || seq_id >= (llama_seq_id) n_seq) {
+            return;
+        }
+
+        const size_t row_bytes = (size_t) n_embd * sizeof(float);
+        if (data.size() != row_bytes) {
+            return;
+        }
+        std::memcpy(pending_h[seq_id].data(), data.data(), row_bytes);
+    }
 };

 // state of self-speculation (simple implementation, not ngram-map)