models · intermediate · 30 min

Get data back, not prose

Turn messy customer emails into validated records your code can trust.

HANDS-ON LAB · YOU RUN IT ON YOUR MACHINE · 4 STEPS
  1. Step 1 of 4

    Write ten short customer emails about parcels: lost, damaged, late

    This is Parcel Desk, the small courier the rest of the course works for. Its customers email in claims for refunds.

    Run this to check

    ls samples | wc -l

    You pass when

    Ten files. Make two of them awkward: one with no parcel number, one with two amounts.

    Files you write

    • samples/
  2. Step 2 of 4

    Define a Claim: parcel id, reason (lost, damaged or late), amount, currency

    Run this to check

    uv run --with pydantic python -c "from extract import Claim; print(Claim.model_json_schema()['required'])"

    You pass when

    The required fields print. Reason only accepts the three values.

    Files you write

    • extract.py
  3. Step 3 of 4

    Ask the model for JSON in that shape and validate it

    Run this to check

    uv run --with openai --with pydantic extract.py samples/

    You pass when

    Ten lines of valid JSON, one per email. The email with no parcel number has a null id, not an invented one.

    Files you write

    • extract.py
  4. Step 4 of 4

    On a validation error, send the error back to the model once, then give up loudly

    Run this to check

    uv run --with openai --with pydantic extract.py samples/; echo "exit $?"

    You pass when

    Exit 0 when all ten validate. Break one on purpose (ask for a fourth reason value) and the exit code is not 0.

    Files you write

    • extract.py
No transcript here on purpose. This page does not show terminal output, because model answers differ from run to run. Each step says what a pass looks like; your own terminal is the proof.