Build your own semantic search
Setup & orientation·8 min

Load the vectors

0 / 1
# grade this stage (from your course directory)
npx theinference test --stage load-the-vectors --watch

Before any math, prove you can read the corpus off disk and that the vectors are what we said they are. You'll load corpus_emb.f32, report its shape, and report the L2 norm of document 0 — which should be ≈ 1.0, because the embeddings are pre-normalized (a fact the next chapters lean on hard).

What to build

Your task

Report the corpus shape + doc-0 norm

When run as ./your_program.sh load-corpus <packDir>, print a single JSON object:

  • shape — [numDocs, dim] of the corpus matrix, i.e. [200, 64].
  • doc0_norm — the L2 norm of the first document vector (rounded to 6 dp).

The provided loadPack(packDir) gives you pack.corpus (a flat Float32Array), pack.numDocs, and pack.dim. Slice row 0 with pack.corpus.subarray(0, pack.dim) and take its l2norm (you'll write l2norm in Chapter 2 — for now Math.sqrt(Σ x²) inline is fine).

json
{
  "shape": [200, 64],
  "doc0_norm": 1.0
}
How it's graded

process — your stdout JSON is deep-compared to the reference within atol=1e-3. The shape must match exactly and doc0_norm must be within 1e-3 of the reference (≈ 1.0). The pack path is passed by the grader — read it from argv, don't hardcode it.

Pre-normalized is the whole point

Doc 0's norm comes out ≈ 1.0 because a real embedding model (and our synthetic generator) L2-normalizes every output vector. Keep that fact in your pocket: in Chapter 2 it turns cosine similarity into a plain dot product, for free.

Row-major, no reshaping needed

The blob is numDocs × dim row-major: bytes [0 .. dim) are doc 0, [dim .. 2·dim) are doc 1, and so on. loadF32 already returns the flat Float32Array; you index row i as corpus.subarray(i*dim, (i+1)*dim). There is no 2-D array to build.