Skip to content

Commit 4ecc7e4

Browse files
committed
qwen35: force pre-norm hidden state for MTP
Tap the MTP/nextn hidden state before the final output norm in both the trunk and MTP graphs of Qwen35 and Qwen35MoE, reverting the semantic core of the post-norm migration (ggml-org#24025) while keeping the upstream `nextn` naming and the masked (embeddings_nextn_masked) extraction path. This restores the fork's pre-norm Qwen MTP optimization (TheTom#149) on top of the rebased TurboQuant+ KV cache lineage, per explicit request to prefer pre-norm over upstream's post-norm/nextn approach. https://claude.ai/code/session_01HZZQMPA6D6KWgcuDsDarWa
1 parent 03bbefa commit 4ecc7e4

2 files changed

Lines changed: 20 additions & 15 deletions

File tree

src/models/qwen35.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,15 +204,17 @@ llama_model_qwen35::graph::graph(const llama_model & model, const llm_graph_para
204204
}
205205
cur = inpL;
206206

207-
cur = build_norm(cur, model.output_norm, nullptr, LLM_NORM_RMS, -1);
208-
207+
// Pre-norm hidden state (before the final output norm) seeds the MTP/nextn draft loop.
209208
cb(cur, "h_nextn", -1);
210209
res->t_h_nextn = cur;
211210

212211
if (!cparams.embeddings_nextn_masked && inp_out_ids) {
213212
cur = ggml_get_rows(ctx0, cur, inp_out_ids);
214213
}
215214

215+
// Final norm
216+
cur = build_norm(cur, model.output_norm, nullptr, LLM_NORM_RMS, -1);
217+
216218
cb(cur, "result_norm", -1);
217219
res->t_embd = cur;
218220

@@ -619,16 +621,17 @@ llama_model_qwen35::graph_mtp::graph_mtp(const llama_model & model, const llm_gr
619621
cur = ggml_add(ctx0, cur, ffn_residual);
620622
cb(cur, "mtp_post_ffn", il);
621623

624+
// Pre-norm hidden state: used by the AR draft loop to seed the next MTP step.
625+
cb(cur, "h_nextn", -1);
626+
res->t_h_nextn = cur;
627+
628+
cur = ggml_get_rows(ctx0, cur, inp_out_ids);
629+
622630
ggml_tensor * head_norm_w = layer.nextn.shared_head_norm
623631
? layer.nextn.shared_head_norm
624632
: model.output_norm;
625633
GGML_ASSERT(head_norm_w && "QWEN35 MTP: missing both nextn.shared_head_norm and output_norm");
626634
cur = build_norm(cur, head_norm_w, nullptr, LLM_NORM_RMS, -1);
627-
628-
cb(cur, "h_nextn", -1);
629-
res->t_h_nextn = cur;
630-
631-
cur = ggml_get_rows(ctx0, cur, inp_out_ids);
632635
cb(cur, "mtp_shared_head_norm", -1);
633636

634637
ggml_tensor * head_w = layer.nextn.shared_head_head ? layer.nextn.shared_head_head : model.output;

src/models/qwen35moe.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -227,16 +227,17 @@ llama_model_qwen35moe::graph::graph(const llama_model & model, const llm_graph_p
227227
}
228228
cur = inpL;
229229

230-
// post-norm hidden state feeds both the LM head and the MTP seed below
231-
cur = build_norm(cur, model.output_norm, nullptr, LLM_NORM_RMS, -1);
232-
230+
// Pre-norm hidden state (before the final output norm) seeds the MTP/nextn draft loop.
233231
cb(cur, "h_nextn", -1);
234232
res->t_h_nextn = cur;
235233

236234
if (!cparams.embeddings_nextn_masked && inp_out_ids) {
237235
cur = ggml_get_rows(ctx0, cur, inp_out_ids);
238236
}
239237

238+
// Final norm
239+
cur = build_norm(cur, model.output_norm, nullptr, LLM_NORM_RMS, -1);
240+
240241
cb(cur, "result_norm", -1);
241242
res->t_embd = cur;
242243

@@ -716,16 +717,17 @@ llama_model_qwen35moe::graph_mtp::graph_mtp(const llama_model & model, const llm
716717
cur = ggml_add(ctx0, cur, ffn_residual);
717718
cb(cur, "mtp_post_ffn", il);
718719

720+
// Pre-norm hidden state: used by the AR draft loop to seed the next MTP step.
721+
cb(cur, "h_nextn", -1);
722+
res->t_h_nextn = cur;
723+
724+
cur = ggml_get_rows(ctx0, cur, inp_out_ids);
725+
719726
ggml_tensor * head_norm_w = layer.nextn.shared_head_norm
720727
? layer.nextn.shared_head_norm
721728
: model.output_norm;
722729
GGML_ASSERT(head_norm_w && "QWEN35MOE MTP: missing both nextn.shared_head_norm and output_norm");
723730
cur = build_norm(cur, head_norm_w, nullptr, LLM_NORM_RMS, -1);
724-
725-
cb(cur, "h_nextn", -1);
726-
res->t_h_nextn= cur;
727-
728-
cur = ggml_get_rows(ctx0, cur, inp_out_ids);
729731
cb(cur, "mtp_shared_head_norm", -1);
730732

731733
ggml_tensor * head_w = layer.nextn.shared_head_head ? layer.nextn.shared_head_head : model.output;

0 commit comments

Comments
 (0)