Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

~12 min readRoFormer · 2021

Rotary position embedding,
explained.

Attention, on its own, is blind to order — it sees a bag of tokens, not a sentence. Every transformer needs a way to tell it where each token sits. RoPE's answer is quietly elegant: don't add a position vector, rotate the query and key by an angle set by their position. Because rotations add when you compose them, the attention score between two tokens ends up depending only on how far apart they are. Here's the geometry, and why it powers nearly every modern LLM.

The delta

What changes against sinusoidal positions: rotate, do not add

Rung 2 supplies position by adding a position vector to a token's embedding before attention ever happens. That works, and it has a structural oddity: the attention score between two tokens then depends on their two absolute positions, and any sense of "these are three apart" has to be reconstructed by the network from that. What a language model overwhelmingly wants is relative distance — the word before this one matters because it is before this one, not because it is word 4,096.

The change is to stop adding and start rotating. Treat each pair of dimensions in the query and key vectors as a point in a plane and rotate it by an angle proportional to the token's position. Then the dot product of a query at position m with a key at position n is, by the algebra of rotations, a function of the rotation m − n: relative position falls out of the arithmetic instead of being learned from absolute inputs. Different dimension pairs are rotated at different rates — a geometric spread of frequencies — so some pairs track fine local offsets and others track position at the scale of the whole sequence.

Stated in the ladder's units: sinusoidal encodings add a vector and change the values that flow through the network; RoPE modifies only the queries and keys, leaves the values untouched, adds no learned parameters at all, and the paper proves an upper bound on its attention score that decays on average with distance, so faraway tokens tend to interact less. The claim that made it spread beyond elegance is about extrapolation — a scheme defined by relative offsets has no built-in largest position, so in principle it might keep working past the length it was trained on — a hope the paper does not test, and one that plain RoPE did not meet in practice.

01

Attention is order-blind

Self-attention computes how much each token should attend to each other by comparing their query and key vectors — but it does this over an unordered set. Shuffle the words and, without extra information, the mechanism produces the same result. "Dog bites man" and "man bites dog" would be indistinguishable. So every transformer must inject position information somewhere.

The original transformer added a fixed sinusoidal position vector to each token's embedding. It works, but it is bolted on: position is mixed into the content, and what the model really cares about — how far apart two tokens are — has to be recovered indirectly. RoPE asks a sharper question: what if position lived in the geometry of the query and key comparison itself?

The one-sentence version

Instead of adding a position vector to a token, rotate its query and key by an angle proportional to position — and the dot product that drives attention automatically encodes relative distance.

02

Absolute vs relative position

There are two ways to tell a model about order. Absolute encoding stamps each token with its index: this is position 5, this is position 6. Relative encoding cares instead about the offset between tokens: this token is 2 places before that one. For language, relative structure is usually what matters — "the adjective right before the noun" is a relative fact, true whether the phrase starts at word 3 or word 300.

Relative encoding also generalizes better. A model that has learned to handle offsets up to a few thousand does not care where in the sequence they occur, so it was hoped to extend more gracefully to lengths it never saw in training (later work found plain RoPE needs help to do this). The challenge had always been building a relative scheme that stays cheap and slots naturally into the attention dot product. Rotation is that scheme.

03

The rotation trick

Split each query and key vector into consecutive 2D pairs. For a token at position m, rotate every pair by an angle m·θi, where each pair i has its own frequency θi. In matrix form, apply a rotation R(mθ) to the query and R(nθ) to the key. Then take their dot product as usual. The magic is what that dot product simplifies to:

Because rotation matrices satisfy R(a)ᵀR(b) = R(b − a), the two absolute rotations collapse into a single rotation by the difference of positions. The attention score therefore depends only on n − m — the relative distance — even though you only ever rotated by absolute positions. Different pairs use different frequencies θi = base^−2i/d (base is usually 10000), so short-range and long-range relationships are each captured by their own rate of rotation. The runnable version below confirms both facts directly.

04

Why relative falls out

The whole result rests on one property of rotations: rotating by α then by β is the same as rotating by α + β. Angles simply add. So when a query rotated by mθ meets a key rotated by nθ, the comparison "un-rotates" one against the other and what remains is a rotation by (n − m)θ. Two consequences worth naming:

Two facts the geometry guarantees
Same offsetTokens 2 apart score identically whether at positions (3,5) or (300,302) — absolute index doesn't matter.
Zero offsetA token compared with itself: the rotations cancel exactly, recovering the plain, position-free dot product.
Norm preservedRotation never changes a vector's length, so RoPE doesn't distort magnitudes — it only re-aims them.

That last point matters practically: because rotation is norm-preserving, RoPE injects position without inflating or shrinking activations, keeping the attention scores well-behaved. Position becomes a pure change of direction, layered cleanly onto content that lives in magnitude and angle already.

How it works

How RoFormer applies rotary position embedding, step by step

RoFormer is a Transformer in which RoPE replaces the absolute position embeddings. Everything else, from the projections to the softmax, is unchanged, and RoPE adds no trained parameters.

one pair (x₁, x₂) of q and k q · angle mθ k · angle nθ (n − m)θ score depends only on n − m values v are never rotated rotation rate per pair, d = 128 pair 1: θ = 1, period ≈ 6 tokens pair 17: θ = 0.1, period ≈ 63 pair 33: θ = 0.01, period ≈ 630 pair 49: θ = 0.001, period ≈ 6,300 pair 64: θ ≈ 0.0001, period ≈ 54,000 θj = 10000^(−2(j−1)/d)
RoPE rotates each pair of query and key coordinates by position; the score sees only the angle between them, at many rotation rates at once.
  1. Project without positions. Token embeddings enter the network with no position vector added. Each attention layer computes queries and keys as usual, q = Wqxm and k = Wkxn.
  2. Pair the dimensions. A head of dimension d is split into d/2 two-dimensional pairs. The paper pairs neighbouring coordinates, (x₁, x₂), (x₃, x₄) and so on, as GPT-J's code does. GPT-NeoX and the Hugging Face LLaMA code instead pair coordinate i with coordinate i + d/2, the version usually called rotate_half. The two are the same method up to a fixed reordering of coordinates, but a checkpoint trained with one only runs correctly under the other if the rows of Wq and Wk are permuted to match.
  3. Give each pair a frequency. Pair j turns at θj = 10000^−2(j−1)/d radians per token, a geometric spread from 1 radian per token down to roughly one ten-thousandth.
  4. Rotate by position. In the query at position m, pair j is rotated by mθj; in the key at position n, by nθj. In code this is two element-wise products with precomputed cosine and sine tables plus a swap-and-negate of coordinates: O(d) work per token, and no n × n bias matrix is ever built.
  5. Attend as usual, values untouched. The dot product of a rotated query and key depends on position only through n − m, so every score sees relative position directly. Values are not rotated, so the content being mixed carries no position signal of its own.
  6. Repeat in every layer. An added embedding enters once at the bottom and has to survive the residual stream. The rotation is applied afresh to the queries and keys of every attention layer.

Two properties the paper proves

Long-term decay. The authors write the score as a sum of rotating complex terms and apply Abel summation. That bounds its size by a quantity whose average shrinks as |m − n| grows, given the 10000 frequency spread. It is a bound, not a promise that every score falls with distance: real scores oscillate underneath it.

Linear-attention compatibility. RoPE acts on each query and key separately, not on the n × n score matrix, so it can be added to kernelized linear attention such as the Performer. The paper rotates the feature-mapped queries and keys in the numerator and leaves the normalizing denominator unrotated, which avoids any risk of dividing by zero. The cost, which the authors acknowledge, is that the weights on the values are no longer strictly normalized.

How the paper tested it

The experiments swap RoPE into existing recipes instead of building new models. They cover a Transformer-base translation model on WMT 2014 English-German, a BERT-style masked language model pre-trained on BookCorpus and English Wikipedia and then fine-tuned on GLUE, a Performer language model on enwik8, and Chinese RoFormer models pre-trained with maximum lengths up to 1,024 tokens for a long-document task.

The math

The RoPE rotation in the form it is computed

RΘ,m x = x ⊙ (cos mθ₁, cos mθ₁, …, cos mθd/2, cos mθd/2) + (−x₂, x₁, …, −xd, xd−1) ⊙ (sin mθ₁, sin mθ₁, …, sin mθd/2, sin mθd/2)
θj = 10000^−2(j−1)/d, j = 1, …, d/2
qm · kn = Re[ Σj q̃j k̃j^* ei(m−n)θj ]
  • x — a projected query or key of dimension d. The same function is applied to both, with that token's own position.
  • ⊙ — element-wise product with tables that depend only on position, so they are computed once and reused for every layer and head.
  • (−x₂, x₁, …) — each pair swapped with one sign flipped, which is what turns two multiplications into a 2-D rotation.
  • θj — the rotation rate of pair j, in radians per token.
  • q̃j, k̃j — pair j read as one complex number; * is the complex conjugate and i the imaginary unit.
  • m − n — the only place positions appear in the score.

At the extremes: when m = n every phase is zero and the score is the plain dot product. The fastest pair completes a full turn about every 6 tokens, so for large offsets its phase wraps around and carries only local information. The slowest pair barely turns across a training context, so it behaves almost like a position-free channel. Raising the base above 10000 slows every pair down, which is the lever later long-context models pull.

The evidence

What the RoFormer authors ran, and what it showed

Every experiment holds a published recipe fixed and changes only the position scheme, so each comparison is RoPE against whatever that recipe used before, usually learned or sinusoidal absolute positions.

ExperimentBaselineWith RoPE
WMT 2014 English-German, Transformer-base27.3 BLEU27.5 BLEU
English masked-LM pre-training, BERT recipeBERTfaster convergence, lower loss
GLUE fine-tuning, six tasksBERTclearly better on three, not on the rest
enwik8 with Performer linear attentionPerformerfaster convergence, lower loss
Long Chinese legal-case matching (CAIL2019-SCM)BERT, WoBERT at 512 tokenslevel at 512; about 1.5 points higher at 1,024

Read honestly, the translation gain is small, 0.2 BLEU, and GLUE is mixed. The most distinctive results are the training curves: masked language modeling and the linear-attention Performer both converged faster with RoPE, which supports the claim that relative position is easier to learn when it is built into the score.

The long-document result needs one caveat. The gain at 1,024 tokens came from a model trained at that length reading more of each document, not from running a model beyond the length it was trained on. The paper does not test extrapolation, and when later work did, unmodified RoPE degraded badly past its training length.

The authors are explicit about what they could not explain. They prove the relative-position property and the long-term decay bound, but say they lack a thorough account of why RoPE converges faster than other position encodings, or why it does better on long texts when its decay property resembles that of existing schemes.

Since then

What the authors admit, and what happened next

The extrapolation claim is the part that did not survive contact. In practice, a model trained at one context length and run at several times that length with RoPE unchanged degrades badly — the rotations reach angles the model has never seen, and quality falls off a cliff rather than tapering. This is the clearest case on the ladder of a property that is true of the encoding and false of the trained model.

What followed is a family of patches, and they are worth naming because any long-context model you use today contains one: interpolating positions so a longer sequence is squeezed into the trained angular range, adjusting the frequency spread so high-frequency dimensions are treated differently from low ones, and the combinations of the two that became standard practice for extending a released model's context after training. None of these are in the original paper; all of them are RoPE plus an admission.

How it held up: as the default. Rotary positions are what the open-weight models use and what most frontier architectures are assumed to use, and the alternative that competed most seriously — biasing attention scores linearly with distance — lost on quality rather than on principle. The honest summary is that RoPE won the question it was built for (represent relative position cleanly and cheaply) and lost the question it was marketed on (extend context for free), and that both halves are why the context ladder exists as separate engineering rather than a solved corollary.

SOLVE IT YOURSELF

Rotate, and watch relative position appear

