Extraction looks like one task and is really three: find candidate text, decide what each candidate is, and normalize the result. The model is good at the middle step. The other two belong in code, because a value the model writes can be invented and a calculation the model performs can be wrong.
The strongest designs in this space share a rule: the model chooses, and code owns the string. That single constraint prevents a large class of hallucinations and makes the output auditable.
Dates: decompose, then compute
The date extraction cookbook asks seven Choice questions about a date's shape and parts: mode (absolute, relative, none), month, day, year from 1900 to 2050, day anchor, weekday, and week offset. Code reads only the pieces the mode calls for, resolves them against a pinned TODAY, and infers a missing year. The model does no arithmetic.
Five of six examples were auto-accepted. The instructive failure was a form with no kickoff date: it returned none at 0.46 confidence with a note that the absolute date was incomplete, below the 0.60 review gate. That is the correct outcome. A missing date should not be resolved into a plausible one.
Two conventions have to be written down because phrases like "next Thursday" are ambiguous. The cookbook fixes bare weekdays to mean the next occurrence on or after today, and "next" to mean the following calendar week. Anything under 0.60 goes to a person. The year question also has escapes: none means the text states no year and code fills it in, while out_of_range means a year is stated but falls outside the list and code flags it rather than guessing. This is the dates-as-text problem handled structurally.
Fields: offer spans, copy the choice
The pre-parsed value extraction cookbook builds candidate lists with regexes for emails, phone numbers, and currency amounts. find() over-finds, dedupes, and returns spans in document order. pick() then offers those spans to a Choice question plus a none hatch. The returned value is a verbatim copy of one match, so it cannot be invented.
On the receipt example, the correct email was picked at 0.98, a cell number was normalized in code to +14155550177, and an invoice total was read as $1,315.50 with amounts parsed to Decimal. A $50.00 courtesy credit was flagged at P(credit) 0.99, which is the kind of distinction a regex cannot make and a model should. The caveat is a hard limit: Choice caps at 255 options, and candidates without a regex (names, for example) must come from a roster, NER, or an LLM. This is pre-parsed value extraction as a pattern: the model never sees the document, only the options.
Structure recovery is extraction too
The structure recovery cookbook rebuilds Markdown from unformatted text without asking a model to rewrite anything. Pass one sends 16 Noul line-pair questions to decide whether a line picks up mid-sentence. Pass two classifies the resulting blocks and their companions. On a 28-line memo that was 62 questions in the second pass, 10,211 tokens, 0.8 seconds, and $0.0015.
Join cutoffs of 0.2 after dangling lines and 0.5 after terminal punctuation healed 11 line breaks. Asking whether a line picks up mid-sentence kept the document at 17 blocks rather than collapsing it to 12. Every character of the output comes from the input, and every judgment arrives with a probability. The caveat is that stitching and typing are separate judgment layers, so a bad stitch can produce a clean-looking document with the wrong structure. Keep the two passes separately testable.
Entity resolution: a third outcome is the point
The entity alignment cookbook matches 450 candidate beer pairs from two catalogues. It uses one three-level Score per pair: different product, related but possibly not the same, or same product. The middle level is not a hedge; it is the recognition that merging two entities inappropriately is more expensive than missing a match. Every fact about either entity then describes the merged one, and undo means reconstructing which fact came from where.
Of the 450 pairs, 40 asserted sameAs (8.9%), 50 went to a curator (11.1%), and 360 stayed unlinked. Three additional Nouls about name, brewery, and style ride along to localize disagreements, while ABV comparisons stay in arithmetic. The caveat is that a rounded three-level score is a routing policy, not a calibrated match probability, which is exactly why the middle keeps a curator path. This is entity alignment with an explicit abstain.
Grounded extraction libraries
jevextract generalizes the span-choice approach into a schema-driven library. Deterministic code proposes candidate spans with exact offsets, and Jev answers one Choice per span plus sentence-level Nouls. The invariant doc.text[start:end] == e.text holds by construction; there is no alignment step and no LLM-written output. On its benchmark it cost $1.05–1.50 per 1,000 documents at 0.6–1.1 seconds median per document, against $13–28 and 7–14 seconds for LangExtract on Gemini 3.5 Flash. Quality is more mixed: relaxed span F1 was 84.2 against 88.5 for LangExtract and 92.0 for an LLM JSON baseline, with an optional mention gate raising it to 88.0. The README also reports that Jev decisions are not deterministic, with two runs agreeing at Jaccard 0.86–0.97 and confidence over-confident at ECE 0.17–0.44.
JevSpan applies the same shape to zero-shot named entity recognition. Text is split at punctuation, candidate windows are offered as Choice options, and nominated windows are verified and boundary-polished by further calls. It averages 73.7 strict F1 across 12 Chinese and English NER benchmarks and beats Qwen3.8-27B direct extraction by 1.6 points using the same type descriptions. The biggest accuracy lever is not a model setting but a boundary convention: on a small e-commerce set, one sentence saying that a model name excludes the product category and version suffix raised strict F1 from 0.778 to 0.945. Both libraries are MIT-licensed and call a hosted API; neither ships local weights.
Verify the record, not just the schema
A JSON-schema-valid record can still be semantically wrong. The SDE cascade cookbook makes this concrete: a cheap model extracts, a battery of Nouls verifies each field in one request, and any per-field probability above 0.7 escalates the record to a reasoning model. A fabricated description read hallucinated 0.95 and off_target 0.85, while correct and empty fields sat between 0.02 and 0.14.
The cookbook deliberately avoids structured outputs and JSON mode at the extraction rung, on the argument that a schema-following mistake is usually a sign the model is confused, which constrained decoding does not fix. The cost/quality sweep is a historical snapshot, not recalculated at the current Jev rate, so re-run it before quoting the numbers. The durable lesson is the verification layer: field-level questions catch semantic errors that validation cannot.
Keep arithmetic and normalization in code
The jaggedness list names the failure modes that matter here: counting is unreliable and error grows with size, dates are read as text, and structural invariants do not hold. Do not ask for a total, do not ask the model to compare two dates, and do not assume complementary probabilities sum to one.
A practical extraction pipeline is therefore: regex, parser, or NER proposes spans; Jev chooses among them or marks none; code normalizes units, dates, and identifiers; a small verification battery checks the chosen fields; and anything uncertain goes to a person. The records article shows the same shape in document and inbox tools, and numbers, dates, and units in decision states goes deeper on the state design. If you only remember one rule, make it this: the model chooses, code copies.