Step 3: Enrich
This ordering is the whole efficiency argument. “Peanut satay skewers” contains the word peanut, and satay. No model needs to be consulted about that. On a real catalog the rules routinely settle most of it, and your model bill is for the remainder.
The rules match whole words, with case and accents set aside: creme in your contract matches “Crème brûlée” on the menu. If the contract reads a PDF, the lines of it about this record go to the rules and the model too, marked with their file and page.
For what is left, the model is asked one record at a time, constrained to your allowed values, and told plainly that abstaining beats guessing. Here is how our four rows come out:
Tomato soup dairy rule "cream" → dairy Peanut satay skewers peanut rule "peanut" → peanut, "satay" → peanut Garden salad (none) model confidence 0.91, nothing indicates an allergen Chef's tart — abstain the record does not say what is in it
Three settled, one refused. The tart is not a failure: the model was asked what is in a dish whose description is “Ask your server”, and correctly declined to invent an answer. It gets a receipt too — receipts are written for refusals, not just for stored values, and that is the half people find most useful later.
{
"method": "rule",
"confidence": 1,
"contract_version": 3,
"decided_by": null
}The method on a receipt is one of rule, model, rule+model, unchanged, abstain, low_confidence, ratchet_blocked, human or flagged. abstain, low_confidence and ratchet_blocked are the run telling you, in writing, why it did not store something; flagged is a value stored while the model was unsure, on a field set to flag, still waiting for you.
A receipt also shows what a value was decided from. It quotes the record's own text, and, where the contract reads a PDF, the line it used with the file's name and page, linked to open the PDF at that page. A word your contract excludes (cocoa butter for dairy) is noted where it held a rule back.