Unit 08.02: Extraction with a schema you can check
Extraction is where a model's output becomes a record in your system.
A schema with bounds, not just types
Four extractions against a schema with a pattern and a positivity constraint.
The code validates each.
from pydantic import BaseModel, Field, ValidationError
from typing import Optional
class Invoice(BaseModel):
invoice_id: str = Field(pattern=r"^INV-\d+$")
amount: float = Field(gt=0)
currency: str = Field(pattern=r"^[A-Z]{3}$")
due_date: Optional[str] = None
EXTRACTIONS = [
{"invoice_id": "INV-1187", "amount": 240.0, "currency": "USD"},
{"invoice_id": "1187", "amount": 240.0, "currency": "USD"},
{"invoice_id": "INV-1187", "amount": "two hundred", "currency": "USD"},
{"invoice_id": "INV-1187", "amount": -240.0, "currency": "USD"},
]
for raw in EXTRACTIONS:
try:
print(f"OK {Invoice(**raw)}")
except ValidationError as exc:
e = exc.errors()[0]
print(f"FAIL {str(raw)[:52]:54} {e['loc'][0]}: {e['type']}")
# Extraction is where a model's output becomes a record in your system. A
# negative amount and a malformed id both parse as JSON, and both would be
# written to a database by any code that only checked the parse.
The negative amount and the malformed id both parse as JSON and would be written to a database by any code that checked only the parse. A negative invoice amount is not a data error to be cleaned later - it is a record that will be reconciled against something real.
gt=0 and the id pattern are the two lines that turn a plausible dict into a usable one.
The mistake this prevents
The mistake is extracting into a dict and inserting it. The insert succeeds, the row is wrong, and the error surfaces weeks later in a report nobody can trace back to a model call.
Takeaway
Validate extracted records with bounds and patterns before they become rows. A parse tells you the shape; only the schema tells you the values are usable.
