Session Report — 2026-05-28
Summary
Two major infrastructure shifts: (1) migrated from self-hosted docs to GitHub Pages + HF Bucket for 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.' assets, and (2) expanded WOFWOF (Who's On First). An open-source gazetteer of places maintained by Mapzen/whosonfirst. Mailwoman builds a custom SQLite database from WOF GeoJSON repos, extended with postcode data, importance scores, and coincident-role relations. data from US-only to 7-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. global coveragecoverageThe fraction of a population or region for which a data source has real, non-placeholder entries — e.g. 47% rooftop coverage on Texas addresses. Distinct from accuracy on the rows that are present. with a multi-script 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. retrain.
WebGPU debugging arc
The bug
The demo's 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. 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.' produced correct results via WASM but garbage via WebGPU on Safari/iOS. All-localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. output with 0.2-0.4 confidence. Playwright tests (headless, no GPU) always passed — masking the bug entirely.
Root cause
onnxruntimeONNX (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.-web ships two WebGPU execution providers in the same package:
import "onnxruntime-web"→ JSEPJSEP (JavaScript Execution Provider). onnxruntime-web's older WebGPU backend. A kernel bug on slice operations with axis reversal corrupted int8 dequantization in the browser; it has been superseded by the native WebGPU execution provider. (old, broken slice kernel on Metal)import "onnxruntime-web/webgpu"→ Native EP (correct on all backends)
The default import uses JSEPJSEP (JavaScript Execution Provider). onnxruntime-web's older WebGPU backend. A kernel bug on slice operations with axis reversal corrupted int8 dequantization in the browser; it has been superseded by the native WebGPU execution provider.. Chrome's Dawn/Vulkan masked the bug; Safari's Metal exposed it.
Fix
One import path change: onnxruntime-web → onnxruntime-web/webgpu. WebGPU now works on Chrome, Safari macOS, and iOS Safari — verified on real devices.
Takeaway
Headless CI cannot catch GPU-specific bugs. The verify skill's Playwright tests were passing while every real user saw garbage. Added diagnostics (backend indicator, force-WASM toggle, build stamp) to make this class of issue visible.
Reference: Technical doc. Research blog post: "Our 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.' worked in CI but broke on every real device".
Infrastructure migration
GitHub Pages + HF Bucket
Replaced the playpen nginx + rsync deployment with:
- GitHub Pages: Docusaurus builds and deploys via Actions on push to main
- HF Bucket: 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.'.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., 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..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.', 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.-en-US.bin, wofWOF (Who's On First). An open-source gazetteer of places maintained by Mapzen/whosonfirst. Mailwoman builds a custom SQLite database from WOF GeoJSON repos, extended with postcode data, importance scores, and coincident-role relations.-hot.db served from CDN
- Version selector: demo page fetches
releases.jsonmanifest, lets users switch between v0.5.3, v0.5.2, v0.4.0, v0.1.0 - Cache-busting:
stale-while-revalidateon HTML, version-qualified asset URLs
Demo improvements
- Build stamp footer (commit hash + timestamp)
- Backend indicator (webgpu/wasm + 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.' size)
- Force WASM toggle
- CodeBlock for XML output (syntax highlighting + copy)
- Example buttons clear stale results
- 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. provenance metadata (expandable details)
Global WOF expansion
Data pipeline
Built a unified SQLite from 7 priority countries (US, FR, JP, CN, KR, DE, GB):
| Metric | Value |
|---|---|
| GeoJSON files | 1.74M |
| Admin places | 1,288,749 |
| Name variants | 10,233,886 |
| Languages | 20+ |
| Build time | 185s (3 min) |
| Frozen DB | 1.09 GB |
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. implements the WAL + FreezeWAL + FreezeThe SQLite build pattern for the gazetteer: ingest under WAL (write-ahead logging) for concurrent writes, then checkpoint, set journal_mode=DELETE, add indexes, ANALYZE, and VACUUM INTO to emit a clean read-only artifact with no sidecar files. design brief: WAL during ingest, checkpointcheckpointA saved snapshot of the model weights and optimizer state during training. Mailwoman saves a checkpoint periodically so training can resume after a GPU hang. + journal_mode=DELETE + indexes + ANALYZE + VACUUM INTO for the frozen artifact.
Tokenizer retrain
v0.6.0-a0 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. trained on 2.19M multi-script WOFWOF (Who's On First). An open-source gazetteer of places maintained by Mapzen/whosonfirst. Mailwoman builds a custom SQLite database from WOF GeoJSON repos, extended with postcode data, importance scores, and coincident-role relations. names:
| Script | v0.5.0-a1 (old) | v0.6.0-a0 (new) |
|---|---|---|
| Chinese | 50-75% byte-fallback | 0% |
| Japanese | 58-60% | 0% |
| Korean | 41% | 0% |
| Thai | 30% | 0% |
| Aggregate | 36.6% | 0.0% |
Issue #120 target was less than 5%. Hit 0%. Same 48K vocabvocabularyThe fixed set of tokens a tokenizer can produce. Mailwoman's SentencePiece vocabulary is tens of thousands of subword pieces, with byte fallback for anything outside it., 28 seconds to train.
Global FST
Multi-language 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. with Unicode-aware normalization:
| Metric | US-only (old) | Global (new) |
|---|---|---|
| StatesregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. | 60K | 2.08M |
| Places | 94K | 1.25M |
| Name insertions | 128K | 4.16M |
| Binary size | 9 MB | 302 MB |
| CJK queries | Impossible | Working |
"東京" → Tokyo, "北京" → Beijing, "서울" → Seoul, "大阪" → Osaka.
CJK normalization fixes
Three files needed Unicode-aware regexes:
fst-matcher.ts:normalizeTokens()—[^a-z0-9\s]→[\p{P}\p{S}]fst-builder.ts:languages: ["*"]support for all-language indexingfst-prior.ts:hasAlnumcheck andnormalizeFstToken()— ASCII → Unicode property escapes
Piscina lock fix
The wof/prepare CLI command's Piscina workers were opening concurrent SQLite connections, causing SQLITE_BUSY. Fixed per the design brief: workers return ParsedPlace[] to the main threadthreadA parallel workstream within a release. Threads compose; they are not sequential milestones like phases., main threadthreadA parallel workstream within a release. Threads compose; they are not sequential milestones like phases. handles all DB writes in batched transactions.
FST V4 format
The global 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.'s root stateregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. has 488K edges — overflowed the u16 edgeCount field. Bumped to V4 with u32 edge/place counts per stateregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. (STATE_ENTRY_SIZE 12 → 16). Backwards compatible.
v0.5.4 training
Running on ModalModalA cloud GPU platform (modal.com) where Mailwoman trains its neural models on NVIDIA A100 GPUs. Training runs are launched via scripts/modal/train_remote.py and typically complete in ~1 hour. A100 with:
- v0.6.0-a0 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. (multi-script, 0% CJK byte-fallback)
- v0.5.1 recipe (wofWOF (Who's On First). An open-source gazetteer of places maintained by Mapzen/whosonfirst. Mailwoman builds a custom SQLite database from WOF GeoJSON repos, extended with postcode data, importance scores, and coincident-role relations.-admin: 2.0, constant LR, no 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., 100K steps)
- Per-tag F1 logging
- Step 48000/100000 at time of writing
HF Bucket inventory
| Path | Size | Description |
|---|---|---|
en-us/v0.5.3/* | ~75 MB | Current 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.' release (4 versions available) |
tokenizer/v0.6.0-a0/* | 1.9 MB | Multi-script 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. |
wof/admin-global-priority-7country.db | 1.09 GB | Global admin DB |
wof/fst-global-7country-all-langs.bin | 302 MB | Global multi-language 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. |
Issues closed
- #120: 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. retrain (0% byte-fallback achieved)
- #98: PhasephaseA milestone in the implementation plan (Foundation, Corpus, Training, Integration, and forward-looking phases). Distinct from stage (runtime pipeline) and tier (model vocabulary). B browser demo (closed previous session)
- #47: PhasephaseA milestone in the implementation plan (Foundation, Corpus, Training, Integration, and forward-looking phases). Distinct from stage (runtime pipeline) and tier (model vocabulary). 3.x browser demo (closed previous session)
Night shift addendum (02:00–02:40 UTC)
v0.5.4 shipped
- 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. completed (100K steps, A100, ~2.5h)
- Export → 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. 117 MB → int8 28.1 MB
- Demo presets: 6/6 correct on int8
- Error analysis: 17.0% exact matchexact matchThe share of eval items whose every component is correct (compared per-span or per-token). Stricter than per-tag F1, which credits partial correctness. on 4535 golden entries (cross-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. comparison invalid per evalevalRunning the model against a held-out golden dataset and computing per-component F1, exact-match, calibration, and resolved-coordinate error. protocol — schema mismatch dominates; 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). 3 will close most boundary errors)
- Uploaded to HF
en-us/v0.5.4/with 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.'.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., 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..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.', 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.-en-US.bin, 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.'-card.json en-us/releases.jsonupdated,defaultVersion: v0.5.4neural-weights-en-uspackage version bumped to 0.5.4
Stage 3 corpus adapters shipped
All three priority adapters now emit street_prefix, street_suffix, unit from existing structured input — no rescraping needed.
- TIGERTIGERThe US Census Topologically Integrated Geographic Encoding and Referencing database. Used as a corpus source for street-segment data.:
decomposeStreet()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. FULLNAME using libpostallibpostalAn open-source C address parser used by Pelias. Mailwoman's rule-based v0 and neural classifier supersede it./en directionals + street_types. 8 unitunitA subdivision of a building — apartment, suite, floor — that refines a street address. Mailwoman's unit component; a designator plus identifier forms a subpremise. tests pass. - NADNAD (National Address Database). A US Department of Transportation dataset of structured address points, added to the training corpus as a major source of real US addresses.: Uses NADNAD (National Address Database). A US Department of Transportation dataset of structured address points, added to the training corpus as a major source of real US addresses.'s structured
St_PreDir/St_PreTyp/St_PosTyp/St_PosDirfields directly.Unit/Building/Floor/Roomchain intounittag. - BANBAN (Base Adresse Nationale). France's authoritative open national address register — the highest-quality training source for French addresses, with full component structure.: French streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. types are leading words (
Rue,Avenue,Boulevard).decomposeFrStreet()uses libpostallibpostalAn open-source C address parser used by Pelias. Mailwoman's rule-based v0 and neural classifier supersede it./fr/street_types. 6 unitunitA subdivision of a building — apartment, suite, floor — that refines a street address. Mailwoman's unit component; a designator plus identifier forms a subpremise. tests pass.
ACTIVE_TAGS remains STAGE2 — bump to STAGE3 when v0.6.0 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. is ready.
Japanese WOF adapter prototype
wof-admin-jp walks the global SQLite parent chainparent chainThe sequence of administrative parents above a place — Springfield → Sangamon County → Illinois → United States. Used to check the geographic coherence of a parse. for every 丁目 (chome) in the JP repo. Produces 6,373 synthetic JP 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. rows across 47 prefectures, 269 localities. Top: 東京 (Tokyo) 2,251 rows. See the blog post "Why Japanese addresses break Western parsers".
Per-locale FSTs on HF
Seven localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. FSTsFST (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. uploaded to hf://buckets/sister-software/mailwoman/fst/:
| LocalelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. | Size | StatesregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. |
|---|---|---|
| en-US | 20.9 MB | 160K |
| en-GB | 3.7 MB | 33K |
| fr-FR | 10.2 MB | 72K |
| ja-JP | 13.0 MB | 116K |
| ko-KR | 7.1 MB | 55K |
| zh-CN | 92.5 MB | 589K |
| de-DE | 8.1 MB | 70K |
CJK queries (東京, 北京, 서울) now resolve correctly. Deep demo wiring (localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. detection → dynamic 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. swap) deferred — out of scope for tonight.