RoPE is a 2D rotation applied per pair of dimensions — a few lines of trigonometry. This rotates a query and key by their positions and scores them, showing the defining property directly: two tokens the same distance apart score identically regardless of where they sit (positions 5,3 and 7,5 give the same number), at equal positions the rotations cancel back to the plain dot product, rotation preserves vector length, angles compose additively, and each dimension pair spins at its own frequency. Change the positions or the vectors and confirm only the relative offset moves the score.

YOUR TASK

Write the body of rotate2d. Everything else in the file is already written; this is the function the paper is about. Press ▶ Run to check it against the 5 assertions below — they start red.

WHAT IT HAS TO SATISFY — 5 ASSERTIONS
  1. Rotation preserves vector norm
  2. The RoPE score depends only on relative position m - n
  3. At equal positions rotations cancel to the plain dot
  4. Rotation composes additively
  5. Per-pair frequencies decrease with dimension index
CPython · WebAssembly
06

Why it won

RoPE quietly became the default position encoding of the LLM era. LLaMA and its descendants, GPT-NeoX, PaLM, and most open models use it. It won by combining three things that had been hard to get together: it encodes relative position (what language needs), it slots directly into the existing attention dot product (no extra parameters, no architectural surgery), and it extends to longer contexts by rescaling its frequencies.

There is a deeper lesson in its elegance. Position had been treated as something you add to a representation; RoPE reframed it as something you do to the geometry of comparison. That change of perspective — from additive feature to rotational operation — is why a scheme this simple could quietly outlast the alternatives it replaced.

Worth knowing

RoPE is applied to the query and key only — never the value. Position shapes who attends to whom, but the information carried once attention is decided stays position-free.

07

Why it still matters

RoPE — Rotary Position Embedding — is how almost every modern LLM tells tokens apart by position, and it quietly solved problems the original approaches had. Rather than adding a position vector to each token (absolute encoding) or bolting on learned position tables, RoPE rotates each token's query and key vectors by an angle proportional to its position. When two tokens interact through attention, the math works out so that only their relative distance affects the result.

That relative property is the win. Attention naturally cares about "how far apart are these tokens," not their absolute indices, and RoPE bakes that in elegantly — no extra parameters, applied directly inside the attention dot product. It gives clean relative-position behavior while being simple and efficient to compute.

RoPE also turned out to be friendly to context extension. Because position is encoded as rotation frequencies, you can stretch or interpolate those frequencies to make a model trained on short contexts handle longer ones — techniques like position interpolation and NTK/YaRN scaling all build on RoPE, and they are a big part of how models grew from a few thousand to hundreds of thousands of tokens of context.

It matters because it is now the default: RoPE (and its scaled variants) is in most open LLMs, and long-context work overwhelmingly assumes it. Understanding rotary embeddings is understanding how today's models represent "where" a token is — and how they get extended to read far more of it.

Questions

Questions people ask about RoPE

How do you implement RoPE, and what is the difference between rotate_half and interleaved?

Precompute, for every position m and pair j, the angle m times theta_j, with theta_j equal to 10000 to the power minus 2(j minus 1)/d, and store its cosine and sine. For each query and key, multiply element-wise by the cosine table, add a swapped-and-negated copy of the vector multiplied by the sine table, then run attention as normal. Values are left alone. The two conventions differ only in which coordinates form a pair. Interleaved, used in the RoFormer paper and GPT-J, pairs neighbours (x1, x2). Rotate_half, used by GPT-NeoX and the Hugging Face LLaMA code, pairs x_i with x_i plus d/2. Both are correct, but weights from one need their query and key projections permuted to run under the other.

What is the difference between RoPE and ALiBi?

RoPE rotates queries and keys so the attention score becomes a function of relative position; it changes the angle between vectors and adds no parameters. ALiBi, from Press, Smith and Lewis's paper Train Short, Test Long, adds no position information to the vectors at all. It subtracts a penalty proportional to the distance between query and key from each attention score, with a different fixed slope per head. ALiBi was designed for length extrapolation and showed better perplexity than rotary or sinusoidal positions beyond the training length. BLOOM and MPT used ALiBi, while LLaMA and most later open models chose RoPE and closed the extrapolation gap with context-extension methods.

How is RoPE extended to a longer context window?

