The cosine-similarity matrix
# grade this stage (from your course directory)
npx theinference test --stage cosine-matrix --watchBuild the B×B similarity matrix S where S[i][j] = cosine(query_i, positive_j). Because both batches are already L2-normalized (you did that in encode), cosine is just the dot product — so the whole matrix is S = Q · Pᵀ.
Q : [B × 32] (query embeddings, ‖row‖ = 1)
P : [B × 32] (positive embeddings, ‖row‖ = 1)
S[i][j] = Σ_k Q[i][k] · P[j][k] → S : [B × B]
What to build
Implement the similarity matrix
Implement runSimMatrix(Q, P): return the [B, B] matrix of dot products between every query row and every positive row. Since the rows are unit-norm, this dot product is the cosine — no extra normalization here.
export function runSimMatrix(Q: number[][], P: number[][]): number[][] {
// S[i][j] = Σ_k Q[i][k] · P[j][k]
}
Adapter mode: your [B, B] matrix is compared to the reference with allclose, atol 1e-5, rtol 1e-4. The fixture ships two fixed, already-normalized batches.
S[i][j] pairs query i with positive j — you dot row i of Q against row j of P. The diagonal S[i][i] is each query against its own positive; that is the entry the loss wants to be largest.