Belgium — 30 addresses, three configurations
What ran
On 2026-08-04 we ran 30 Belgian address lines through a local install three times, changing one
thing each time. Belgium was chosen because it is not a measured localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.: no Belgian rooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. 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.
ships, no nl-BE or fr-BE weightsparameterA single learned number inside a model — one weight or bias. Mailwoman's encoder has roughly 30 million of them; training is the search for good values. package exists, and the global candidate 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. is the only
artifact answering. This panel reports what that gets you.
It also carries a case Belgium is well suited to. Five Brussels streetsstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. appear twice, once in Dutch
and once in French — Wetstraat and Rue de la Loi, Grote Markt and Grand-Place — so a pair
tests whether two surface forms of one streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. reach one place.
The result the page turns on: out of the box, six of the 30 rows do not land in Belgium. Setting one option fixes all six.
Method
The panel is be-panel.json: thirty address lines built from public
streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. names, each paired with the 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. and commune it belongs to. Ten are the five bilingual
Brussels pairs; nine are in Flanders, nine in Wallonia, and two in the German-speaking Community. No
Belgian rooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. 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. ships, so 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. is parsed and never looked up — the panel does not
depend on any particular number existing at any of these streetsstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels..
Three arms, each named for the question a reader arrives with:
| Arm | WeightsparameterA single learned number inside a model — one weight or bias. Mailwoman's encoder has roughly 30 million of them; training is the search for good values. | Configured | Question |
|---|---|---|---|
base | en-US | nothing | What does an install plus a 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. give me? |
fr-overlay | fr-FR | nothing | Does the nearest measured localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. help? |
country-pinned | en-US | defaultCountry: "BE" | What if I tell it the file is Belgian? |
The first two leave the countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. unpinned, because countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. routing is the measurement. Belgian place names collide with Dutch, French and Slovenian ones, and a cross-border miss is the failure worth catching.
Four things are graded, and there is no ground-truth coordinate set among them. Belgium has no public rooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. 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. we can grade distances against, so this page claims no distance to a true building.
- Resolution — did a coordinate come back, and at which tier.
- CountrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. routing — is the coordinate inside a bounding box drawn around Belgium's extremesexpectation-maximizationAn iterative algorithm that estimates model parameters when some variables are unobserved. In Mailwoman's matcher, EM learns the Fellegi-Sunter m and u parameters from unlabeled data — no training labels needed., and
does the result name
BE. A coordinate outside the box did not land in Belgium; one inside it is not thereby correct. - LocalitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy., split in three, because the two obvious versions of it are each wrong on their own.
parsedreads the 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 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.' labeled, which is close to circular — the commune is right there in the input string.name matchedreads only the nodes the resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. decorated, which says 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. returned an accepted spelling and says nothing about where.resolvedis the name match conjoined with the bounding-box check, and it is the one to read: a place nametoponymA proper name for a geographic place. is not unique on Earth, and this panel exists to catch the cases where the wrong one won. - Bilingual agreement — for each pair, the distance between the two language forms. This one needs no ground truthground truthThe correct answer for an example, used as the standard a prediction is graded against. Mailwoman's ground truth is the hand-labeled golden set; its quality caps achievable accuracy. at all: the two rows name one streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels., so any distance between them is 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. disagreeing with itself.
Numbers
Thirty rows per arm, from be-results.json:
| Measure | base | fr-overlay | country-pinned |
|---|---|---|---|
| Returned a coordinate | 27 | 27 | 30 |
| Inside the Belgium bounding box | 24 | 24 | 30 |
Result names BE | 24 | 24 | 30 |
| LocalitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. — parsed | 29 | 29 | 30 |
| LocalitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. — name matched | 26 | 26 | 30 |
| LocalitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. — resolved, in Belgium | 24 | 24 | 30 |
| Bilingual pairs declared | 5 | 5 | 5 |
| Bilingual pairs comparable | 4 | 4 | 5 |
| Bilingual pairs agreeing | 4 | 4 | 5 |
| Worst pair separation | 0 km | 0 km | 0 km |
Answered at admin | 27 | 27 | 30 |
| Answered at no tier | 3 | 3 | 0 |
Three readings, in order of how much they change what you would do:
Every row that answered at all answered at admin — a commune centroid. Nothing on this panel is
streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.-grade, because there is no Belgian artifact that could make it streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.-grade. A perfect score
here means "resolved to the right commune", and a commune is kilometers wide. Three rows in the first
two arms answered at no tier: they returned no coordinate, and they are counted as none rather than
folded into the admin row.
The two localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. rows are one metric and its check. A name match says 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. returned a place carrying an accepted spelling. It does not say the place is in Belgium, and on this panel that gap is exactly two rows in each of the first two arms — one Belgian commune name matched in the Netherlands, one in France. The row that means what a reader thinks "localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy." means is the last of the two.
The French overlay changes nothing. The fr-overlay arm is identical to base on every measure
and on every one of the thirty per-row records. The result file says why, in the per-arm weights
entry rather than the single versions.model run stamp. Both arms record the same weights.model,
model.onnx, while their weights.source differs — and the difference is the giveaway:
package:@mailwoman/neural-weights-en-us against package:@mailwoman/neural-weights-fr-fr+base. That
+base suffix is the loader reporting that the French package resolved through to the base one. The
French package is a data-only overlay: it ships no model.onnx at all, only French 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.,
pair-index and FSTFST (finite-state transducer). A compact automaton that reads an input sequence and emits an output sequence. Mailwoman encodes gazetteer names and street affixes as FSTs for fast prefix matching and prior injection without search overhead. siblings. None of those siblings is consulted for a Belgian 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.. Belgium is
not a tier, and choosing the nearest tier does not make it one.
Pinning the countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. fixes every failure. country-pinned is 30 out of 30 on all six resolution
measures. That is one option in the call, and the section below is what it is repairing.
Losses
Six rows fail in the base arm. Five are one defect and the sixth is a different one.
| Address | Where it landed | Named |
|---|---|---|
Grote Markt 1, 1000 Brussel | no coordinate | — |
Rathausplatz 1, 4700 Eupen | no coordinate | — |
Hauptstrasse 1, 4780 Sankt Vith | no coordinate | — |
Oude Markt 1, 3000 Leuven | 51.844, 5.094 — the Netherlands | NL |
Place Saint-Lambert 1, 4000 Liège | 47.229, 1.110 — Le Liège, France | FR |
Rue Léopold 1, 4000 Liège | 46.243, 14.364 — Slovenia | SI |
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. is not the problem. Probing candidate.db directly for the names these rows carry:
leuven → Leuven/BE pop=102275 | Leuven/BE pop=101032 | Leuven/NL pop=0
liege → Liège/BE pop=197013 | Liège/BE pop=195278 | … | Le Liège/FR pop=238
eupen → Eupen/BE pop=19254
sankt vith → Sankt Vith/BE pop=9481
The Belgian answer is present and ranked first in each case. A 102,275-person Belgian citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. loses to a zero-population Dutch hamlet of the same name, and a 197,013-person Belgian citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. loses to a 238-person French commune, so ranking is not what decided these.
The countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. prior is. Re-running the six failures with the countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. filter disabled, same weightsparameterA single learned number inside a model — one weight or bias. Mailwoman's encoder has roughly 30 million of them; training is the search for good values., same 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., same input strings:
default hardPlaceCountry: false
───────────────────── ────────────────────────
(none) → BE 50.850, 4.349 Grote Markt 1, 1000 Brussel
(none) → BE 50.631, 6.031 Rathausplatz 1, 4700 Eupen
(none) → BE 50.280, 6.126 Hauptstrasse 1, 4780 Sankt Vith
NL 51.844, 5.094 → BE 50.879, 4.701 Oude Markt 1, 3000 Leuven
FR 47.229, 1.110 → BE 50.645, 5.574 Place Saint-Lambert 1, 4000 Liège
SI 46.243, 14.364 → SI 46.243, 14.364 Rue Léopold 1, 4000 Liège
Five of the six recover. The mechanism is that a confident whole-string countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. guess is promoted from a ranking bias to a filter, and when the guess is wrong the correct candidates are removed before ranking runs. That is also why three of the six returned nothing rather than something wrong: with every Belgian candidate filtered out, there was nothing left to rank.
The sixth row is 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. failure and survives every fix. Rue Léopold 1, 4000 Liège 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. as
streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. Rue Léopold 1, 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. 4000 Liège, 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. null — the number is swallowed into 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. 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. and the commune into the 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. 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.. Slovenia's 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. 4000 is Kranj, and a query
carrying 4000 and no readable commune routes there. Under country-pinned this row returns the
right coordinate, and its 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. is still wrong: 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. null, streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. still Rue Léopold 1,
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. still 4000 Liège. The 30-out-of-30 above includes a row whose 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. is broken. That is
the resolve-rate trap in its natural habitat, and it is the reason this page reports the parsed and
resolved localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. counts as separate rows instead of one.
Two of the six were scored as localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. hits until the metric was fixed. Oude Markt 1, 3000 Leuven resolves to a hierarchy reading ["Leuven"] and Place Saint-Lambert 1, 4000 Liège to
["Le Liège", "Liège"]. Both are accepted spellings. Both are in the wrong countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head.. A name match is
not a resolution on a panel whose subject is cross-border misrouting, which is why the published
metric is the name match conjoined with the bounding-box check — and why the two rows are reported
separately rather than one replacing the other.
One bilingual pair could not be measured. Grote Markt 1, 1000 Brussel returned no coordinate in
the base and fr-overlay arms, so its French twin had nothing to be compared against. The pairs
row reads 4 comparable of 5 declared rather than 4 of 4 because an early version of the script
dropped the unmeasurable pair from its own denominator and reported a clean sweep. Of the pairs that
could be compared, every one agreed to within the reporting precisionprecisionOf the spans the model labeled as a given tag, the fraction it got right. High precision means few false positives. Paired with recall to compute F1., in every arm.
Caveats
Belgium is not a measured localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for., and this panel does not make it one. There is no Belgian evalevalRunning the model against a held-out golden dataset and computing per-component F1, exact-match, calibration, and resolved-coordinate error. set, no Belgian 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. tier, and no Belgian rooftop datasitus dataA dataset of exact address-point coordinates (rooftop-level). Mailwoman's geocoder uses a national situs layer (124.9M US points built from state address-point sources) as the highest-precision tier of the geocode cascade.. Everything above is 30 addresses through a global 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.. Locales and tiers draws the line this page sits outside of.
Every number is a commune-grade number. All 84 answering row-runs answered at admin. Do not read
30 of 30 as streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. accuracy — read it as "the right commune centroid", with the error bounded by
the size of the commune rather than by anything measured here.
The bounding-box check is coarse in one direction only. A coordinate outside the box definitely missed Belgium. A coordinate inside it could still be the wrong commune, and the localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. row is what covers that case.
The localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. expectations are ours. Each row carries a committed list of accepted commune
spellings in be-panel.json, covering the Dutch, French and English forms a 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. may hold. We
wrote those lists. They are public facts and checkable, and they are still our lists.
n = 30, and the rows are civic addresses on well-known streetsstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.. That is an easier population than a delivery manifest. A harder panel would score worse, and we have not run one.
What to do with this
Pin the countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. when you know it. For a file you already know is Belgian, defaultCountry: "BE" took
this panel from 24 correct to 30, and it is the same one-line change in the library, the CLI and the
server. The countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. prior exists to help an input that arrives with no context; a file that has
context should say so rather than let the prior guess.
Reproduce
The script is be-panel.mjs, the panel is
be-panel.json, and the output above is
be-results.json verbatim, including a per-row record for all thirty
addresses in each of the three arms.
That file's versions block records what this run used: Mailwoman 8.7.0, model.onnx from
neural-weights-en-us@7.0.0, and candidate-global-1026.db. Each arm additionally carries its own
weights entry, which is how the identical base and fr-overlay columns are traceable to one ONNXONNX (Open Neural Network Exchange). An open format for machine learning models that enables interoperability between training frameworks and inference runtimes. Mailwoman ships its trained model as an ONNX file so it can run in Node.js and the browser via onnxruntime.
file behind two package names. There is no data-release field, because no Belgian 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. ships to
have one.
npm install mailwoman @mailwoman/neural @mailwoman/neural-weights-en-us \
@mailwoman/neural-weights-fr-fr @mailwoman/resolver \
@mailwoman/resolver-wof-sqlite @mailwoman/spatial
mailwoman data pull candidate
node be-panel.mjs --data-root <DATA_ROOT> --out be-results.json
One 1.65 GB bundleevidence bundleThe pair of retrieval-augmented input channels (street-type + locality-surface) that feed lexicon membership as soft per-token evidence alongside the text. Shipped in 6.7.0; trained natively from step 0 in the from-scratch base line., and no rooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. shardshardA partial output file of the corpus build, written in Parquet format. The training pipeline streams shards row by row. — that is the point of the panel. The three arms took 4,273 ms together, 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.' load excluded.
Related
- France — 100 addresses from the BAN — the same machinery where a national 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. does exist.
- Reading our numbers — why the resolve rate and the precisionprecisionOf the spans the model labeled as a given tag, the fraction it got right. High precision means few false positives. Paired with recall to compute F1. are different numbers.
- Locales and tiers — which countries are measured.
- Runtime flags — the countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. prior and its filter.