PR3 — the self-conditioned retrain (plan)
The third and largest step of the system-conditioning work. The consult and the risk-probe that motivate it are written up in the research blog post "Does 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. know what 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. it's in?" and the consult notes under .agents/skills/deepseek-consult/session-notes-2026-06-03-system-conditioning.md. PR1 (the codex inverse-mapping + the membership-gated anchor, #264) shipped. PR2 (an anchor-only localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. prior replacing --default-country) was killed by the risk-probe before it was built. This is the piece the probe pointed at: teach 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.' to infer 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. from the whole address and condition its own labeling on it.
This document is the plan, not a launch. It costs GPU time and changes 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.', so the run waits on explicit sign-off. The decisions that need an operator call are collected at the end.
Why now
The probe measured the assumption everything else rested on: 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. pins its own 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. only 27.9% (US) / 44.1% (DE) of the time, because a bare five-digit code is a valid US ZIP, German PLZ, and French code at once. The strongest single pre-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. signal settles 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. less than half the time, so the rest has to come from the citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy., 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 order 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). arrive in. That is a job for 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.' reading the full sequence, which is exactly what self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. is.
It also lines up with the failure that started the anchor work. The v0.8.0 German order-shardshardA partial output file of the corpus build, written in Parquet format. The training pipeline streams shards row by row. taught us that order is learnable cheaply, but the continue-train re-triggered the Saint-AlbansBAN (Base Adresse Nationale). France's authoritative open national address register — the highest-quality training source for French addresses, with full component structure. 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. fragmentation at end-of-string — an emission-level collapse where a citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.'s lead 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. bled 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.. The hypothesis behind self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. is that a 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.' which has already resolved "this is a German address" globally, before it commits 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. labelscomponent tagOne of the 33 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., stops making that cross-tag mistake. The pilot is built to confirm or kill that hypothesis on a budget.
What changes in the model
The architecture is grounded in corpus-python/src/mailwoman_train/model.py (MailwomanCoarseEncoder): a 6-layerlayerOne transformer block — attention plus a feed-forward network, with normalization and residual connections — applied to every position. Stacking layers lets the model build up richer representations; Mailwoman's encoder has 6., 384-hidden, 6-headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads. pre-norm transformerneural 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.' encoderencoderThe part of a transformer that turns input tokens into contextualized vector representations. Mailwoman's classifier is a small encoder-only transformer (~30M parameters). feeding a single linear BIO headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads. over 33 labelscomponent tagOne of the 33 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. (labels.py, 16 component tagscomponent tagOne of the 33 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.). No localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. representation exists anywhere in it today. Self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. adds three small 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). and reuses one that is already there.
1. An auxiliary localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads. (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.''s own country posteriorcountry posteriorA country → probability map (derived from postcodes or the coarse-placer) that re-ranks resolver candidates as a soft prior, never a hard filter.). Mean-pool the encoderencoderThe part of a transformer that turns input tokens into contextualized vector representations. Mailwoman's classifier is a small encoder-only transformer (~30M parameters). output over non-padpadding tokenA filler token added to short sequences to reach a fixed length, masked out during attention so it carries no meaning. tokenstokenOne 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. into a single vector, run it through Linear(384 → num_locales), and train it with cross-entropycross-entropyThe standard classification loss: it penalizes a model for putting low probability on the correct label. Per-token negative log-likelihood is the cross-entropy of each token's label. against the row's country field. The 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. already carries country on every row (corpus/src/types.ts CanonicalRow, the country parquetParquetThe open columnar file format the corpus is written and streamed in. The training pipeline reads shards row-by-row from Parquet. column data_loader.py reads), so the target is free. This headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads. is what forces the pooled representation to actually encode "which 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.", and it closes the loop with the consult: it is the authoritative LocalePosterior 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. wanted. Export it alongside the BIO output, and 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.'s swappable localePriorProvider finally has a strong producer to point at.
2. Feedback from that posterior into the 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. labeling (the "self" in self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders.). The design rule is that localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. gets resolved globally, before 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. labelscomponent tagOne of the 33 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.. So project the pooled localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. representation into a FiLM modulationFiLM modulation (Feature-wise Linear Modulation). A parameter-efficient adaptation that scales and shifts feature vectors by learned per-example multipliers and biases. Used in self-conditioning to make parsing decisions locale-aware without retraining the whole model. (a learned scale and shift) and apply it to 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. representations feeding the BIO headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads.: h' = γ(p) ⊙ h + β(p). 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.' infers 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. once from the whole string, then lets that inferenceinferenceRunning the trained model on new input to get predictions, as opposed to training, which produces the model. In Mailwoman that means a small transformer encoder reads an address string and classifies every token — house number, street, locality, region, postcode, and the rest. A Who's On First gazetteer can feed soft location hints into the pass, but the model makes the final call on every label. Where a generative model writes text token by token, Mailwoman's output is a retrieval-augmented token classification: one label per input piece. reshape how it labelscomponent tagOne of the 33 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. each 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.. If headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads.-level FiLM proves too weak to move the cross-pollutioncross-pollutionAn eval tripwire for unwanted tag bleed across locales — predicting a German city as a postcode because multi-locale training let one locale's patterns hurt another. metric, the escalation is to split the encoderencoderThe part of a transformer that turns input tokens into contextualized vector representations. Mailwoman's classifier is a small encoder-only transformer (~30M parameters). and FiLM the back half (infer localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. after layerlayerOne transformer block — attention plus a feed-forward network, with normalization and residual connections — applied to every position. Stacking layers lets the model build up richer representations; Mailwoman's encoder has 6. 3, condition layerslayerOne transformer block — attention plus a feed-forward network, with normalization and residual connections — applied to every position. Stacking layers lets the model build up richer representations; Mailwoman's encoder has 6. 4–6). That is more faithful to "before 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. labelscomponent tagOne of the 33 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." and more code, so it is the fallback, not the opening move.
3. The cheap-prior / anchor input channel, via the seam that already exists. 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.' has a phrase_priors path (use_phrase_priors, model.py ~159–223): an optional (batch, seq, phrase_feature_dim) featurefeatureAn input signal a model conditions on. Beyond the raw tokens, Mailwoman feeds soft features — gazetteer-membership channels and the postcode anchor — that inform predictions without overriding them. tensor concatenated to 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.+position embeddingembeddingA vector of numbers representing a token (or other item) so that similar items sit near each other in vector space. The first thing the model does is turn each token into an embedding. and projected back to hidden, defaulting to zeros when absent. That zero-default is the anchor-dropoutdropoutA regularization trick that randomly zeroes a fraction of activations during training, forcing the model not to rely on any single feature. Disabled at inference. mechanism the design asked for, already built. The postcode anchoranchor inferenceA technique where structured knowledge (postcode locations, gazetteer place names) is injected into the model as soft input features — not as deterministic overrides. The model still decides the final labels, but the anchor signal biases it toward correct admin tags.'s 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. signal (country posteriorcountry posteriorA country → probability map (derived from postcodes or the coarse-placer) that re-ranks resolver candidates as a soft prior, never a hard filter. + confidence) rides in as additional featurefeatureAn input signal a model conditions on. Beyond the raw tokens, Mailwoman feeds soft features — gazetteer-membership channels and the postcode anchor — that inform predictions without overriding them. dims on this channel, and dropping it to zeros ~20% of the time during 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. keeps 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.' from depending on it. The catch the grounding surfaced: there is no path today from the TS anchor into the Python trainer — the anchor is runtime-only, post-hoc repair (neural/classifier.ts repairPostcodeLabels). Feeding it to 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. means a precompute pass that writes the anchor signal into the 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. shardsshardA partial output file of the corpus build, written in Parquet format. The training pipeline streams shards row by row.. That is real 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. work, and it is why the pilot splits.
The staging — prove the free thing first
The design doc bundled self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. and the anchor channel into one pilot. The grounding argues for separating them, because they have very different costs and the probe already told us which one is essential.
Pilot A — self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. only. No 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. rebuild. 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). 1 and 2 above. The localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. target is the existing country column; nothing in the data 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. changes. From scratch on US + FR + DE, balanced, against the v0.7.2 recipe with exactly one variable added (self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders.). Stop at the 20k-step gate. This is the cheapest possible test of the core hypothesis — does a 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.' that infers localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. globally and conditions on it 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. better and stop the German cross-tag collapse — and it needs no new data engineering. If self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. alone does nothing, the anchor channel is unlikely to rescue it, and we have spent a few dollars to learn that.
Pilot B — add the anchor input channel. Only if A clears its gate. Build the precompute pass (run the TS anchor over the 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., emit 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. anchor_posterior + anchor_confidence columns into the shardsshardA partial output file of the corpus build, written in Parquet format. The training pipeline streams shards row by row.), widen phrase_feature_dim, and retrain with anchor-dropoutdropoutA regularization trick that randomly zeroes a fraction of activations during training, forcing the model not to rely on any single feature. Disabled at inference.. This tests whether the anchor is a useful booster on top of self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders., which is the one thing the probe could not measure (a wide {DE, US} prior plus citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. tokenstokenOne 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. may still let 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.' commit correctly).
The real run. Only after a pilot passes and 4–5 localeslocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. are staged. One from-scratch, balanced, self-conditioned run, judged by 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., promoted only if it clears the pre-registered bars below.
Data and recipe
US and FR are already in the 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. (country_weights {US: 1.0, FR: 1.0} in the v0.8.1 config); the German OA adapter exists from the DE-1 work. Pilot A balances the three. Everything else holds at the v0.7.2 settings so self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. is the only moving part: label smoothinglabel smoothingA training regularization technique: instead of putting 1.0 probability on the correct label, train to put 1 − ε on it and ε/(N−1) on each wrong label. Improves calibration; disabled in some Mailwoman runs for stability. 0.1, CRFCRF (Conditional Random Field). A statistical modeling method that predicts structured outputs by modeling dependencies between adjacent labels. Mailwoman uses a linear-chain CRF as the Viterbi decoder at inference time to enforce BIO label consistency — a B-street must be followed by I-street or O, never I-locality. off (crf_loss_weight: 0.0, because it NaNNaN (not a number). A floating-point result for an undefined operation (log of a negative, 0/0). Appearing in the training loss usually halts the run; recovering from it follows the NaN protocol.'d under bf16bf16 (bfloat16). A 16-bit floating-point format used during training. Half the memory of fp32 with similar numeric range, which lets the training batch fit on the lab's GPU. twice and stays disabled until the core change is stable), the same tokenizertokenizerThe component that converts a raw address string into a sequence of numeric token IDs the model can process. Mailwoman's tokenizer is a SentencePiece unigram model trained specifically on postal addresses. (v0.6.0-a0, so F1 stays comparable across the change), constant LR with a 1000-step warmupwarmupThe early phase of training where the learning rate ramps up from 0 to its peak value before cosine decay. Mailwoman uses a linear warmup.. New knobs land on the existing config dataclasses (config.py): use_locale_conditioning, locale_loss_weight, num_locales, anchor_dropout_rate. Any new reduction-heavy op (the pooling, the FiLM) runs in fp32fp32 / fp1632-bit and 16-bit floating-point formats. Mailwoman trains in bf16 (a 16-bit variant) and exports the ONNX model in int8 for size. — the CRFCRF (Conditional Random Field). A statistical modeling method that predicts structured outputs by modeling dependencies between adjacent labels. Mailwoman uses a linear-chain CRF as the Viterbi decoder at inference time to enforce BIO label consistency — a B-street must be followed by I-street or O, never I-locality. NaNNaN (not a number). A floating-point result for an undefined operation (log of a negative, 0/0). Appearing in the training loss usually halts the run; recovering from it follows the NaN protocol. was a bf16bf16 (bfloat16). A 16-bit floating-point format used during training. Half the memory of fp32 with similar numeric range, which lets the training batch fit on the lab's GPU.-reduction failure, and we do not repeat that lesson.
The new metric we have to build
The pre-registered tripwire is "per-localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for., the rate of citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.-start tokenstokenOne 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. mis-tagged as postcode falls below 1% by 20k steps." That cross-pollutioncross-pollutionAn eval tripwire for unwanted tag bleed across locales — predicting a German city as a postcode because multi-locale training let one locale's patterns hurt another. metric does not exist yet: the current evalsevalRunning the model against a held-out golden dataset and computing per-component F1, exact-match, calibration, and resolved-coordinate error. (scripts/eval/per-locale-f1.ts, corpus-python eval.py) measure component F1 and calibration, not this specific confusion. It needs writing: over a held-out per-localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. set, count how often a 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. whose gold labelground 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. starts a locality/region 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. gets predicted postcode. This is the direct readout of the Saint-AlbansBAN (Base Adresse Nationale). France's authoritative open national address register — the highest-quality training source for French addresses, with full component structure. collapse, and it is the gate that tells us self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. is doing its job before we spend a full run.
The gates (pre-registered, resolver is the judge)
No promotion on parser-F1 alone. These come straight from the anchor-based-parsingaddress 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. decision rules and this session's consult.
- 20k cross-pollutioncross-pollutionAn eval tripwire for unwanted tag bleed across locales — predicting a German city as a postcode because multi-locale training let one locale's patterns hurt another. gate: citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.-start-as-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. under 1% per localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. by 20k steps. If it will not clear, that recipe has hit its interference ceiling; stop the run.
- No regression on the incumbents: US and FR 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. utility within 1pp of v0.7.2. Adding DE must not drop an existing localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.'s 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. citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.-match by more than 2pp (the 77→43 German collapse is the thing we are guarding against).
- DE has to actually move: German localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. F1 ≥ 70% and rising at the gate, or the run is not earning the German data.
- DropoutdropoutA regularization trick that randomly zeroes a fraction of activations during training, forcing the model not to rely on any single feature. Disabled at inference. robustness: with the anchor channel zeroed and the localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. signal dropped, degradation ≤ 5pp — proof 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.' learned to 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., not to lean on a crutch.
- Promotion is 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.'s call. Run the full
oa-resolver-eval(US + DE, real OA points) and the per-tag error analysis; promote to default only if 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. improves and no tag regresses more than 2pp. Otherwise the artifact ships labelled experimental inreleases.json, not promoted, the same discipline as every prior cycle.
Export and the resolver loop
The 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. export (export_onnx.py) grows a second output: the BIO logitslogitA raw, unnormalized per-label score the model outputs before softmax. Priors and biases are added in logit space, then softmax turns logits into probabilities. as today, plus the localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. posterior from the aux headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads.. At inferenceinferenceRunning the trained model on new input to get predictions, as opposed to training, which produces the model. In Mailwoman that means a small transformer encoder reads an address string and classifies every token — house number, street, locality, region, postcode, and the rest. A Who's On First gazetteer can feed soft location hints into the pass, but the model makes the final call on every label. Where a generative model writes text token by token, Mailwoman's output is a retrieval-augmented token classification: one label per input piece. the localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads. is cheap and useful — it is the LocalePosterior the consult specified, the strong producer 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.'s localePriorProvider was designed to swap in. When this lands, --default-country can finally retire, not because 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. got smarter, but because 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.' now reads the whole address the way the probe said it had to. That is the payoff that PR2 reached for too early.
Budget and protocol
The pilot is an A100 hour, roughly $3–8, inside the ~$30 already approved for the v0.7 line. The launcher is unchanged: modal run -d scripts/modal/train_remote.py --config <new-config> --resume auto, with --trackio for the live curves. The NaN protocolNaN protocolThe NaN-recovery discipline: stop, change one variable, retry, document the hypothesis — never adjust two knobs at once during recovery, or you can't tell which change fixed it. stands: one knob at a time (self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. is the only change in A), fp32fp32 / fp1632-bit and 16-bit floating-point formats. Mailwoman trains in bf16 (a 16-bit variant) and exports the ONNX model in int8 for size. for new reductions, stop on divergencedivergenceA training failure where loss descends through warmup, plateaus low for a while, then climbs catastrophically back to its starting magnitude — the model unlearns everything despite no obvious component failure. and diagnose a single variable before the next attempt, document the hypothesis in the config YAML as a comment. Stop at 20k on a gate failure rather than burning the full run.
File-level work list (Pilot A)
corpus-python/src/mailwoman_train/config.py— adduse_locale_conditioning,locale_loss_weight,num_localestoModelConfig.corpus-python/src/mailwoman_train/labels.py— a stable localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.-index map (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. → id) for the aux headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads.'s target.corpus-python/src/mailwoman_train/data_loader.py— surfacecountryas a per-row localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.-id target tensor (the column is already read).corpus-python/src/mailwoman_train/model.py— the pooled localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads., the FiLM feedback, the aux output; all new reductions in fp32fp32 / fp1632-bit and 16-bit floating-point formats. Mailwoman trains in bf16 (a 16-bit variant) and exports the ONNX model in int8 for size..corpus-python/src/mailwoman_train/train.py— add the aux CE losscross-entropyThe standard classification loss: it penalizes a model for putting low probability on the correct label. Per-token negative log-likelihood is the cross-entropy of each token's label. term, weighted bylocale_loss_weight.corpus-python/src/mailwoman_train/eval.py(and/or a newscripts/eval/cross-pollution.ts) — the citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.-start-as-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. metric, per localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for..corpus-python/src/mailwoman_train/configs/v0.9.0-pilot-selfcond.yaml— the pilot config: US/FR/DE balanced, self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. on, CRFCRF (Conditional Random Field). A statistical modeling method that predicts structured outputs by modeling dependencies between adjacent labels. Mailwoman uses a linear-chain CRF as the Viterbi decoder at inference time to enforce BIO label consistency — a B-street must be followed by I-street or O, never I-locality. off, v0.7.2 recipe otherwise.corpus-python/src/mailwoman_train/export_onnx.py— export the localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.-posterior output (wire into 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. later, not in the pilot).
Open decisions for the operator
- Approve the split (Pilot A self-conditioningself-conditioningAn auxiliary model head that predicts the input's locale (language/country) and then FiLM-modulates the encoder so parsing adapts to the detected locale. Structural facts like word order still need explicit training on both orders. first, then B adds the anchor channel) over the design doc's bundled single pilot, or run them bundled.
- LocalelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. granularity for the aux headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads.: 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. (US/FR/DE, matching the 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.
countrycolumn) or BCP-47 localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. (en-US/fr-FR, the optionallocalecolumn). 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. is simpler and sufficient for 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.; localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. is finer but sparser. Recommendation: 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. for the pilot. - Budget ceiling for the pilot — confirm the $3–8 / one-A100-hour stop-at-20k envelope.
- Conditioning mechanism: start with headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads.-level FiLM (cheapest) and escalate to back-half FiLM only if the cross-pollutioncross-pollutionAn eval tripwire for unwanted tag bleed across locales — predicting a German city as a postcode because multi-locale training let one locale's patterns hurt another. gate does not move, or go straight to back-half. Recommendation: start cheap, escalate on evidence.