1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//! **YaRN's magnitude term**, and the one key that adjusts it.
//!
//! YaRN has two halves. The FREQUENCY half -- which rotary bands are
//! interpolated toward the trained context and which stay extrapolated
//! -- lives in `frink_core::attention::yarn_freq_factors` and reaches
//! the kernels as per-band divisors. The MAGNITUDE half is a scalar on
//! the rotated channels of q and k, and until 2026-09-11 frink did not
//! apply it: `ModelConfig::rope_attn_factor` carried
//! `rope.scaling.attn_factor` alone, while llama.cpp multiplies that
//! key by a YaRN term it derives from the scaling factor. Every YaRN
//! checkpoint on the generic path -- the `*-128K` Qwen3 exports, every
//! Ministral-3 -- was therefore roped at the right frequencies and the
//! wrong magnitude, with attention logits low by the SQUARE of the
//! missing term (both q and k take it). Found reading
//! `mistral3.cpp:9` for `rope.scaling.yarn_log_multiplier`, whose
//! whole job is to adjust a term frink turned out not to have.
//!
//! # llama.cpp's arithmetic, in three places
//!
//! `llama-context.cpp:189-227`, when the scaling type is YaRN
//! (`yarn_ext_factor` defaults to 1.0 for it and 0.0 otherwise, :190):
//!
//! ```text
//! get_mscale(scale, m) = scale <= 1 ? 1 : 0.1 * m * ln(scale) + 1
//! factor = 1 / rope_freq_scale // = rope.scaling.factor
//! attn = log_mul != 0 ? get_mscale(factor, 1) / get_mscale(factor, log_mul)
//! : get_mscale(factor, 1) // :202-221
//! attn *= 1 / (1 + 0.1 * ln(factor)) // :227, "cancel this factor"
//! attn *= rope_attn_factor // :231, the GGUF key
//! ```
//!
//! and then ggml's `rope_yarn` (`ggml-cpu/ops.cpp:5835-5841`) multiplies
//! `mscale` by `1 + 0.1 * ln(1 / freq_scale)` -- the term :227 cancelled
//! -- before folding it into `cos` and `sin`. The two cancel exactly,
//! so what reaches the rotated channels is
//!
//! ```text
//! rope_attn_factor * get_mscale(factor, 1) / get_mscale(factor, log_mul) // log_mul != 0
//! rope_attn_factor * get_mscale(factor, 1) // otherwise
//! ```
//!
//! which is [`yarn_attn_magnitude`], folded into `rope_attn_factor` at
//! load time so that it rides the existing `apply_rope_attn_factor`
//! helper and the Metal `mscale` uniform unchanged.
//!
//! The `DEEPSEEK2` special case at :210-212 (`mscale = mscale_all_dims`
//! when it is not 1) belongs to the MLA engine and is not written here:
//! that engine reads no YaRN key at all today.
//!
//! # Who reads `yarn_log_multiplier` -- MEASURED
//!
//! `grep -rn rope_yarn_log_mul src/` over llama.cpp, 2026-09-11: the
//! key is read by `mistral3.cpp:9` (verbatim), `deepseek2.cpp:34-37`
//! and `deepseek32.cpp:36-39` (both divide it by 0.1 for a legacy
//! converter, `[TAG_DEEPSEEK2_YARN_LOG_MUL_FIX]`), and applied by
//! `glm-dsa.cpp:234,610` through deepseek2's hparams. The three
//! dedicated rows apply it INSIDE their graph's `kq_scale`
//! (`deepseek2.cpp:444-448`), a different formula on a different
//! engine. On the generic path `mistral3` is the only reader, so
//! `hparams.rope_yarn_log_mul` stays at its `llama-hparams.h:133`
//! default of 0 for every other architecture and the key is dead
//! metadata there -- [`yarn_log_mul_for`] returns 0 for it, and a test
//! pins that a `llama` file carrying the key is not changed by it.
//!
//! Real Ministral-3 files carry it: `conversion/mistral3.py:28` writes
//! `mscale_all_dim` from the HF `rope_parameters`, and
//! `conversion/mistral.py:99` writes `1.0` when the checkpoint's
//! `apply_scale` is false and `0.0` when true -- so a Ministral with
//! `yarn_log_multiplier = 1.0` has NO magnitude term at all (the ratio
//! is exactly 1) and one with `0.0` takes the plain `get_mscale`.
//! `mistral3_yarn_tiny.gguf` and `mistral3_yarn_logmul_tiny.gguf`
//! evidence both arms against libllama.
/// Generic-path architectures whose `load_arch_hparams` reads
/// `rope.scaling.yarn_log_multiplier`, with the line.
///
/// A census the resolver is checked against, like every other table
/// in this crate. The dedicated readers (`deepseek2`, `deepseek32`,
/// `glm-dsa`) are deliberately absent: their engines do not go through
/// `ModelConfig::rope_attn_factor`.
pub const YARN_LOG_MUL_READERS: & = &;
/// The `yarn_log_multiplier` llama.cpp's hparams hold for `arch` given
/// what the file declares: the declared value for an architecture that
/// reads the key, the `llama-hparams.h:133` default of `0.0` for every
/// other.
/// `llama-context.cpp:196-199`, in `f32` as it is there.
/// The magnitude every rotated channel of q and k is multiplied by
/// under YaRN scaling with the given `factor` (`rope.scaling.factor`)
/// and `log_mul` (`rope.scaling.yarn_log_multiplier`, 0 when the
/// architecture does not read it), BEFORE `rope.scaling.attn_factor`.
///
/// Exactly `1.0` for `factor <= 1`, which is llama.cpp's own
/// `get_mscale` floor and why a file with no scaling is untouched.