Skip to content

← Attention Variants step 5 of 14

Hard Framework

Causal Attention with Framework Operations

Compute one head of causal attention using framework operations. Every query may use its own position and earlier positions, but not later ones. This version uses unbatched matrices and negative infinity for masked scores.

Build the scores and mask

Calculate scores = (Q @ K.T) / sqrt(d_k). Row i contains the scores for query i, and column j refers to key j.

Create a Boolean mask for the strict upper triangle: True where j > i. Here, True means blocked. Keep the diagonal unmasked so a query can use its own key. Replace blocked scores with negative infinity before applying softmax across the last axis. Then multiply the weights by V.

For Q = K = [[1], [2]] and V = [[10], [20]], the masked scores are:

[[1, -inf],
 [2,    4]]

The first row has weights [1, 0] and returns 10. The second row has weights approximately [0.119203, 0.880797] and returns 18.807971.

Use framework operations

In PyTorch, use torch.triu(..., diagonal=1), masked_fill and torch.softmax(..., dim=-1). Build the Boolean mask on the scores' device, for example from torch.ones_like(scores, dtype=torch.bool).

In JAX, use jnp.triu(..., k=1), jnp.where and jax.nn.softmax(..., axis=-1). Softmax gives blocked positions zero weight when each row has finite allowed scores. The diagonal ensures an allowed position here; do not extend this rule blindly to rows blocked by padding.

This implementation constructs a dense square score matrix. Masking changes which values contribute, but does not by itself avoid the quadratic score storage or make this a sparse attention algorithm.

Inputs

Implement causal_attention(Q, K, V) following these steps.

  • Q and K: floating-point tensors of shape (seq_len, d_k).
  • V: a floating-point tensor of shape (seq_len, d_v).

Dimensions are positive, and the inputs produce finite unmasked scores. Use compatible dtypes and, in PyTorch, the same device. The value width may differ from the query/key width. No batching, dropout or padding mask is needed.

Output

Return the weighted values as a tensor of shape (seq_len, d_v), leaving inputs unchanged. Return values, not scores or attention weights.

The grid below shows permitted query/key pairs rather than numerical weights. Select Causal to see the pattern used here.

Loading visualization…