Build your own semantic search
The search CLI (the capstone)·20 min

The search CLI

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

The payoff. Build search as a CLI: take a query, retrieve the top-k, and print real documents with their scores. This is the artifact you screenshot — the whole stack, from a·b to a ranked answer, behind one command.

What to build

Your task

Build the search command

Wire your_program.sh search <packDir> <queryIndex> --k <k> (handled in cli.ts): load the pack, take query queryIndex from pack.queries, run scoreAll + topK over the corpus, and print one JSON array of hits — each { rank, doc_id, score, title } (rank 1-based, score to 6 dp). doc_id and title come from pack.docs[index].

(The CLI dispatch is provided; you only need your scoreAll/topK from earlier chapters to be correct.)

your_program.sh
./your_program.sh search fixtures/pack 0 --k 5
Shape of the printed result
[
  { "rank": 1, "doc_id": "10185", "score": 0.939813, "title": "..." },
  { "rank": 2, "doc_id": "10009", "score": 0.30685,  "title": "..." }
]
How it's graded

process — for a fixed query the harness deep-compares your stdout JSON to expected.json: doc_ids, ranks, and titles exact, scores within atol=1e-3. The fixture query is chosen so its top-5 is well-separated (the rank-5 vs rank-6 gap is comfortably above the tolerance), so ids and ranks are stable and only the printed score rides the tolerance.

Read a real result

Rank 1 should be the document whose vector the query was built nearest to — the "gold" doc the qrels mark relevant. On a real corpus this is the abstract that genuinely answers the question, in words that may not even appear in the query. That's semantic search working.