Your training set is only as clean as its worst record
The last lesson gave you the customs-officer picture: model output is foreign data, and the schema inspects it at the border. Now apply it to the highest-stakes case — records headed into a dataset. An extractor (an LLM, a scraper, a labeling script) emits thousands of dicts, and every one of them is about to become training data, eval data, or a row someone bets a decision on.
Here's the asymmetry that makes this worth a whole lesson: a bad
record doesn't crash anything. It just sits there. A missing label
becomes a silent KeyError three scripts later; a confidence of
87.0 (the model felt like returning a percentage that day) quietly
wrecks every average computed over the column. Garbage in a dataset
doesn't fail loudly — it fails statistically, weeks later, as a
model that's mysteriously worse than the last one.
Three checks, in escalating order
Every record crosses the boundary through the same gauntlet:
- Required fields. Does the record have every key the schema
demands? The one-liner is the workhorse of this whole chapter:
missing = [f for f in REQUIRED if f not in record]. Empty list means present and accounted for. - Types. Is
confidenceactually a number, or the string"0.97"? Extractors emit stringly-typed numbers constantly, and"0.97" > 0.5is aTypeErrorwaiting for whoever aggregates the column.isinstance(value, float)at the border, not deep in analysis code. - Ranges. A confidence of
-0.2has the right type and the wrong reality. Range checks encode what the value means: confidences live in0.0-1.0, labels come from a fixed set, token counts are non-negative.
Reject or quarantine?
Failing a check is half a decision. The other half is where the record goes:
- Reject — the record is structurally broken (missing fields) and there's nothing to salvage. Drop it, and count it.
- Quarantine — the record is intact but suspicious (out-of-range
value, unknown label). Park it in a separate pile a human can
review. That
87.0confidence is probably0.87with a story; quarantine keeps the evidence instead of shredding it.
The alternative to all this is trusting the extractor because it behaved during the demo. It did — on twelve documents you picked. The boundary check is for document 4,000, the scanned one with the coffee stain, where the model improvises. Validate at the boundary and bad records never enter; trust the extractor and you get to find them by archaeology.
The editor runs one record through all three checks. Run it, then
sabotage the record — delete the "label" key, set confidence to
-0.2 — and watch it land in a different bucket each time. Later in
this lesson the schema grows one more demand: not just shaped
right, but provable — every claim carrying a receipt saying where
it came from.