| 448 | } |
| 449 | |
| 450 | ggml_tensor * llm_build_qwen3next::build_layer_attn( |
| 451 | llm_graph_input_attn_kv * inp, |
| 452 | ggml_tensor * cur, |
| 453 | ggml_tensor * inp_pos, |
| 454 | int il) { |
| 455 | const int64_t n_embd_head = hparams.n_embd_head_v; |
| 456 | GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); |
| 457 | |
| 458 | // Order: joint QG projection, QG split, Q norm, KV projection, K norm, RoPE, attention |
| 459 | |
| 460 | // Qwen3Next uses a single Q projection that outputs query + gate |
| 461 | ggml_tensor * Qcur_full = build_lora_mm(model.layers[il].wq, cur); |
| 462 | cb(Qcur_full, "Qcur_full", il); |
| 463 | |
| 464 | Qcur_full = ggml_reshape_4d(ctx0, Qcur_full, n_embd_head * 2, n_head, n_tokens, 1); |
| 465 | |
| 466 | // Split Q projection into query and gate |
| 467 | // The split should be along dimension 0 (the feature dimension) |
| 468 | ggml_tensor * Qcur = ggml_view_4d(ctx0, Qcur_full, n_embd_head, n_head, n_tokens, 1, |
| 469 | Qcur_full->nb[1], Qcur_full->nb[2], Qcur_full->nb[3], 0); |
| 470 | ggml_tensor * gate = |
| 471 | ggml_view_4d(ctx0, Qcur_full, n_embd_head, n_head, n_tokens, 1, |
| 472 | Qcur_full->nb[1], Qcur_full->nb[2], Qcur_full->nb[3], n_embd_head * ggml_element_size(Qcur_full)); |
| 473 | cb(Qcur, "Qcur", il); |
| 474 | cb(gate, "gate", il); |
| 475 | |
| 476 | // Now reshape Qcur to [n_embd_head, n_head, n_tokens] for multi-head attention |
| 477 | Qcur = ggml_cont_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); |
| 478 | cb(Qcur, "Qcur_reshaped", il); |
| 479 | |
| 480 | // Apply Q normalization |
| 481 | Qcur = build_norm(Qcur, model.layers[il].attn_q_norm, nullptr, LLM_NORM_RMS, il); |
| 482 | cb(Qcur, "Qcur_normed", il); |
| 483 | |
| 484 | ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); |
| 485 | cb(Kcur, "Kcur", il); |
| 486 | |
| 487 | ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); |
| 488 | cb(Vcur, "Vcur", il); |
| 489 | |
| 490 | // Apply K normalization |
| 491 | Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens); |
| 492 | Kcur = build_norm(Kcur, model.layers[il].attn_k_norm, nullptr, LLM_NORM_RMS, il); |
| 493 | cb(Kcur, "Kcur_normed", il); |
| 494 | |
| 495 | // Reshape gate to [n_embd, n_tokens] for the sigmoid gating (flatten the heads) |
| 496 | gate = ggml_cont_2d(ctx0, gate, n_embd_head * n_head, n_tokens); |
| 497 | cb(gate, "gate_reshaped", il); |
| 498 | |
| 499 | Vcur = ggml_reshape_3d(ctx0, Vcur, n_embd_head, n_head_kv, n_tokens); |
| 500 | |
| 501 | // Apply RoPE |
| 502 | Qcur = ggml_rope_ext( |
| 503 | ctx0, Qcur, inp_pos, nullptr, |
| 504 | n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, |
| 505 | ext_factor, attn_factor, beta_fast, beta_slow); |
| 506 | |
| 507 | Kcur = ggml_rope_ext( |
nothing calls this directly
no test coverage detected