YaRN RoPE
gpt-oss
Medium
NTK-by-parts inverse frequency scaling that extends RoPE to long contexts.
Independent study note. Written from the public paper and official code. This is not TensorTonic Plus and does not reproduce their exercises, starter code, or tests. For the official version, subscribe on TensorTonic.
Overview
gpt-oss applies rotary position embeddings to every attention layer and stretches the dense layers to a 131,072-token context with YaRN (Peng et al., 2023). The model card names RoPE and YaRN and gives the target length. It does not give (\theta), the scale factor, or the NTK cutoffs. Those live in ModelConfig and RotaryEmbedding._compute_concentration_and_inv_freq in the official reference model.
The trained rotary basis is the 4,096-token “initial context.” At inference the inverse frequencies of the low-frequency pairs are interpolated toward a (32\times) longer horizon ((4096\times 32=131072)), high-frequency pairs keep their original (\theta), and a YaRN concentration multiplies (\cos) and (\sin). Sliding-window layers still use the same rotary module; they simply mask keys. Positions stay absolute.
How it works
Head width is (d_h=64), so there are (d_h/2=32) frequency pairs. The unscaled RoPE base is (\theta_{\mathrm{base}}=150{,}000):
f_i = \theta_{\mathrm{base}}^{2i/d_h},\qquad i=0,\ldots,31,
and the ordinary inverse frequency is (1/f_i). When the YaRN scale (s=32>1), the code forms two candidates
\omega^{\mathrm{interp}}_i=\frac{1}{s\,f_i},\qquad \omega^{\mathrm{extra}}_i=\frac{1}{f_i}
and blends them with an NTK-by-parts ramp. Let (L=4096), (\alpha=1), (\beta=32). Dimension-space cutoffs are
r_{\mathrm{low}}=\frac{d_h}{2}\frac{\log\bigl(L/(\beta\cdot 2\pi)\bigr)}{\log\theta_{\mathrm{base}}},\qquad r_{\mathrm{high}}=\frac{d_h}{2}\frac{\log\bigl(L/(\alpha\cdot 2\pi)\bigr)}{\log\theta_{\mathrm{base}}}.
A linear ramp (u_i=(i-r_{\mathrm{low}})/(r_{\mathrm{high}}-r_{\mathrm{low}})) is clipped to ([0,1]). The mix mask is (m_i=1-\mathrm{clip}(u_i)):
\tilde{\omega}_i = (1-m_i)\,\omega^{\mathrm{interp}}_i + m_i\,\omega^{\mathrm{extra}}_i.
Small (i) (high-frequency pairs) have (m_i=1) and keep the original (\theta). Large (i) (low-frequency pairs) have (m_i=0) and use (\theta/s). The mid band interpolates. That is the “NTK-by-parts” recipe the YaRN paper describes and that the official comment points at (https://arxiv.org/abs/2309.00071).
YaRN’s attention-temperature / concentration factor is
c = 0.1\log s + 1.
For token index (t) and pair (i),
\cos_{t,i}=c\cos(t\tilde{\omega}_i),\qquad \sin_{t,i}=c\sin(t\tilde{\omega}_i).
Application is a half-rotation, not the interleaved even/odd form. Split the last axis of a head in half, (x=(x_1,x_2)), then
x'_1 = x_1\cos - x_2\sin,\qquad x'_2 = x_2\cos + x_1\sin.
The same ((\cos,\sin)) tables rotate (Q) and (K). (V) is not rotated. If (s=1), concentration is 1 and (\tilde{\omega}_i=1/f_i) (plain RoPE). The public checkpoint uses (s=32).
The paper specifies only “YaRN to 131,072.” The numbers (150{,}000), (4096), (32), (\alpha=1), (\beta=32), and the half-split rotation are inferred from official code.
Official code
gpt_oss/torch/model.py: ModelConfig (rope_theta, initial_context_length, rope_scaling_factor, rope_ntk_alpha, rope_ntk_beta). RotaryEmbedding._compute_concentration_and_inv_freq implements the ramp; _compute_cos_sin applies (c); _apply_rotary_emb does the half-split rotate. AttentionBlock constructs one RotaryEmbedding per layer with those config values.
Watch-outs
- Do not apply a single global (\theta\leftarrow\theta/s) (pure PI) or a single NTK (\theta_{\mathrm{base}}) rescale. The point of YaRN here is a per-pair blend plus concentration.
- (c) multiplies (\cos) and (\sin), which scales the rotated vector’s pairwise structure. Folding (c) into (\tilde{\omega}) instead changes the angles, not the same thing.
- Pair index (i=0) is the highest frequency. Reversing the ramp (stretching high frequencies, freezing low ones) inverts YaRN.
- Rotate (Q) and (K) only, with absolute positions (0\ldots T-1). Re-basing positions inside a sliding window desynchronizes local and dense layers.
Sources
- Paper: gpt-oss-120b & gpt-oss-20b Model Card, §2.2
- YaRN: Peng et al., “YaRN: Efficient Context Window Extension of Large Language Models”, 2023
- Code: openai/gpt-oss
gpt_oss/torch/model.py(RotaryEmbedding)