Full Transformer Architecture
Imagine building a machine translation system. It reads an entire English sentence and understands it. Then it writes out a fluent French sentence word by word. The system must handle inputs and outputs of different lengths. It must keep track of what it has already generated. It must also constantly refer back to the source sentence to decide what to say next. This is the concrete problem the full Transformer architecture was designed to solve. It was introduced in 2017 as an alternative to recurrent sequence-to-sequence models. The full Transformer glues together two components that are often studied in isolation. These are an encoder stack that builds a contextual representation of the input, and a decoder stack that generates the output autoregressively while consulting the encoder's representation at every step. The mechanism that connects them, cross-attention, is the piece that turns two separate stacks into a single working seq2seq system. Understanding how information flows from source tokens to target tokens through this bridge is essential. It underlies machine translation, summarization, speech recognition, and any task framed as "map one sequence to another." This architecture matters because it is the direct ancestor of nearly every modern sequence model. Encoder-decoder Transformers power production translation systems. The same cross-attention idea reappears in image captioning, text-to-speech, and multimodal models. Those models must align one modality with another. Even architectures that later dropped the encoder, like decoder-only language models such as GPT, are best understood as specializations of this design. The same is true of architectures that dropped the decoder, like encoder-only models such as BERT. Both are specializations of this original, more general design. This article assembles the encoder and decoder into the complete system. It traces the full information flow from source tokens to output probabilities. It gives correctness and complexity arguments for the whole pipeline. It also works through a concrete translation example step by step. It closes by pointing toward how such architectures are pretrained at scale.
- The full Transformer is an encoder-decoder model: an encoder builds contextual source representations, a decoder generates target tokens autoregressively.
- Cross-attention is the bridge: decoder queries attend to encoder keys/values, letting every generated token look back at the whole source sentence.
- The decoder uses masked self-attention to prevent looking at future tokens, preserving valid left-to-right generation during training and inference.
- Training uses teacher forcing with parallel computation over the whole target sequence; inference is sequential, one token at a time.
- Total compute is dominated by self-attention terms, quadratic in sequence length, plus cross-attention, linear in target length times source length.
- This architecture is the direct predecessor of the pretraining paradigms (BERT-style, GPT-style, T5-style) that dominate modern NLP.
The full Transformer is two attention-based stacks — an encoder and a decoder — connected by cross-attention, so that every generated output token can directly attend to every input token regardless of distance.
The idea
A sequence-to-sequence (seq2seq) task maps an input sequence to an output sequence , where and can differ and are not known in advance. The full Transformer solves this with two cooperating stacks. The Transformer Encoder Stack reads the entire source sequence at once and produces a set of contextualized vectors , one per input token, each aware of the whole input through self-attention. The Transformer Decoder Stack generates the output sequence one token at a time, conditioning at each step on all previously generated tokens and on the encoder's output. The component that makes this a genuine encoder-decoder model, rather than two independent stacks, is cross-attention (also called encoder-decoder attention). In each decoder layer, after masked self-attention over the target prefix, a second attention sub-layer computes queries from the decoder's current hidden states but keys and values from the encoder's final output. This lets the decoder ask, at every generation step, "which parts of the source sentence are most relevant to the word I am about to produce?" Because attention is computed over all source positions simultaneously, this reference is direct — unlike a recurrent encoder-decoder model, there is no information bottleneck forcing the entire source meaning through a single fixed-size vector. Two attention masking conventions distinguish the stacks. Encoder self-attention is unmasked (bidirectional): position can attend to every position , since the whole input is available at once. Decoder self-attention is causally masked: position can attend only to positions , since at generation time future tokens do not exist yet. Cross-attention has no masking restriction on the source side (all source positions are visible) but is only ever queried from decoder positions, never the reverse. This asymmetry — full visibility into the past and the source, no visibility into the future — is what makes the model both a valid probabilistic language model over the target and a genuine translator of the source.
How it works
End-to-end pipeline. Training operates on a paired example . The encoder processes once, producing . The decoder is fed the target sequence shifted right (prepended with a start token, ``), and — using teacher forcing — is trained to predict the true next token at every position simultaneously, in one parallel forward pass, using as the cross-attention source at every layer. At inference time there is no ground-truth target to feed, so tokens are generated one at a time: each newly produced token is appended to the decoder input and the whole process (or an incrementally cached version of it) repeats until an end token is produced or a length limit is reached. ``` function ENCODE(x[1..n]): E = Embed(x) + PositionalEncoding(1..n) # n x d H = E for l in 1..L_enc: A = SelfAttention(H, H, H, mask = None) # bidirectional H = LayerNorm(H + A) F = FeedForward(H) H = LayerNorm(H + F) return H # n x d, final encoder memory function DECODE_TRAIN(y[1..m], H):
# teacher forcing: full target fed at once, causal mask enforces left-to-right validity D = Embed(shift_right(y)) + PositionalEncoding(1..m) # m x d for l in 1..L_dec: A1 = SelfAttention(D, D, D, mask = CAUSAL) # target attends only to its own past D = LayerNorm(D + A1) A2 = CrossAttention(query=D, key=H, value=H, mask = None) # target attends to all of source D = LayerNorm(D + A2) F = FeedForward(D) D = LayerNorm(D + F) logits = D @ W_out.T # m x |V| return logits function DECODE_INFER(H, max_len, bos, eos): tokens = [bos] for t in 1..max_len: D = DECODE_ONE_STEP(tokens, H) # same layer stack, causal mask, cross-attn to H next_token = argmax_or_sample(D[-1] @ W_out.T) tokens.append(next_token) if next_token == eos: break return tokens[1:] # drop bos ``` The three attention operations that appear above (encoder self-attention, decoder self-attention, cross-attention) all use the same scaled dot-product formula, differing only in where queries, keys, and values come from and whether a mask is applied: ``` function ATTENTION(Q, K, V, mask): scores = (Q @ K.T) / sqrt(d_k) # (len_Q x len_K) if mask is not None: scores = scores + mask # mask entries are 0 or -infinity weights = softmax(scores, axis=-1) # rows sum to 1 return weights @ V # (len_Q x d_v) ``` For decoder self-attention, `mask[i][j] = 0` if else , so that after softmax, position places zero probability on any future position . For cross-attention, `Q` comes from the decoder's current layer, `K` and `V` come from the encoder's final output `H`, and there is no mask — every source position is eligible. The figure below shows the full information flow for one decoding step, including where the two masking regimes and the cross-attention bridge sit relative to each other.
Complexity & correctness
Time complexity. Let be source length, be target length, the model dimension, and the number of layers per stack (assume roughly equal for encoder and decoder). Each self-attention sub-layer costs (encoder) or (decoder) for computing all pairwise scores and their weighted sums, since the score matrix has or entries and each requires an dot product; each feed-forward sub-layer costs or . Cross-attention costs : the decoder's queries each attend over encoder positions, and each score/weighted-sum computation is . Summing over layers, total training-time compute for one example is
For typical settings where is comparable to or larger than sequence length, the and feed-forward terms often dominate in practice, but the , , and attention terms are what make long sequences expensive — this is the well-known quadratic bottleneck of standard attention.
Training vs. inference asymmetry. During training, teacher forcing means the entire target sequence is available up front, so all decoder positions are processed in parallel in one forward pass — the causal mask is just an additive matrix, not a sequential control-flow constraint. This is why Transformer training parallelizes far better than recurrent seq2seq models, whose recurrence forces sequential steps. At inference, no such shortcut exists: each output token depends on the previous one through the argmax/sampling step, so generation genuinely requires sequential decoder passes, each — without caching — costing redundant recomputation of earlier positions. Production systems avoid most of this redundancy with a key-value cache: since keys and values for already-generated positions never change, they are computed once and reused, reducing each incremental step to work rather than recomputing the full attention matrix, so total inference cost becomes overall — the same asymptotic total as an uncached forward pass over the growing sequence, but spread correctly across steps rather than repeated wastefully at each one.
Space complexity. Storing all activations, attention weight matrices, and the KV cache costs for attention matrices (per layer, per head) and for hidden states and the cache, times layers and heads for the attention matrices specifically: .
Correctness argument. Two properties must hold for the model to define a valid, learnable conditional distribution . Autoregressive validity (no label leakage). The chain rule factorization requires that the computation of never depends on . The causal mask enforces this as an invariant: by induction on layer depth, if the input to layer at position depends only on target positions (true trivially for the embedded input, since position 's embedding is under the right-shift), then after masked self-attention — which by construction assigns zero weight to any position — the output at position still depends only on positions . Cross-attention and feed-forward layers act position-wise (cross-attention reads from the encoder, which has no dependence on at all), so they preserve the invariant. Hence at every layer and every position , the representation is a function only of and , and the final softmax at position computes exactly — matching training-time teacher forcing to inference-time autoregressive generation exactly. Full-input visibility for the encoder. Because encoder self-attention is unmasked, , the encoder's representation of position , is influenced by every , not just . This is correct and necessary for encoding: unlike generation, understanding a completed input sentence has no causality constraint, so restricting the encoder would only discard useful context (this is precisely why encoder-only models like BERT can be trained with bidirectional objectives, while decoder-only generative models cannot). Tradeoff. The price of this correctness is the quadratic attention cost above, plus the strict sequential nature of inference — even with KV caching, generation cannot be parallelized across time steps, unlike encoding, because each token's distribution genuinely depends on the sampled identity of all previous tokens.
Worked example
Consider translating the English sentence "the cat sat" into French, target "le chat était assis" (simplified here to "le chat s'assit" for brevity — we'll trace generating "le chat" as the first two tokens). Source tokens: , .
Step 1 — Encoding (done once). The encoder processes all three tokens simultaneously with bidirectional self-attention, producing . Note is influenced by both "the" (its determiner) and "sat" (its verb) — full sentence context, computed in a single pass.
Step 2 — Decoding step 1. Decoder input so far: `[]`. Masked self-attention over a length-1 sequence trivially attends only to `` itself. Cross-attention: the query derived from ``'s representation attends over ; because French typically opens a noun phrase with a determiner, attention weight concentrates on . The output distribution places high probability on "le". Suppose argmax selects "le".
Step 3 — Decoding step 2. Decoder input: `[, le]`. Causal self-attention at the current (second) position attends over `{, le}` only — position 2 cannot see any hypothetical future token. Cross-attention now shifts weight toward , since the model needs the noun following the determiner. Output distribution favors "chat".
Step 4 — Decoding step 3. Decoder input: `[, le, chat]`. Cross-attention shifts weight toward to produce the verb; self-attention at position 3 sees `{, le, chat}` and correctly excludes any not-yet-generated token. This continues until `` is emitted.
| Step | Decoder input (causal-visible) | Cross-attention focus (approx.) | Output token |
|---|---|---|---|
| 1 | `` | "the" | le |
| 2 | `, le` | "cat" | chat |
| 3 | `, le, chat` | "sat" | s'assit |
| 4 | `, le, chat, s'assit` | (sentence-final cue) | `` |
Contrast this with training on this same pair: instead of four sequential calls, the decoder receives `[, le, chat, s'assit]` all at once, and the causal mask ensures position 2's output logits (used to compute the loss against "chat") never had access to "chat" or "s'assit" as inputs, so the parallel computation exactly reproduces what four sequential inference-style steps would have computed — this equivalence is precisely the invariant argued above.
Common pitfalls & traps
| Pitfall | Why it's wrong | Fix |
|---|---|---|
| Forgetting the causal mask in the decoder | Position can see or later, so the model trivially "cheats" during training and fails catastrophically at inference (exposure bias becomes total) | Always add mask above the diagonal before softmax in decoder self-attention |
| Confusing cross-attention with decoder self-attention | Using all from the decoder in the cross-attention sub-layer discards the source sentence entirely | Cross-attention keys/values must come from encoder output , only queries from the decoder |
| Feeding the decoder the raw target (not shifted right) | Without the right-shift, position 's input token literally equals its own label | Prepend `` and shift all targets by one position before embedding |
| Re-encoding the source at every decoding step | Wastes redundant encoder passes; the encoder output does not change across decoding steps | Compute once, reuse it across all decode steps (cache it) |
| Ignoring padding masks in batched training | Attention over `` tokens pollutes real tokens' representations with meaningless content | Add padding masks to both self-attention and cross-attention score matrices |
| Believing inference parallelizes like training | Teacher-forcing parallelism only exists because ground truth is known; at inference each token depends on the sampled previous one | Use KV caching to speed up sequential decoding, not naive batched-parallel decoding |
:::warning[The single most dangerous mistake is omitting or misplacing the causal mask in decoder self-attention. If unmasked, training loss will look deceptively good — the model achieves near-perfect next-token prediction because it can literally see the answer — while inference-time generation, which cannot cheat, collapses into incoherent or repetitive output. This bug is silent: no shape error, no crash, just a model that "trained fine" and generates nonsense, often discovered late in a project.]:::
Pioneers & history
The full encoder-decoder Transformer was introduced by a team at Google Brain and Google Research, building on a decade of work in neural sequence-to-sequence modeling and attention mechanisms that preceded it, including Bahdanau-style additive attention for RNN encoder-decoders and the insight that attention alone, without recurrence, could carry long-range dependencies more directly.
:::physicist[Ashish Vaswani|b. 1980s (contemporary)|Lead author of "Attention Is All You Need" (2017), which proposed replacing recurrence entirely with self-attention and cross-attention, establishing the full encoder-decoder Transformer as the architecture underlying nearly all subsequent large-scale sequence models.]:::
Origins · 1 minhow this was discovered
Where this matters
The full encoder-decoder Transformer underlies production machine translation systems, including large-scale services that translate between dozens of languages in real time. It is the backbone of abstractive summarization systems, where an encoder digests a long document and a decoder produces a condensed summary while cross-attending to the source. Speech recognition and speech synthesis pipelines use the same pattern, with the encoder consuming audio features and the decoder producing text (or vice versa). Multimodal systems that generate image captions or answer questions about images reuse the identical cross-attention bridge, substituting a vision encoder for a text encoder while keeping the decoder unchanged. The text-to-text framework popularized by models like T5 casts nearly every NLP task — classification, translation, summarization, question answering — as a single encoder-decoder problem, directly exploiting this architecture's generality. Understanding this full pipeline is also the necessary foundation for the Pretraining-Finetuning Paradigm, since decisions about which half of the architecture to keep, and what objective to pretrain it with, define the major families of modern pretrained language models.
Ask the tutor: How would the architecture change if you needed the decoder to attend to two different encoders at once, such as one for text and one for an image?
Why does the full Transformer need both an encoder and a decoder if the decoder alone could generate text?
A decoder-only model can generate fluent text, but it has no dedicated mechanism for conditioning on a full, separately-encoded input sequence with bidirectional context. The encoder builds a representation where every source token can see every other source token, including ones that come later, which is important for accurate understanding: knowing a sentence's ending can clarify its beginning. Cross-attention then gives the decoder a clean, direct channel to that entire bidirectional representation at every generation step. Decoder-only models instead must fold the input into the same causal, left-to-right stream as the output, which works well for many tasks but loses the encoder's bidirectional advantage for the input specifically.
Is cross-attention just the same computation as self-attention with different inputs?
Mechanically, yes — it uses the identical scaled dot-product attention formula. The distinction is purely about the source of queries, keys, and values. In self-attention, all three come from the same sequence (encoder-to-encoder or decoder-to-decoder). In cross-attention, queries come from the decoder while keys and values come from the encoder's output. This means cross-attention has no causal masking concern on the source side, since the entire encoder output is always fully available and static across the whole decoding process, unlike the growing, partially-generated decoder sequence.
Why is decoder inference sequential even though decoder training is parallel?
During training, the true target sequence is already known, so teacher forcing can feed the whole shifted sequence in one pass and rely on the causal mask to prevent leakage — no actual sequential dependency in the computation exists, just a masking constraint. During inference, no ground truth exists yet: token must be sampled or chosen by argmax before token can even be computed, since it becomes part of token 's input. This is a genuine data dependency, not just a masking convention, so it cannot be parallelized away, though key-value caching removes redundant recomputation.
What happens if you use the wrong mask, such as masking cross-attention causally?
Causally masking cross-attention would incorrectly prevent later decoder positions from attending to later source positions, even though the source is fully available and has no temporal ordering constraint relative to the target. This would degrade translation quality especially for language pairs with different word orders, where a target word early in the sentence may need to attend to a source word late in the sentence (for example, verb-final languages translating into verb-medial ones). Cross-attention should never be masked based on target position; the only masking it might need is a padding mask to ignore padded source tokens in a batch.
How does the encoder-decoder architecture relate to encoder-only models like BERT and decoder-only models like GPT?
BERT keeps only the encoder half, trained with a bidirectional masked-language-modeling objective, since it targets representation learning rather than generation. GPT keeps only the decoder half, but removes the cross-attention sub-layer entirely since there is no separate source sequence to attend to — it self-attends causally over its own growing context. The original full encoder-decoder architecture is thus best understood as the common ancestor from which both major pretraining families specialized, each keeping the stack suited to their objective and discarding the other.
Does the quadratic attention cost make the full Transformer impractical for long documents?
It is a genuine limitation: both the encoder self-attention cost and the decoder self-attention cost grow quadratically with sequence length, becoming expensive for documents of many thousands of tokens. In practice this is mitigated by truncating or chunking long inputs, by sparse or linear-attention variants that approximate full attention at lower cost, and by the fact that cross-attention itself is only , not quadratic in a single sequence — the summarization or translation output is often much shorter than the source, keeping the term small even when is large.
Why does the decoder need its own self-attention sub-layer in addition to cross-attention?
Cross-attention alone lets the decoder consult the source sentence, but says nothing about the relationships among the target tokens generated so far. Decoder self-attention lets the model track what it has already said — subject-verb agreement, pronoun consistency, avoiding repeated words — independent of the source. The two sub-layers serve complementary roles: masked self-attention enforces target-side coherence and the chain-rule factorization, while cross-attention supplies source-side grounding, and both are necessary for fluent, faithful generation.