The additive causal mask
Easy8 min10 hidden tests
A code-completion model predicts each token from the tokens before it, so attention must never look ahead. Write causal_mask(n, past=0) that returns the additive mask the model adds to its attention scores before the softmax: 0.0 where a query may look at a key and -inf where it may not. The n queries are the newest tokens, and past tokens already sit in a cache before them, so the keys are all past + n tokens. Query i is token past + i and may see keys 0 through past + i, itself included. For n = 3 and no past, the rows are [0, -inf, -inf], [0, 0, -inf] and [0, 0, 0].
Tap a row: what can that token see?
shape (n, past + n) = (3, 3)Row 2 is the token w, at position 2. It attends to keys 0 to 2: y = w. Nothing comes after it, so the whole row is 0.
Row 2, token w, sees 3 of 3 keys.
Examples
Each row sees one more token than the row above
causal_mask(3)
returns [[0, -inf, -inf], [0, 0, -inf], [0, 0, 0]]
Two new tokens after three cached ones
causal_mask(2, 3)
returns [[0, 0, 0, 0, -inf], [0, 0, 0, 0, 0]]
Requirements
nis an integer of 1 or more andpastan integer of 0 or more.- Return a float NumPy array of shape (n, past + n).
- Entry (i, j) is 0.0 when
j <= past + iand-inf(-np.inf) whenj > past + i.
The idea behind it
A decoder-only transformer such as GPT is trained to predict every next token at once. To keep that honest, each position may attend only to itself and earlier positions. The usual way is an additive mask: add 0 to the scores the query may use and -inf to the rest, then take the softmax. Since exp(-inf) = 0, blocked keys get a weight of exactly 0, and the other weights still sum to 1. For one sequence the mask is square and upper triangular. With a key-value cache (stored keys and values of earlier tokens), new queries arrive after past cached tokens, so the mask has past + n columns and the boundary shifts right by past. Implementations that work in half precision often use a large negative number in place of -inf, but the idea is the same.
Worked solution
Give it a real try first. Then read the solution and why each line is there.