Skip to content

fix(nn): apply RoPE on the input shape, not a reshaped 3D tensor - #357

Open
sergey-scherbina wants to merge 1 commit into
oxiglade:mainfrom
sergey-scherbina:fix/rope-decode-single-position
Open

fix(nn): apply RoPE on the input shape, not a reshaped 3D tensor#357
sergey-scherbina wants to merge 1 commit into
oxiglade:mainfrom
sergey-scherbina:fix/rope-decode-single-position

Conversation

@sergey-scherbina

Copy link
Copy Markdown

Problem

RotaryPositionalEncoding::forward reshapes [B, n_heads, L, head_dim] to
[-1, L, head_dim] before calling mx.fast.rope, then reshapes back. For
single-position input (L == 1, i.e. every autoregressive decode step) the
collapsed [B*n_heads, 1, head_dim] shape hits a fast::rope bug that rotates
only the first row along the leading axis — every head past the first is left
un-rotated. The result is corrupt decode queries and garbage generation.

Prefill (L > 1) is unaffected, so this only surfaces during incremental
decoding, which makes it easy to miss.

Python mlx_lm applies mx.fast.rope to the 4D tensor directly and is correct.

Fix

Drop the reshape and apply RoPE on the input shape directly.

Test

Adds test_rope_rotates_all_heads_when_single_position: feeds four identical
heads at a non-zero offset and asserts every head comes out identical to a
single-head reference (RoPE depends only on position, so identical heads must
rotate identically) and that the rotation is non-trivial. Fails before this
change (heads 1–3 stay un-rotated), passes after.

`RotaryPositionalEncoding::forward` reshaped [B, n_heads, L, head_dim] to
[-1, L, head_dim] before `mx.fast.rope`. For single-position input (L == 1,
i.e. every decode step) the resulting [B*n_heads, 1, head_dim] shape triggers a
fast-rope bug that rotates only the first batch row, leaving every head past the
first un-rotated -> corrupt decode queries -> garbage generation. Prefill
(L > 1) is unaffected, so this only shows up during incremental decoding.

Python mlx_lm applies `mx.fast.rope` to the 4D tensor directly and is correct.
Fix: drop the reshape and apply RoPE on the input shape.

Adds a regression test that feeds identical heads at a non-zero offset and
asserts every head is rotated alike (a single-head reference, broadcast).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant