Writing
Transformers ·Attention ·Positional Encoding

Positional Encoding

Attention works out which words matter to each other, but on its own it cannot tell "the dog bit the man" from "the man bit the dog". Here is how a transformer is told where each token sits.

interactive explainer

same word, three meanings

One word. Three meanings.

Before we get to order, a quick recap of what attention already solved. The token "bit" shows up in three sentences and means something different each time.

context_aware_embedding
setthebit
token ID2699

starting embedding

means: a single bit of data, a 0 or a 1

thedogbit
token ID2699

starting embedding

means: bit as in bite, the past tense of a dog biting

alittlebit
token ID2699

starting embedding

means: a small amount of something

before attentionAll three "bit" tokens start out identical: token ID 2699, the same embedding. No context has touched them yet.
Three sentences, one token. Attention gives "bit" its meaning from the words next to it. Token IDs and embeddings are illustrative.

Attention fixed meaning. But it still has a blind spot: word order.

the machinery: Q, K, V

Query, Key, Value.

Attention "looks at neighbors", but how? Every token produces three vectors: a Query (what it is looking for), a Key (what it advertises), and a Value (what it carries). Here is one attention step on "the dog bit", with bit doing the looking.

query_key_value
Qbit is looking for its subject: who did the biting?
the
Kdeterminer
dog
Kagent
bit
Kverb
Vdog's Value flows into bit, making it context-aware: a biting, by the dog.

01 / 04 · match (Q · K)

Query: what bit is looking for

Every token casts a Query, the thing it wants to find. bit is a verb, so its Query hunts for a subject: who did the biting?

QQuery (Q)

what a token is looking for

e.g. bit: a verb hunting for its subject, who did the biting?

KKey (K)

what a token advertises about itself, like a billboard

e.g. dog: I am a noun, an agent.

VValue (V)

the content a token carries, blended in when it is attended to

e.g. dog's meaning gets pulled into bit.

One attention step (a single head) on "the dog bit": Query meets Key to decide where to look, then Value decides what gets carried. bit is the Query here; Q rose, K violet, V teal.

the blind spot: word order

Same words. Opposite meaning.

"The dog bit the man" and "the man bit the dog" use the exact same tokens. Only the order differs. Flip between them and watch what attention outputs.

attention_output

tokenized

The785
dog5562
bit2699
the785
man4842
The785
man4842
bit2699
the785
dog5562

The number under each word is its token ID, the integer index of that word in the vocabulary (not a 0-1 value). Both sentences use the exact same token IDs, only the order differs. (IDs are the course's illustrative values.)

Output Embeddings

dog[0.52, 0.48, ...]
bit[0.5, 0.5, ...]
man[0.47, 0.53, ...]
who bit whom???? attention cannot tell
order-agnosticThe rows reorder, but every token keeps the exact same vector. Attention sees a bag of words, not a sequence.
The model that knows "the dog bit" from "a little bit" cannot tell who did the biting. Output vectors are the lesson's illustrative numbers.

Additive Positional Embeddings

Give every token its address.

The first fix: before a token enters the transformer, add a second vector that says where it sits. Token embedding plus position vector equals a position-aware embedding.

position_aware_embedding
sentence
position vectors
Token embeddingPositionPosition-aware
thepos 0
+
=
dogpos 1
+
=
bitpos 2
+
=
thepos 3
+
=
manpos 4
+
=

Look at "man": position 4 in one sentence, position 1 in the other. Different position, different sum, so order finally reaches the model.

Each position vector is the same size as the token embedding (1024-dim here), so the two can be added element by element.

Fixed: produced by a set formula (the original Transformer's sinusoidal encoding). Never trained, defined for any position.

sentenceIn "the dog bit the man", man sits at position 4: its vector is X₅ + P₄.
Same word, different position, different vector. 1024-dim vectors are drawn as strips; values are illustrative.

but language is relative

Position is relative, not absolute.

Absolute positions ("you are token 3") are a clumsy fit for language. What usually matters is the distance between words, and that is exactly what absolute encoding misses.

relative_distance
Neitherhasitrainedtodaynorwillitraintomorrow
Press to slip words between Neither and nor. The gap grows, but they are still one pair, so absolute position is the wrong thing to track.
gap:5 tokensrelationship:Neither ... nor (unchanged)
relationship"Neither" and "nor" are 5 tokens apart here, yet the pairing is the same.

Push "Neither" and "nor" apart and the absolute gap grows, but the grammatical link is identical. Relative distance is what carries the meaning.

Thecatthatsatonthematishappy
is agrees with catnot the closer "mat"

"is" must agree with its subject "cat", not with the closer noun "mat". The link reaches across the sentence, no matter the absolute slots.

Absolute position cannot capture "5 apart" versus "7 apart, same relationship". This is what motivates RoPE.

Rotary Positional Embeddings

RoPE: rotate, don't add.

Most large language models today (Llama, Qwen, Mistral, DeepSeek) use Rotary Positional Embeddings. Position is not added to the input. It is applied inside attention, by rotating the Query and Key vectors by an angle set by each token's position. Here is what that buys you, step by step.

rope_rotation
bit (Q)dog (K)
thedogbit

01 / 05

An attention score is alignment

Take the Query of "bit" and the Key of "dog". Their attention score is just how aligned the two vectors are: a smaller angle means a higher score, which means pay more attention here.

attention score0.94

gap 20°

Inside one attention head

XQKVRoPEAttention

Q and K get rotated. V does not: position should decide who looks at whom, not what content gets carried.

Rmq,  Rnk  =  g(q,k,  mn)\langle R_m\,q,\; R_n\,k \rangle \;=\; g(q,\,k,\; m-n)

Rotate q by its position, rotate k by its position. Their dot product then depends only on the gap m - n, so attention reads relative distance directly, no extra step.

q, k
the Query and Key vectors
R_m, R_n
rotate by position m and n
⟨ , ⟩
dot product, the attention score
m - n
the gap between the two positions (relative distance)
g(...)
depends only on q, k and that gap
Relative positionsNo max-sequence limit
An auto-playing walkthrough: bit is the Query, dog is the Key, and the bar is their attention score. A 2D slice; real RoPE rotates many pairs of dimensions.

No Positional Embedding

NoPE: maybe the mask already knows.

A research finding: under some conditions a model learns word order with no positional encoding at all. The causal mask on its own leaks position.

causal_maskopen research

The causal mask decides who may look at whom. Each row is a token doing the looking (its Query); each column is a token it might look at (its Key). A token may attend to itself and everything before it, never to a token in the future.

thedogbit
the
0
-inf
-inf
dog
0
0
-inf
bit
0
0
0
row = Query (the token looking)column = Key (the token looked at)
0 = can attend-inf = blocked (future)
field of view:...
No Positional EmbeddingPosition 0 can see 1 token, position 1 sees 2, position 2 sees 3. Every position has a different field of view, and that asymmetry is itself a position signal.

It is still an open question: how much position information must we hand the model, and how much can it infer from the input's own structure?

Hover a row: how many tokens that position can attend to. Green can be seen, rose is masked to -inf. Still an open question in practice.

the four methods

Four ways to encode position.

Where each one injects position, whether it is absolute or relative, and whether a max-sequence limit applies.

method_comparison
MethodWhereTypeMax-seq limitNotes
Fixed (sinusoidal)
Added to input embeddingAbsoluteNone (formula covers any position)Original Transformer. Not trained.
Learned
Added to input embeddingAbsoluteYes (matrix row count)Trained like token embeddings. Simple, but two limits.
RoPEtoday's standard
Inside attention, on Q and KRelativeNone (context extension)Today's standard: Llama, Qwen, Mistral, DeepSeek.
NoPE
Nowhere (no explicit encoding)Implicit (causal mask)NoneResearch finding. Works under some conditions.
RoPE is the default in modern open-weight models.

the takeaway

Attention is not all you need.

Attention decides who looks at whom. Positional encoding adds where. RoPE rotates Query and Key so relative position falls straight out of the dot product, with no max-sequence wall in sight.