Commit de32b268c for llama.cpp
commit de32b268c4ad55d45f3b7b16c029f4e077f4ba74
Author: Anton Sokolchenko <wsevendays@gmail.com>
Date: Sun Nov 15 12:36:08 2026 +0100
Support DFLASH2 for Recursive Ripple-65B-Preview (#31904)
* fixed support for DFlash2 for Ripple 65B
* spec: Add NoPE handling to DFlash
(cherry picked from commit 89ea8e3e77e3359d17902a2db136022d5d419d88)
* spec: Fix NoPE not being picked up by DFlash
(cherry picked from commit 43393b95fda2ce7e7d243e2650bf7b1cadf1c732)
---------
Co-authored-by: James Pickering <james_pic@hotmail.com>
diff --git a/conversion/base.py b/conversion/base.py
index b8461072e..ac231ac94 100644
--- a/conversion/base.py
+++ b/conversion/base.py
@@ -1979,6 +1979,12 @@ class TextModel(ModelBase):
if (local_rope_theta := self.rope_parameters.get("sliding_attention", {}).get("rope_theta")) is not None:
self.gguf_writer.add_rope_freq_base_swa(local_rope_theta)
logger.info(f"gguf: rope theta swa = {local_rope_theta}")
+ # Add rope_pattern from no_rope_layers
+ if no_rope_layers := self.hparams.get("no_rope_layers"):
+ # Convert 1/0 to bool (1 = use RoPE, 0 = NoPE)
+ rope_pattern = [bool(x) for x in no_rope_layers]
+ self.gguf_writer.add_rope_pattern(rope_pattern)
+ logger.info(f"gguf: rope_pattern = {sum(rope_pattern)} RoPE layers / {len(rope_pattern)} total")
if (f_rms_eps := self.find_hparam(["rms_norm_eps", "norm_eps"], optional=True)) is not None:
self.gguf_writer.add_layer_norm_rms_eps(f_rms_eps)
logger.info(f"gguf: rms norm epsilon = {f_rms_eps}")
diff --git a/conversion/granite.py b/conversion/granite.py
index 74622ad43..8bfae2644 100644
--- a/conversion/granite.py
+++ b/conversion/granite.py
@@ -112,14 +112,6 @@ class GraniteSWAModel(GraniteModel):
logger.info("gguf: (granite_swa) sliding_window_pattern (inferred) = %d SWA layers / %d total",
sum(is_swa), n_layers)
- # Add rope_pattern from no_rope_layers
- if no_rope_layers := self.hparams.get("no_rope_layers"):
- # Convert 1/0 to bool (1 = use RoPE, 0 = NoPE)
- rope_pattern = [bool(x) for x in no_rope_layers]
- self.gguf_writer.add_rope_pattern(rope_pattern)
- logger.info("gguf: (granite_swa) rope_pattern = %d RoPE layers / %d total",
- sum(rope_pattern), len(rope_pattern))
-
@ModelBase.register("GraniteMoeSWAForCausalLM")
class GraniteMoeSWAModel(GraniteSWAModel):
diff --git a/src/llama-context.cpp b/src/llama-context.cpp
index 3e931f1cf..93edabc02 100644
--- a/src/llama-context.cpp
+++ b/src/llama-context.cpp
@@ -2923,8 +2923,11 @@ uint32_t llama_context::graph_max_nodes() const {
res = std::max<uint32_t>(1024u, 32u * model.n_tensors());
} else if (model.arch == LLM_ARCH_DFLASH && model.hparams.dflash_selector_rank > 0) {
// DFlash2's convolutions and selector are shape work rather than matmuls,
- // so they cost ~8.6 nodes per tensor against ~5.9 for a plain DFlash draft
- res = std::max<uint32_t>(1024u, 12u*model.n_tensors());
+ // so they cost ~8.6 nodes per tensor against ~5.9 for a plain DFlash draft.
+ // The selector lattice scales with the draft block size; 12u was calibrated
+ // on block-8 drafters, so scale the budget for larger blocks (e.g. Ripple's 16).
+ const uint32_t block_scale = std::max<uint32_t>(1u, model.hparams.dflash_block_size/8u);
+ res = std::max<uint32_t>(1024u, 12u*block_scale*model.n_tensors());
} else {
res = std::max<uint32_t>(1024u, 8u*model.n_tensors());
for (const auto & lora : model.loras) {
diff --git a/src/models/dflash.cpp b/src/models/dflash.cpp
index ea1e862a9..96360e404 100644
--- a/src/models/dflash.cpp
+++ b/src/models/dflash.cpp
@@ -77,6 +77,8 @@ void llama_model_dflash::load_arch_hparams(llama_model_loader & ml) {
hparams.rope_freq_scale_train_swa = hparams.rope_freq_scale_train;
}
+ ml.get_key_or_arr(LLM_KV_ATTENTION_ROPE_PATTERN, hparams.rope_pattern, hparams.n_layer(), false);
+
type = LLM_TYPE_UNKNOWN;
}
@@ -263,7 +265,11 @@ llama_model_dflash::graph_base::graph_base(const llm_graph_params & params) : ll
std::copy(std::begin(hparams.rope_sections), std::begin(hparams.rope_sections) + 4, sections);
}
-ggml_tensor * llama_model_dflash::graph_base::build_rope(ggml_tensor * cur, ggml_tensor * pos) {
+ggml_tensor * llama_model_dflash::graph_base::build_rope(ggml_tensor * cur, ggml_tensor * pos, int il) {
+ if (!hparams.has_rope(il)) {
+ return cur;
+ }
+
return rope_type == GGML_ROPE_TYPE_MROPE
? ggml_rope_multi(ctx0, cur, pos, nullptr,
n_rot, sections, rope_type, n_ctx_orig, freq_base, freq_scale,
@@ -292,7 +298,7 @@ ggml_tensor * llama_model_dflash::graph_base::build_inject() {
if (shared_kv) {
Vcur = ggml_rms_norm(ctx0, Vcur, hparams.f_norm_rms_eps);
}
- Kcur = build_rope(Kcur, inp_pos);
+ Kcur = build_rope(Kcur, inp_pos, il);
cb(Kcur, "Kcur_injected", il);
cb(Vcur, "Vcur_injected", il);
@@ -382,8 +388,8 @@ ggml_tensor * llama_model_dflash::graph_base::build_layers(ggml_tensor * inp_tok
Vcur = ggml_rms_norm(ctx0, Vcur, hparams.f_norm_rms_eps);
}
- Qcur = build_rope(Qcur, inp_pos);
- Kcur = build_rope(Kcur, inp_pos);
+ Qcur = build_rope(Qcur, inp_pos, il);
+ Kcur = build_rope(Kcur, inp_pos, il);
cb(Qcur, "Qcur", il);
cb(Kcur, "Kcur", il);
cb(Vcur, "Vcur", il);
diff --git a/src/models/models.h b/src/models/models.h
index e5bc8113d..913c52ade 100644
--- a/src/models/models.h
+++ b/src/models/models.h
@@ -1574,7 +1574,7 @@ struct llama_model_dflash : public llama_model_base {
ggml_tensor * build_inp_tokens();
ggml_tensor * build_layers(ggml_tensor * inp_tokens);
ggml_tensor * build_logits(ggml_tensor * cur);
- ggml_tensor * build_rope(ggml_tensor * cur, ggml_tensor * pos);
+ ggml_tensor * build_rope(ggml_tensor * cur, ggml_tensor * pos, int il);
};
struct graph_dflash : public graph_base {
diff --git a/src/models/ricursive.cpp b/src/models/ricursive.cpp
index e14caa8b3..306cdd4dc 100644
--- a/src/models/ricursive.cpp
+++ b/src/models/ricursive.cpp
@@ -132,6 +132,8 @@ llama_model_ricursive::graph::graph(const llm_graph_params & params) : llm_graph
for (int il = 0; il < n_layer; ++il) {
const auto & layer = model.layers[il];
+ res->t_layer_inp[il] = inpL;
+
ggml_tensor * inpSA = inpL;
cur = build_norm(inpL, layer.attn_norm, NULL, LLM_NORM_RMS, il);