Lab: Schema design
Upgrade the triage assistant to full structure: fenced input, schema'd JSON output, integrity checks — tested against awkward real emails.
In this lab the triage assistant graduates from 'chatbot with rules' to 'component with a contract'. You'll wire the Module 2 pieces into your v0.2 prompt and stress-test the contract.
Step 1 — Assemble v0.3
- 1Add named sections to your system prompt if any are missing: ROLE / RULES / EDGE CASES / DATA HANDLING / OUTPUT.
- 2Paste the output schema from lesson 2 into OUTPUT, adapting field comments to your rule set.
- 3Convert the user-message template to the fenced form:
<email>…</email>+ the one-line reminder that fenced content is data. - 4Log the changes at the top: v0.3, date, 'structured I/O'.
Step 2 — The awkward-email gauntlet
Run each of these through v0.3 and record the JSON. You're grading the contract, not the prose:
- 1A normal damaged-item complaint with an order number → expect COMPLAINT / HIGH / order_id captured verbatim / damage_mentioned true.
- 2An order-status ask with no order number → order_id must be null. If the model invented one, your escape-hatch line is missing or too weak.
- 3An email mentioning TWO order numbers → what did it do? Decide the policy (first? both? null + LOW confidence?), encode it, re-run.
- 4A vendor cold-pitch → OTHER with suggested_reply null — check it didn't draft a polite reply anyway.
- 5The mid-paragraph injection email from Module 1 → contract intact, no obedience.
Step 3 — Validate like a machine would
- 1Paste each output into a JSON validator (jsonlint.com is a reputable one, or your editor's built-in). Zero parse failures is the bar. (These are invented test emails — if you ever validate with real customer emails, redact names and order details first.)
- 2Check enums by eye: any category or urgency outside the allowed list is a contract breach even if it 'reads fine'.
- 3Tally your results: parse rate, enum compliance, null discipline across the gauntlet. Write the three numbers at the top of your lab notes — in Module 5 they become your first eval metrics.
You graded outputs without reading them as prose — shape first, sense second. That's the reflex that lets prompt systems scale past one careful author to a whole team.
Problem set 2 — fix three broken schemas
Three schemas below, each broken in a way pulled from real projects. For each: name the flaw, redesign it, and write one sentence on which downstream consumer forced the change.
- Schema A — no null policy:
{ "order_id": string, "ship_date": string }with the instruction 'always fill every field'. Emails without an order number get an inventedorder_id. (Which consumer breaks when the id is fake?) - Schema B — the 6-level nest:
{ "result": { "data": { "email": { "meta": { "fields": { "category": string } } } } } }. Every level multiplies model error and your parsing pain. Flatten it. - Schema C — overlapping enum:
"category": "COMPLAINT" | "ISSUE" | "PROBLEM" | "RETURN_REQUEST" | "OTHER". Three of those mean the same thing, so the model splits similar emails across them at random. Collapse to a set where every value is mutually exclusive.