Not by running it unchanged: past the trained length the rotations reach angles the model never saw, and quality collapses. The common fixes all change the angles. Position Interpolation (Chen et al., 2023) divides positions by the extension factor, so a model trained at 4,096 tokens and run at 16,384 sees every position scaled by a quarter, then fine-tunes briefly. NTK-aware scaling raises the base instead, stretching slow pairs much more than fast ones so local resolution survives. YaRN (Peng et al., 2023) treats frequency bands differently and adds a temperature on the attention logits. Many models also simply train with a larger base; Llama 3 used 500,000. None of these are in the RoFormer paper.

Why does RoPE rotate the queries and keys but not the values?

Because position only needs to influence who attends to whom, and that is decided entirely by the query-key score. Rotating both q and k makes their dot product depend on the offset n minus m, which is the whole point. Rotating the values would stamp absolute positions onto the content being mixed, and the output would then carry a position signal that no longer cancels to a relative one. Leaving values alone keeps the mixed content position-free, while the next layer re-applies the rotation to its own queries and keys. It also keeps the cost low, since only two of the three projections are touched.

What does long-term decay mean in the RoFormer paper?

It is a property the authors prove about an upper bound on the attention score. Treating each coordinate pair as a complex number, the score is a sum of terms rotating at different rates with the relative distance. Using Abel summation, they show that this sum's magnitude is bounded by a quantity whose average decreases as the distance between query and key grows, for the standard 10000 frequency spread. The intuition is that distant tokens should, by default, interact less. It is not a guarantee that every score falls with distance: the actual scores oscillate below the bound, and a trained model can still attend strongly to a faraway token when the content calls for it.

Check yourself

4 questions to test what you just read

Work each one out before you open it — a number, a prediction or a reason, not a definition. Producing the answer is what makes it stick. Your progress is kept on this device.

For a 128-dimensional head with base 10,000, what are the rotation rate and the period, in tokens, of pair 1 and of pair 64?

Show answer

Pair 1: θ₁ = 10000⁰ = 1 radian per token, period 2π ≈ 6.3 tokens. Pair 64: θ₆₄ = 10000^−126/128 ≈ 1.15 × 10⁻⁴, period ≈ 2π / 1.15 × 10⁻⁴ ≈ 54,000 tokens. The fast pair resolves neighbours; the slow pair barely turns across a whole context.

The same query and key vectors sit first at positions (7, 3), then at (1,007, 1,003), then at (3, 7). Which of the three scores must be equal?

Show answer

The first two are equal: both have m − n = 4, and the score depends only on that offset. The third has m − n = −4, a rotation in the opposite direction, so in general it differs. RoPE encodes signed distance, which is how it can tell before from after.

A pair (1, 0) in a query at position m = 2 is rotated with θ = π/4. Where does it end up, and what is its dot product with an unrotated key (1, 0) at n = 0?

Show answer

The angle is mθ = π/2, so (1, 0) becomes (0, 1). Its dot product with (1, 0) is 0. Check with the relative form: rotating the key by (n − m)θ = −π/2 turns (1, 0) into (0, −1), and its dot product with the original query (1, 0) is also 0.

In an 8-dimensional head, which coordinate does coordinate 1 pair with under the interleaved convention, and which under rotate_half? Why can't checkpoints be swapped freely?

Show answer

Interleaved pairs 1 with 2; rotate_half pairs 1 with 5 (i with i + d/2). The rotation is applied to whichever coordinates the code pairs, and a trained Wq and Wk have learned to put matching content into those coordinates. Running one convention on the other's weights rotates the wrong pairs, unless the projection rows are permuted first.

Where this sits

The Transformer

The architecture itself: what it replaced, how position is encoded once recurrence is gone, and what it turns out to have learned inside.

  1. 1Seq2Seq2014
  2. 2Attention Is All You Need2017
  3. 3RoPE2021
  4. 4Concept Circuits2026

All 110 papers, in 19 ladders →

Finished this one? 0 / 110 Paper Breakdowns done
NextConcept Circuits Next on the “The Transformer” ladder · rung 4 of 4

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More Paper Breakdowns