AI Engineering Programme Start here Weeks Playground Open Codespace
‹ All weeks

Week 3

Grounding and evaluation, of answers and of paths

5 of 18 checks pass · citations 0% valid (fake model) ›route startOn GitHub

Do this next

Build this week's exercise, then run the gate.

make check WEEK=3

This week at a glance

SessionSession 3: Observation, 60 min
BuildPOST /ask with its two gates and citations; your own hundred questions; a judge you build and check against thirty labels; twenty trajectory tasks.
Filesapp/api/ask.py, app/eval/judge.py, eval/my-test-set.jsonl, eval/trajectories.jsonl
Measuremake evidence WEEK=3 on a real model, into evidence/week-3.json
Recorddecisions/week-3.md from the evidence, ai-use/week-3.yml, reflections/week-3.md
GuidesWorked examples B to E: evaluation · Glossary

checks fail 5 of 18 checks pass

The 13 that do not
  • abstains below threshold without calling the modeltest_week3.py
  • abstains when the model says not groundedtest_week3.py
  • answers with citations that resolvetest_week3.py
  • citation numbers outside the context are droppedtest_week3.py
  • eval gate passes on ci thresholdstest_week3.py
  • judge labels are thirty answers you labelledtest_week3.py
  • my test set has 100 questions in the required compositiontest_week3.py
  • provider failure is not an abstentiontest_week3.py
  • the judge grades faithfulness from the passagestest_week3.py
  • the judge prompt is writtentest_week3.py
  • trajectory set has twenty well formed taskstest_week3.py
  • unanswerable question is declinedtest_week3.py
  • valid citations map to real chunkstest_week3.py

Red is the normal state of a week you have not built yet. Each name is a test in the file beside it.

The 5 that do
  • eval gate blocks when a threshold is not mettest_week3.py
  • my test set is written from what a user would asktest_week3.py
  • the threshold curve runs and declines more as it risestest_week3.py
  • the trajectory command runstest_week3.py
  • trajectory scoring reads the pathtest_week3.py

Hidden evaluation

Not shown on the public page. The programme runs it on each week you merge; your mentor sees the totals on the brief and brings them to you.

Decision and AI use

Written last: make evidence WEEK=3, then decisions/week-3.md and ai-use/week-3.yml.

Measuredthis week

Evaluation gate

metricvaluethresholdverdict
abstain_rate_unanswerable0.000.70FAIL
answer_rate_answerable0.000.50FAIL
hit_rate0.000.60FAIL
citation_validity0.000.80FAIL
total_cost_usd0.0000

Dothe week

The exercise is in your repository, where you can run it:

code weeks/3/README.md
make next

Read it on GitHub · what the gate verifies · the tests

Whythis week is here

You arrived with

Hybrid search, keyword and meaning together, restricted to the customer's version and called by the agent as a tool, with every choice in it made by a number.

This week leaves

Answers that cite their source and decline when the evidence is thin, your own test set, a judge you checked against labels, and the agent's path measured as well as its answer.

Which is why the next week can

Week 4 lets the agent act. You cannot let it act until you can tell whether a change made it worse.

Readthe concept

A system that always answers is worse than one that sometimes declines. And nothing ships without a number that says how often it does each.

Read this once (about 20 minutes). Write the sentence in your own words in reflections/week-3.md, Q1, before you touch code.

Grounding: answer from the passages or not at all

A model will answer any question you put to it. That is the problem. Grounding is the set of disciplines that make it answer only from what you gave it:

flowchart TD
  Q[question] --> S[search top k]
  S --> G1{"top score ≥
RELEVANCE_THRESHOLD?"} G1 -- no --> A1["abstain
reason: threshold
cost: $0, no model call"] G1 -- yes --> M["model reads numbered passages
returns answer, citations, grounded"] M --> G2{"grounded and
a valid citation?"} G2 -- no --> A2["abstain
reason: passages do not contain the answer
cost: one call"] G2 -- yes --> O["answer + citations
each #91;n#93; mapped to a real chunk"] style A1 fill:#eef7ef,stroke:#2e7d4f style A2 fill:#eef7ef,stroke:#2e7d4f

Evaluation: the thing that separates builders from enthusiasts

Interviewers ask two questions: how do you know it works, and what did it do for the business. Evaluation is the answer to the first.

Four numbers, one grid. Each cell is a different thing going wrong.

answered declined
answerable hit rate: did it contain the fact? citation validity: did it cite the right file? answer rate drops → look at retrieval first
unanswerable abstention rate drops → look at the prompt and gate 2 correct

And the gate in CI, which is what "we have evals" means:

flowchart LR
  PR[pull request] --> CK[make check WEEK=3]
  CK --> EV["scripts/eval.py
golden.jsonl through /ask"] EV --> TH{"every metric ≥
thresholds-ci.json?"} TH -- yes --> OK[merge allowed] TH -- no --> NO["merge blocked
the table says which metric"] style NO fill:#fbeeed,stroke:#b3261e

A test you cannot see

Your own test set has a weakness you cannot remove: you wrote it, so your system and your questions share your blind spots. From this week the programme runs about 150 questions and 20 agent tasks you never see, written for your product, on every pull request, on one reference model. You see the totals. If your own score is well above the hidden one, your questions are easier than real users' (worked example E). The gap is the finding; chasing the hidden questions is not the fix, rewriting your own is.

Evaluating a path, not just an answer

From next week the system acts: it looks a customer up, searches, drafts, escalates. An answer can be right for the wrong reasons: it guessed the version instead of looking it up, it searched four times when once would do, or it reached for a refund nobody asked for. A trajectory is the path, and four numbers describe it: the right tool (first, and in order), the steps it took, what it cost, and whether anything that needs a person's approval ran without one. You write twenty tasks this week; the agent you build next week is measured on them, and on twenty hidden ones.

What this looks like in the service

Idea Where it lives What you do this week
Threshold and decline app/api/ask.py, RELEVANCE_THRESHOLD Build the two gates
Citations AskOut.citations Map the model's [n] to real chunk ids and files
Your test set eval/my-test-set.jsonl Write 100 questions from what users ask
Metrics and gate scripts/eval.py, eval/thresholds.json Run it, read it, make CI block on it
Judge app/eval/judge.py, scripts/judge_agreement.py Build it, label 30 answers, measure agreement
Threshold scripts/threshold_curve.py Read the threshold off a measured curve
Trajectories eval/trajectories.jsonl, app/eval/trajectory.py Write 20 tasks; the agent meets them in week 4

What you should be able to say by Friday

Read more

Checked September 2026.

Optionalself-test

Answers are kept in this browser only, under hub.quiz in local storage. They are never sent anywhere: not to the repository, not to the progress export, not to your mentor, and they have no effect on your route. Clearing your browser data clears them. The explanations are the point, not the score.

‹ Week 2Week 4 ›