Skip to main content

frink_models/
parallel_dense_ffn.rs

1//! **A DENSE FFN SUMMED WITH THE ROUTED EXPERTS** -- the Grok-2 and
2//! Arctic layer shape, served through the shared-expert slot, with the
3//! two things that differ between the two graphs as one table.
4//!
5//! # What it is
6//!
7//! `src/models/grok.cpp:66-68` creates `ffn_gate` / `ffn_up` /
8//! `ffn_down` as `TENSOR_NOT_REQUIRED` beside the routed experts, and
9//! `:171-184` does this when they are present:
10//!
11//! ```text
12//! if (model.layers[il].ffn_up) {
13//!     ffn_out = build_ffn(cur, ffn_up, ffn_gate, ffn_down, LLM_FFN_GELU, LLM_FFN_PAR, il);
14//!     cur = ggml_scale(ctx0, ggml_add(ctx0, ffn_out, moe_out), std::sqrt(2) / 2);
15//! } else {
16//!     cur = moe_out;
17//! }
18//! ```
19//!
20//! `src/models/arctic.cpp:38-42` creates the same three REQUIRED, sized
21//! `{n_embd, n_embd}`, and `:118-154` runs `ffn_out = build_ffn(
22//! ffn_norm(ffn_inp), ...SILU, PAR)`, `moe_out = build_moe_ffn(
23//! ffn_norm_exps(inpSA), ...)` and sums them with no scale.
24//!
25//! # Reach -- MEASURED
26//!
27//! Over all 155 `src/models/*.cpp` (2026-09-12): every graph that calls
28//! `build_moe_ffn` AND reads a dense `layers[il].ffn_up` was listed;
29//! all but two use the dense triple on their LEADING dense layers
30//! (`if (il < n_layer_dense_lead)` or `if (ffn_gate_inp == nullptr)`)
31//! or as `_shexp`. The two that SUM a dense FFN with the routed output
32//! on one layer are `grok.cpp:171-184` and `arctic.cpp:118-154`. So
33//! [`PARALLEL_DENSE_FFN_ARCHITECTURES`] has two rows, and the two free
34//! parameters are the columns: whether the triple is required
35//! (`arctic`) or optional (`grok`: Grok-1 has none and takes the
36//! `else`), and the scale on the sum (`sqrt(2)/2` for `grok`, none for
37//! `arctic`). What does NOT differ and so is not a column: the dense
38//! branch reads the normed FFN input `cur` in both, and its activation
39//! is the architecture's dense activation (GELU for `grok`, SiLU for
40//! `arctic`), which is what `ModelConfig::layer_ffn_acts(il).dense`
41//! already answers for the shared-expert slot. Arctic's OTHER
42//! difference -- the routed branch reading `ffn_norm_exps(inpSA)` --
43//! is `crate::router_input::RouterInput::NormedLayerInput`, one graph
44//! of 155, and not this module's business.
45//!
46//! # Why the shared-expert slot
47//!
48//! `MoeWeights::shared_experts` is already "a dense FFN that fires on
49//! every token and is added to the routed sum", computed with the
50//! architecture's dense activation on the normed FFN input, in the
51//! row body and the batched body alike; every fused Metal MoE launch
52//! refuses a layer that has one. What the slot lacked was the tensor
53//! NAMES (it loads `_shexp`) and the scale on the sum, which is why
54//! this module used to be a refusal: reading Grok-2's triple into it
55//! would have dropped the `sqrt(2)/2`. The loader fills the slot from
56//! the dense names for these two architectures and records the row's
57//! scale on the layer (`MoeWeights::parallel_sum_scale`), which the
58//! FFN bodies apply to the WHOLE branch output -- `ffn_out + moe_out`
59//! -- before the post-FFN norm, where `grok.cpp:180` applies it. A
60//! Grok-1 layer has no triple, loads no shared expert and carries no
61//! scale, which is the `else` branch.
62
63use std::f32::consts::FRAC_1_SQRT_2;
64
65use frink_gguf::TensorSource;
66
67use crate::LoadError;
68
69/// Whether the dense triple must be present on a routed layer.
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum DensePresence {
72    /// `create_tensor(..., 0)`: absent is a load error upstream.
73    Required,
74    /// `TENSOR_NOT_REQUIRED`: absent means "no dense branch, no scale".
75    Optional,
76}
77
78/// One architecture whose routed layers sum a dense FFN with the
79/// experts.
80#[derive(Debug, Clone, Copy)]
81pub struct ParallelDenseFfn {
82    pub arch: &'static str,
83    pub presence: DensePresence,
84    /// The factor on `ffn_out + moe_out`, or `None` for a plain sum.
85    pub sum_scale: Option<f32>,
86    pub lines: &'static str,
87}
88
89/// The two graphs, with the lines.
90pub const PARALLEL_DENSE_FFN_ARCHITECTURES: &[ParallelDenseFfn] = &[
91    ParallelDenseFfn {
92        arch: "grok",
93        presence: DensePresence::Optional,
94        sum_scale: Some(FRAC_1_SQRT_2),
95        lines: "src/models/grok.cpp:66-68,171-184",
96    },
97    ParallelDenseFfn {
98        arch: "arctic",
99        presence: DensePresence::Required,
100        sum_scale: None,
101        lines: "src/models/arctic.cpp:38-42,118-154",
102    },
103];
104
105/// The SAME scale on the SAME sum, under the `_shexp` names: a graph
106/// whose routed layers carry a real shared expert and scale
107/// `moe_out + shexp_out` by a constant. `cohere2moe.cpp:248-260`
108/// (`ggml_scale(ctx0, ggml_add(cur, ffn_shexp), 0.5f)`, the HF
109/// "average" combination strategy, the only one its converter admits,
110/// `conversion/command_r.py:103-105`) is the one graph of 155 that does
111/// (measured: `grep -n 'ggml_scale' src/models/*.cpp` beside a
112/// `ffn_shexp`), and only on a layer that HAS the shared expert
113/// (`:248` `if (layer.ffn_up_shexp)`). The loader records it as
114/// `MoeWeights::parallel_sum_scale`, the field the two dense rows
115/// above already fill, so the FFN bodies apply one scale at one site
116/// whichever names the dense branch was loaded from.
117pub const SHARED_EXPERT_SUM_SCALE: &[(&str, f32, &str)] =
118    &[("cohere2moe", 0.5, "src/models/cohere2moe.cpp:248-260")];
119
120/// The scale on `moe_out + shexp_out` for `arch`, when its routed
121/// layer carries a shared expert; `None` for a plain sum.
122pub fn shared_expert_sum_scale(arch: &str, has_shared_expert: bool) -> Option<f32> {
123    if !has_shared_expert {
124        return None;
125    }
126    SHARED_EXPERT_SUM_SCALE
127        .iter()
128        .find(|(a, _, _)| *a == arch)
129        .map(|(_, scale, _)| *scale)
130}
131
132/// The row for an architecture, or `None` for one whose routed layers
133/// have no dense branch.
134pub fn parallel_dense_ffn(arch: &str) -> Option<&'static ParallelDenseFfn> {
135    PARALLEL_DENSE_FFN_ARCHITECTURES
136        .iter()
137        .find(|row| row.arch == arch)
138}
139
140/// Whether routed layer `l` of `arch` carries the dense triple, by the
141/// row's presence rule: `Some(row)` when it does and the loader should
142/// fill the shared-expert slot from `ffn_{gate,up,down}` and record the
143/// scale, `None` when the layer runs the experts alone.
144///
145/// Refuses a REQUIRED triple that is missing (llama.cpp's loader would
146/// fail on the same tensor), and an incomplete triple in either case,
147/// because a graph with `ffn_up` and no `ffn_down` exists nowhere.
148pub fn parallel_dense_for_layer(
149    arch: &str,
150    file: &impl TensorSource,
151    l: usize,
152) -> Result<Option<&'static ParallelDenseFfn>, LoadError> {
153    let Some(row) = parallel_dense_ffn(arch) else {
154        return Ok(None);
155    };
156    let names = ["ffn_gate", "ffn_up", "ffn_down"].map(|t| format!("blk.{l}.{t}.weight"));
157    let present = names
158        .iter()
159        .filter(|n| file.find_tensor(n).is_some())
160        .count();
161    match (present, row.presence) {
162        (3, _) => Ok(Some(row)),
163        (0, DensePresence::Optional) => Ok(None),
164        (0, DensePresence::Required) => Err(LoadError::Gguf(
165            frink_gguf::GgufError::TensorNotFound(format!(
166                "{} (the dense half of `{arch}`'s parallel dense + MoE layer, REQUIRED by {})",
167                names[1], row.lines
168            )),
169        )),
170        _ => Err(LoadError::UnsupportedFeature(
171            arch.to_string(),
172            format!(
173                "layer {l} carries {present} of the dense `ffn_gate` / `ffn_up` / `ffn_down` \
174                 triple; {} reads all three or none",
175                row.lines
176            ),
177        )),
178    }
179}
180
181#[cfg(test)]
182mod tests {
183    use super::*;
184    use crate::test_source::StubSource;
185
186    const TRIPLE: [&str; 3] = [
187        "blk.0.ffn_gate.weight",
188        "blk.0.ffn_up.weight",
189        "blk.0.ffn_down.weight",
190    ];
191
192    /// Grok-2's triple is served with the scale; Grok-1's absence is
193    /// the `else` branch; Arctic's absence is a missing REQUIRED tensor.
194    #[test]
195    fn presence_follows_each_rows_rule() {
196        let grok2 = parallel_dense_for_layer("grok", &StubSource::with_tensors(&TRIPLE), 0)
197            .unwrap()
198            .expect("Grok-2 has the branch");
199        assert_eq!(grok2.sum_scale, Some(FRAC_1_SQRT_2));
200        assert!(
201            parallel_dense_for_layer("grok", &StubSource::with_tensors(&[]), 0)
202                .unwrap()
203                .is_none()
204        );
205
206        let arctic = parallel_dense_for_layer("arctic", &StubSource::with_tensors(&TRIPLE), 0)
207            .unwrap()
208            .expect("Arctic always has the branch");
209        assert_eq!(arctic.sum_scale, None);
210        let err = parallel_dense_for_layer("arctic", &StubSource::with_tensors(&[]), 0)
211            .expect_err("REQUIRED");
212        assert!(err.to_string().contains("arctic.cpp:38-42"), "{err}");
213
214        // An incomplete triple is refused on both rows.
215        for arch in ["grok", "arctic"] {
216            let err = parallel_dense_for_layer(arch, &StubSource::with_tensors(&TRIPLE[..2]), 0)
217                .err()
218                .unwrap_or_else(|| panic!("{arch}: 2 of 3 refused"));
219            assert!(err.to_string().contains("2 of the dense"), "{err}");
220        }
221    }
222
223    /// Every other architecture with a dense `ffn_up` is a dense model
224    /// or a leading-dense MoE, and neither is this table's business.
225    #[test]
226    fn a_dense_ffn_on_any_other_architecture_is_not_this_tables_business() {
227        for arch in ["llama", "deepseek", "dbrx", "qwen3moe", "smallthinker"] {
228            assert!(
229                parallel_dense_for_layer(arch, &StubSource::with_tensors(&TRIPLE), 0)
230                    .unwrap()
231                    .is_none(),
232                "{arch}"
233            );
234        }
235    }
236
237    /// Every row is an audited generic-path architecture, or the seam
238    /// is unevidenced.
239    #[test]
240    fn every_row_is_an_audited_generic_row() {
241        for row in PARALLEL_DENSE_FFN_ARCHITECTURES {
242            let profile = crate::capability::resolve_profile(row.arch).unwrap_or_else(|| {
243                panic!(
244                    "`{}` ({}) is not a registered architecture",
245                    row.arch, row.lines
246                )
247            });
248            assert!(matches!(
249                profile.path,
250                crate::capability::ArchPath::GenericGqa { .. }
251            ));
252            assert!(
253                crate::capability::AUDITED_GENERIC_GQA.contains(&row.arch),
254                "{}",
255                row.arch
256            );
257        }
258    }
259}