How a model reads an address
The question
Hand the parser this, exactly as a user typed it into a phone:
beacon ridge analytics 800 f st nw washington dc 20004
No commas. No capitals. A company name sitting in front of the address. A streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. whose entire name is one letter. Six fields come back, and all six are right. What happened in between?
This page walks that one line through the parser end to end. Every stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale gate, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). gets its rule-world name before its statistical one, because every stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale gate, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). is doing a job you have written by hand at some point — a lookup table, a regular expression, a tie-break. The machinery is those same jobs, done with scores instead of verdicts.
The analog
Give the line to a person with a highlighter and ask them to mark it up. They will draw four
stretches: the company, the number, the streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels., and the town-plus-state-plus-postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. tail. They will
do it in one pass with the whole line in view, because the reason dc is a state is that
washington sits to its left and five digits sit to its right — nobody reads dc in isolation and
then moves on. And when they finish, they will glance back over the marking to check it reads: a
"this continues the town" stroke with no "the town starts here" stroke before it is a slip of the
pen, not a reading of the line.
That is the whole design. Four moves: cut the line into piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated)., score every possible mark on every piece, add what a place list already knows, and pick the marking that reads.
One: cut the line into pieces
The rule-world version: split on spaces and punctuation, and you have words.
What happens here: the piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated). are smaller than words. analytics arrives at the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' as five of
them:
▁Ana ly t ic s
The ▁ marks a piece that starts a new word. The piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated). come from a fixed inventory of 73,143 of
them, built once from trainingtrainingThe process of adjusting a model's parameters so its predictions match labeled examples, by repeatedly measuring error and nudging the weights to reduce it. Distinct from inference, when the trained model is run on new input. text, and any string at all can be spelled out of that inventory —
which is the property a word list does not have. A word list meets Analytics for the first time and
has nothing to say; a piece inventory spells it out of piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated). it has seen thousands of times.
Two things are worth carrying out of this stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale gate, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone).. Each piece records where it came from in your
original string, so nothing downstream ever needs to know that piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated). exist — you get character
offsets into the text you passed in. And the text the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' sees is not byte-for-byte the text you
typed: a fully lowercase ASCII input is restored to mixed case first, because that is the registerinput modeThe Decision-A register switch: 'fragmented' (human-typed fragments — feeds the evidence channels) vs 'formatted' (complete records — runs the trained absence identity). Explicit on CLI/API; per-endpoint defaults (batch→formatted, autocomplete→fragmented); kind-derived otherwise.
the trainingtrainingThe process of adjusting a model's parameters so its predictions match labeled examples, by repeatedly measuring error and nudging the weights to reduce it. Distinct from inference, when the trained model is run on new input. corpuscorpusThe BIO-labeled training data used to train Mailwoman's neural classifier. Assembled from real sources (OpenAddresses, National Address Database) and synthetic shards (boundary stress, order variants, negative space). Managed by @mailwoman/corpus. was labeled in. beacon reaches the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' as Beacon.
Tokens and labels covers both properly.
Two: score every mark on every piece
The rule-world version: a pattern that fires or does not. if (/^\d{5}$/.test(token)) and you
have a postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one..
What happens here: nothing fires. Every piece receives a score for every one of the 33 available
marks, and the marks compete. ▁2 gets a score for "postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. starts here", a score for "house numberhouse numberThe numeric or alphanumeric identifier of a building on a street. Mailwoman's house_number component; its position relative to the street name flips between locales.
starts here", a score for "outside every component", and thirty more.
The scores are computed with the entire line visible at once. That is the part a per-tokentokenOne word or subword in the tokenized input. For the neural classifier, tokens come from SentencePiece (subword units); for the rule classifiers, tokens are whitespace- and punctuation-separated words. rule
cannot reach. F is scored as the beginning of a streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. name because 800 sits to its left and a
localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy.-shaped word, a two-letter uppercase tokentokenOne word or subword in the tokenized input. For the neural classifier, tokens come from SentencePiece (subword units); for the rule classifiers, tokens are whitespace- and punctuation-separated words. and a five-digit number sit to its right — the
same evidence the person with the highlighter used, and for the same reason. Nothing about the
letter F on its own suggests a streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels..
Three: add what the place list already knows
The rule-world version: the gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. lookup you have written before. Take the tokentokenOne word or subword in the tokenized input. For the neural classifier, tokens come from SentencePiece (subword units); for the rule classifiers, tokens are whitespace- and punctuation-separated words., check it against a list of place namestoponymA proper name for a geographic place., and if it is in there, it is a place.
What happens here: the same lookup, made additive instead of decisive. Washington matches the
place index, so the piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated). it covers get a bonus on the localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. marks and a penalty on streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels., house
number and venuevenueA named, non-address place — a business, building, park, or stadium. Mailwoman's free-text point-of-interest component, added as a Tier 2 fine label.. The bonus is capped, and it is withheld entirely where a match sits in
streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.-shaped surroundings, so a streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. named after a town stays a streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.:
800 Washington Ave, Portland, OR parsesaddress parsingThe process of decomposing a free-text postal address string into structured components — house number, street name, locality, region, postcode, and country — so a geocoder can resolve them to coordinates. the same with the index wired and without it. In the run
above, the place index was the one prior that found anything to say.
The gazetteer prior is the full treatment.
Four: pick the marking that reads
The rule-world version: run your classifiers, then reconcile the mess afterward with tie-break heuristics — prefer the longer spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree., drop the continuation that has no beginning, and so on.
What happens here: whole readings are scored rather than repaired. A table built once from the labelcomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. list says which mark may follow which — "continues the streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels." is legal after "streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. starts here" and after itself, and after nothing else — and the decoderdecoderIn a transformer encoder-decoder model, the part that produces output sequences. Mailwoman's classifier is encoder-only (no decoder); the 'CRF decoder' is a different thing — a structured-prediction layer that picks the best label sequence from the encoder's outputs. searches for the highest-scoring reading that stays inside those rules. A continuation with no beginning is not fixed up after the fact; it never appears, because no legal reading contains one. Decoding and the best path has the mechanism.
Here is the reading that came out for our line, captured from a direct classifier call with the gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. index wired, one row per piece:
piece offsets label score
▁Beacon 0..6 B-venue 0.869
▁Ridge 7..12 I-venue 0.895
▁Ana 13..16 I-venue 0.915
ly 16..18 I-venue 0.901
t 18..19 I-venue 0.895
ic 19..21 I-venue 0.890
s 21..22 I-venue 0.914
▁8 23..24 B-house_number 0.899
0 24..25 I-house_number 0.876
0 25..26 I-house_number 0.899
▁ 27..27 O 0.744
F 27..28 B-street 0.849
▁S 29..30 I-street 0.858
T 30..31 I-street 0.926
▁N 32..33 I-street 0.917
W 33..34 I-street 0.912
▁Washington 35..45 B-locality 0.921
▁ 46..46 O 0.751
DC 46..48 B-region 0.876
▁2 49..50 B-postcode 0.905
0 50..51 I-postcode 0.908
0 51..52 I-postcode 0.906
0 52..53 I-postcode 0.910
4 53..54 I-postcode 0.898
B- marks where a spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. begins and I- marks a piece that continues it, which is how a per-piece
decision becomes a spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree.. Five piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated). of Analytics carry five separate labelscomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. that together mean one
thing.
What comes out
Walk that column, open a spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. at each B-, extend it at each matching I-, and close it at anything
else. Then nest the spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. by geographic containment, and you have the result:
region = "DC" 46..48 0.876
locality = "Washington" 35..45 0.921
street = "F ST NW" 27..34 0.892
venue = "Beacon Ridge Analytics" 0..22 0.897
house_number = "800" 23..26 0.891
postcode = "20004" 49..54 0.905
The offsets point into the string you passed in, not into the case-restored copy the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' read. The
values are the repaired forms — F ST NW rather than f st nw — which is why keeping your own copy
of the raw input is worth the line of code.
Run the same string through createRuntimePipeline, which is the entry point most consumers use, and
the tags, the values and the offsets come back identical. The confidences do not: the pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-gate → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. runs
repair passes the bare classifier call does not, and the venuevenueA named, non-address place — a business, building, park, or stadium. Mailwoman's free-text point-of-interest component, added as a Tier 2 fine label. lands at 0.754 rather than 0.897 while
the house numberhouse numberThe numeric or alphanumeric identifier of a building on a street. Mailwoman's house_number component; its position relative to the street name flips between locales. lands at 0.819 rather than 0.891. Read a confidence as attached to a path, not to a
string.
What it costs
A wrong field does not name its own stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale gate, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone).. Four things can produce street="Washington": the
piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated). split somewhere unhelpful, the scores were wrong, the place index missed, or the best legal
reading was a bad one. The four are not separable from the output alone, which is why
Report a parsing bug asks for the input string rather than a
description of the symptom.
Nothing in the chain abstains. Every stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale gate, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). produces scores, and scores always have a maximum, so there is always an answer. Hand it a line that is not an address and you get an address-shaped reading of it. What the model cannot do is the list of places that matters.
The number is narrower than the decision. The score on each spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. reports how sure the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' was about that labelcomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. on its own, before the place index was added in. So a spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. the place index corrected can come back carrying a lower number than the wrong reading it replaced — The gazetteer prior has the measurement. If you plan to route on the number, read Calibration and confidence before you pick a threshold.
Related
- Tokens and labels — what a piece is, and how per-piece labelscomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. become spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree..
- The gazetteer prior — the place lookup, made additive.
- Decoding and the best path — how a reading gets chosen.
- Understand a parse — the same walk, as something you run.
- Component tags — the 25 tags a parseaddress parsingThe process of decomposing a free-text postal address string into structured components — house number, street name, locality, region, postcode, and country — so a geocoder can resolve them to coordinates. can carry, and the 16 this modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' emits.