Train your own embedding model
Backprop, by hand·35 min

Gradient into the embeddings

0 / 1
# grade this stage (from your course directory)
npx theinference test --stage grad-into-embeddings --watch

Propagate the upstream dScores back through the similarity matrix S = Q · Pᵀ to get gradients on the embeddings. This is the standard matmul backward — one line each for dQ and dP.

matmul backward for S = Q · Pᵀ
dQ[i] = Σ_j dScores[i][j] · P[j]        # dQ = dScores · P
dP[j] = Σ_i dScores[i][j] · Q[i]        # dP = dScoresᵀ · Q

What to build

Your task

Implement the sim-matrix backward

Implement runSimBackwardDQ(dScores, Q, P): given the upstream [B, B] dScores and the two embedding batches, return dQ — the [B, 32] gradient w.r.t. the query embeddings. (simBackward also returns dP; the grader checks dQ here.)

tests/adapters.ts
export function runSimBackwardDQ(
  dScores: number[][], Q: number[][], P: number[][],
): number[][] {
  // dQ[i] = Σ_j dScores[i][j] · P[j]
}
How it's graded

Adapter mode: dQ is compared to the reference with allclose, atol 1e-5, rtol 1e-4. The reference is itself cross-checked against central finite differences (ε = 1e-4) — so the fixture is a finite-diff-validated oracle, not a hand-wave.

L2-norm's gradient comes next

This step stops at the embeddings. The next step pushes dQ/dP through L2-normalize and the MLP and into the table — and the L2-norm Jacobian is the part people get wrong, so we isolate it.