[01-transformer-block/06-assemble-full-block] built ONE reusable Transformer block. Nothing about that block's internal STRUCTURE changes across "BERT," "GPT," and "the original 2017 Transformer" (translation-style encoder-decoder models), the three big architectural families real systems fall into. What changes is entirely WHICH POSITIONS self-attention is allowed to see, and, for the encoder-decoder family, whether a SECOND kind of attention gets added at all.
An encoder (BERT-style) lets every position attend to every other position, in both directions: useful for building a representation of a COMPLETE, already-fully-visible input (classification, understanding tasks), where there's no reason to hide any part of the input from any other part. A decoder (GPT-style) restricts self-attention with [04-seq-modeling/04-attention/02-causal-mask]'s causal mask: essential for autoregressive generation, where a model must never "cheat" by looking at tokens it hasn't generated yet. An encoder-decoder (translation-style) uses BOTH: an encoder processes the full source sequence bidirectionally, and a decoder generates the target sequence causally, while ALSO attending to the encoder's output via a second, distinct attention call, "cross-attention," where the query comes from the decoder but the key/value come from the encoder.
Implement encoder_block_forward (a thin wrapper around [06-assemble-full-block]'s block, no mask), decoder_block_forward (the same block, with [02-causal-mask]'s mask), and encoder_decoder_cross_attention (a direct call to [05-mha-concat-output-projection]'s multi_head_attention, with query from the decoder and key/value both from the encoder's output).
encoder_block_forward passes mask=None to the underlying Transformer block: full bidirectional attention.decoder_block_forward builds a causal mask sized to x's own sequence length and passes it through.encoder_decoder_cross_attention's query is decoder_hidden; its key AND value are both encoder_output. These may have DIFFERENT sequence lengths (the source and target sentences in translation are rarely the same length).encoder_block_forward is exactly transformer_block_forward(x, num_heads, mask=None, **block_params). decoder_block_forward is the same call with mask=build_causal_mask(x.shape[-2]) instead.
output, _ = multi_head_attention(decoder_hidden, encoder_output, encoder_output, num_heads, weight_o, bias_o). Notice query and key/value come from genuinely DIFFERENT tensors here, unlike every self-attention call used so far in this curriculum, where all three were the same tensor.
No results yet
Run your code to check it against the examples, or submit to run every test.