Build your own GPT-2
A single attention head·10 min

Weighted sum of values

0 / 1
# grade this stage (from your course directory)
npx theinference test --stage weighted-sum --watch

Last step: combine the value vectors using the attention weights. Four steps — score → mask → softmax → weighted sum — and you have a complete attention head. This single function is the literal engine of GPT-2: Chapter 6 runs it 12 times per block, 144 times across the whole model.

Output as a weighted sum of values
out[i] = Σ_j weights[i][j] · v[j]
The full head, end to end
q,k,v [T,d] ─▶ scores[T,T] ─▶ masked[T,T] ─▶ weights[T,T] ─▶ Σⱼ wᵢⱼ·v[j] ─▶ out[T,d]

What to build

Your task

Implement runAttention

Implement runAttention(q, k, v) (each [T, d]) returning the attention output [T, d]. You can compose the three functions you just wrote — runScores → runCausalMask → runSoftmaxRows — then take the weighted sum of v, or compute it directly.

tests/adapters.ts
export function runAttention(q: number[][], k: number[][], v: number[][]): number[][] {
  // q, k, v: [T, d]  ->  [T, d]
}
Row i only sums over j = 0..i

The future positions are masked to ~0 weight, so they contribute nothing — you can skip them entirely (the reference does: for j in 0..=i). Either way is fine within tolerance.

How it's graded

Your output tensor ([T, d]) is compared to the reference with allclose, atol 1e-5. Inputs are randomized per run — you can't hardcode the answer.