| 817 | } |
| 818 | |
| 819 | ggml_tensor * llm_build_qwen3next::build_layer_ffn(ggml_tensor * cur, const int il) { |
| 820 | // Check if this is an MoE layer |
| 821 | if (model.layers[il].ffn_gate_inp != nullptr) { |
| 822 | // MoE branch |
| 823 | ggml_tensor * moe_out = |
| 824 | build_moe_ffn(cur, |
| 825 | model.layers[il].ffn_gate_inp, model.layers[il].ffn_up_exps, |
| 826 | model.layers[il].ffn_gate_exps, model.layers[il].ffn_down_exps, |
| 827 | nullptr, |
| 828 | n_expert, n_expert_used, LLM_FFN_SILU, |
| 829 | true, false, 0.0, LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, il); |
| 830 | cb(moe_out, "ffn_moe_out", il); |
| 831 | |
| 832 | // Add shared experts if present - following Qwen3Next reference implementation |
| 833 | if (model.layers[il].ffn_up_shexp != nullptr) { |
| 834 | ggml_tensor * ffn_shexp = |
| 835 | build_ffn(cur, |
| 836 | model.layers[il].ffn_up_shexp, NULL, NULL, |
| 837 | model.layers[il].ffn_gate_shexp, NULL, NULL, |
| 838 | model.layers[il].ffn_down_shexp, NULL, NULL, |
| 839 | NULL, |
| 840 | LLM_FFN_SILU, LLM_FFN_PAR, il); |
| 841 | cb(ffn_shexp, "ffn_shexp", il); |
| 842 | |
| 843 | // Apply shared expert gating as in the reference implementation |
| 844 | // The shared expert has its own gate that is sigmoided |
| 845 | // Note: ffn_gate_inp_shexp is the shared expert gate (outputs 1 value per token) |
| 846 | ggml_tensor * shared_gate = build_lora_mm(model.layers[il].ffn_gate_inp_shexp, cur); |
| 847 | cb(shared_gate, "shared_expert_gate", il); |
| 848 | |
| 849 | // Apply sigmoid to the gate |
| 850 | shared_gate = ggml_sigmoid(ctx0, shared_gate); |
| 851 | cb(shared_gate, "shared_expert_gate_sigmoid", il); |
| 852 | |
| 853 | // Apply the gate to the shared expert output |
| 854 | ffn_shexp = ggml_mul(ctx0, ffn_shexp, shared_gate); |
| 855 | cb(ffn_shexp, "ffn_shexp_gated", il); |
| 856 | |
| 857 | cur = ggml_add(ctx0, moe_out, ffn_shexp); |
| 858 | cb(cur, "ffn_out", il); |
| 859 | } else { |
| 860 | cur = moe_out; |
| 861 | } |
| 862 | } else { |
| 863 | // Dense FFN branch (not currently used I believe) |
| 864 | cur = build_ffn(cur, |
| 865 | model.layers[il].ffn_up, NULL, NULL, |
| 866 | model.layers[il].ffn_gate, NULL, NULL, |
| 867 | model.layers[il].ffn_down, NULL, NULL, |
| 868 | NULL, |
| 869 | LLM_FFN_SILU, LLM_FFN_PAR, il); |
| 870 | cb(cur, "ffn_out", il); |
| 871 | } |
| 872 | return cur; |
| 873 | } |
nothing calls this directly
no test coverage detected