Parse in the browser
The parser is a 39.4 MB 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. graph and a SentencePieceSentencePieceA language-independent subword tokenizer that splits text into pieces using a unigram language model. Mailwoman uses a SentencePiece tokenizer with a 48,000-token vocabulary and byte-fallback, trained on address data rather than general text. 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.. Neither needs a server: a browser
can hold both, and onnxruntime-web can run the graph. @mailwoman/neural/web-loader is what wires
them together, and it produces the same AddressTree the Node runtime does.
If you have seen @mailwoman/neural-web referenced before, that package is now a deprecated
re-export shim. The browser runtime moved into @mailwoman/neural itself, as the ./web-loader and
./web-onnx-runner subpaths, and the shim re-exports both at their original identity so existing
imports keep working. Everything on this page uses the new subpaths.
The demo is the finished version of this — the same loader, the same 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.' files, 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. and a map. By the end of this page you'll have the 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. half of it in your own page: eight
files served from your own origin, one await, and a tree in the tab. You'll also have the measured
byte and time cost of the load, and a clear line around what the browser build does not do. About
twenty minutes.
Prerequisites
The third item decides how this page is structured, so read it before you copy any URL.
- A bundler that can serve static assets and an ESM project on Node.js 24.18.0 or later. The load
and 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. transcripts below were produced with the plain Node runtime, which runs the identical
onnxruntime-webWASM path — see How this page was verified. - About 125 MB of static assets to host: 50.4 MB of 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.' files plus
onnxruntime-web's four.wasmbuilds. A visitor fetches 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.' files and exactly one of those builds, which is between 12.5 MB and 25.4 MB depending on the execution provider the browser lands on. - The demo's asset host is not a public CDN.
public.sister.softwareanswers a cross-origin request only forhttps://mailwoman.sister.software, so a browser on your own domain gets noAccess-Control-Allow-Originheader back and the fetch fails. Host your own copies. Step 1 is where they come from, and they arrive in an npm package you already have if you have installed the parser at all. - 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. is not part of this. The browser runtime turns text into components. Turning those components into coordinates needs 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., and the browser story there is narrower than the 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. story — Resolving in the browser says exactly how narrow and what the next step is.
1. Copy the model files out of the weights package
The browser assets are the same files @mailwoman/neural reads on the server. They ship in the
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:
npm install @mailwoman/neural @mailwoman/neural-weights-en-us onnxruntime-web
onnxruntime-web is named explicitly because @mailwoman/neural declares both ONNX runtimesONNX (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. as
optional peer dependencies, so neither arrives on its own. That is the point: a browser app
installs onnxruntime-web, a Node service installs onnxruntime-node, and neither pays for the
other's binaries. It also means the runtime is a dependency you can see and pin in your own manifest
rather than one that appears transitively.
Eight files go into whatever directory your bundler serves. Four of them are lexicons the loader
looks for beside model.onnx by name, so keep them together:
mkdir -p public/mailwoman
for f in model.onnx tokenizer.model model-card.json \
anchor-lexicon-v1.json country-surface-lexicon-v1.json \
street-type-lexicon-v3.json locality-surface-lexicon-v6.json \
postcode-us.bin; do
cp "node_modules/@mailwoman/neural-weights-en-us/$f" public/mailwoman/
done
The split matters when you are trimming: the first three are required, the four lexicons feed 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.'
inputs, and postcode-us.bin is a ranking channel. What the load costs
prices each one and says what dropping it does.
onnxruntime-web needs its own .wasm runtime files too. Left alone it resolves them relative to
its own module URL, which holds only when your bundler emits those four files beside the JavaScript
it emits. Copy them somewhere you control instead, and tell the runner:
mkdir -p public/ort
cp node_modules/onnxruntime-web/dist/*.wasm public/ort/
Skipping this produces the failure that reads as 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.' problem and is not one. When the resolved
.wasm path is not fetchable the session is never created, and the error names the backend rather
than the file:
Error: no available backend found. ERR: [wasm] TypeError: fetch failed
2. Load the classifier
One call. It fetches the files in parallel, builds the 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., creates the 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. session and runs a warm-up pass before it returns.
import { loadNeuralClassifierFromURLs } from "@mailwoman/neural/web-loader"
const { classifier, diagnostics, labels } = await loadNeuralClassifierFromURLs({
modelURL: "/mailwoman/model.onnx",
tokenizerURL: "/mailwoman/tokenizer.model",
modelCardURL: "/mailwoman/model-card.json",
postcodeBinaryURLs: ["/mailwoman/postcode-us.bin"],
runner: { wasmPathsRoot: "/ort/" },
})
console.log(diagnostics?.backend, labels?.length)
wasm 33
The four lexicons are not in that call because the loader derives their URLs from modelURL — swap
the last path segmentsegmentA punctuation-bounded chunk of the normalized input — the comma-separated parts of 'Portland, OR' — used to give downstream stages structural context., keep the rest — which is why step 1 put them in the same directory. Pass
gazetteerLexiconURL, countryLexiconURL, streetTypeLexiconURL or localitySurfaceLexiconURL
explicitly if yours live elsewhere, or null to skip one.
modelCardURL is the one optional-looking argument that is not optional. The card carries the labelcomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag.
set, and this 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. emits 33 of them. Omit it and the classifier falls back to a built-in 21-labelcomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag.
default, builds a 21×21 transition mask against 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.' emitting 33 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., and the ViterbiViterbi decodingA dynamic programming algorithm that finds the most likely sequence of hidden states (labels) given a sequence of observations (token emissions). Mailwoman uses Viterbi over a linear-chain CRF to produce globally coherent BIO label sequences from per-token model scores. pass
reads past the end of it.
3. Parse something
classifier.parse is the same method the Node runtime exposes, and it returns the same nested
AddressTree.
import type { AddressNode } from "@mailwoman/core/decoder"
const tree = await classifier.parse("1600 pennsylvania ave nw, washington dc 20500")
const print = (node: AddressNode, depth: number): void => {
console.log(`${" ".repeat(depth + 1)}${node.tag} = ${node.value}`)
node.children.forEach((child) => print(child, depth + 1))
}
tree.roots.forEach((root) => print(root, 0))
Three inputs, run in order against one loaded classifier:
1600 pennsylvania ave nw, washington dc 20500 (30 ms)
region = DC
locality = Washington
street = Pennsylvania Ave NW
house_number = 1600
postcode = 20500
10 downing street, london sw1a 2aa (22 ms)
locality = London
street = Downing
house_number = 10
street_suffix = Street
postcode = SW1A 2AA
233 s wacker dr chicago il 60606 (20 ms)
region = IL
locality = Chicago
street = Wacker
house_number = 233
street_prefix = S
street_suffix = DR
postcode = 60606
The indentation is containment, not reading order: the regionregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. contains the localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy., the localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy.
contains 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 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 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. carries its own number, prefix and suffix. That
is why the second input has no region level at all — a British address has no state to nest under —
and the structure is what makes a 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 job tractable later.
Read everything a parse returns walks the same tree with its spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. and
confidences. Everything that page shows is available here; the runner underneath is the only
difference.
All three inputs are lowercase, because that is the registerinput modeThe Decision-A register switch: 'fragmented' (human-typed fragments — feeds the evidence channels) vs 'formatted' (complete records — runs the trained absence identity). Explicit on CLI/API; per-endpoint defaults (batch→formatted, autocomplete→fragmented); kind-derived otherwise. a person types in.
Per-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. cost above is 20–30 ms on the WASM backend, on a warm session. The first 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. after load is not in that range, which is why the loader runs a warm-up 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. before handing the classifier back — that cost is inside step 2's number, not step 3's.
What the load costs
Measured by counting the bytes of every response the loader took, on the call in step 2:
| File | Bytes | What it is | Dropping it |
|---|---|---|---|
model.onnx | 39,419,629 | The int8 graph | Required |
locality-surface-lexicon-v6.json | 7,346,004 | LocalitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. surface forms | LocalitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. evidence channelevidence channelA dedicated model input that injects externally computed per-token features (confidence-scaled, own projection) at the embedding layer: postcode anchor, gazetteer, country, street-type, locality-surface. The clue informs; the model decides (model-first). runs off, with a console error |
postcode-us.bin | 1,904,322 | The US 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. table | Ranking degrades; 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. still work |
tokenizer.model | 1,632,289 | The SentencePieceSentencePieceA language-independent subword tokenizer that splits text into pieces using a unigram language model. Mailwoman uses a SentencePiece tokenizer with a 48,000-token vocabulary and byte-fallback, trained on address data rather than general text. 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.' | Required |
model-card.json | 42,380 | Label setlabel setA model's BIO vocabulary, per-config since CJK Phase 2: stage3 (the Latin 33), stage3-jp (STAGE3 + the seven JP tags = 47, the JP char head), stage4 (the secondary-address family — numerically also 47, a coincidence). A checkpoint persists its own id→label map; label-space mismatches raise instead of collapsing silently. and lineage | Decoding breaks, as step 2 describes |
anchor-lexicon-v1.json | 11,238 | 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. clue | Segmentation degrades, with a console error |
street-type-lexicon-v3.json | 9,882 | StreetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.-type evidence | Fragment 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. degrade, with a console error |
country-surface-lexicon-v1.json | 7,023 | 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.-surface evidence | 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. tagging degrades, with a console error |
| Total | 50,372,767 | About 50.4 MB |
Every "degrades" row prints a console.error naming the missing file when the loaded 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.' declares
the matching input. That is deliberate: 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.' trained with a channel and run without it produces
structurally valid, quality-degraded output, which is the failure mode that hides. Watchnamed watchA known below-target reading recorded at ship with an owner and a retirement condition — never a silent waiver. Example: fr.cedex shipped at 83.3 under the waived floor, named, and retired when the from-scratch base read 90.5. the console
on your first load rather than reading it from 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..
One file is missing from that table because the loader never fetches it: the onnxruntime-web
runtime, which the runtime itself loads. onnxruntime-web ships four builds — 12,528,402 bytes plain,
14,065,792 with JSPI, 22,819,905 with Asyncify, and 25,415,321 for the WebGPU path — and a browser
takes exactly one, chosen from the execution provider and what the browser supports. Which one is not
measurable from Node, where the runtime reads those files off the filesystem rather than over HTTP, so
budget the range and check your own network panel on a first load.
Wall-clock for the same call, cold each time and with no HTTP cache: 1.7 s with the files on
127.0.0.1, and 9.6 s when the same call fetched them across the public internet instead. The
gap between the two is transfer, and it is a property of your link and your hosting. What is left in
the local number is reading 39.4 MB into an 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. session and running the warm-up pass.
Two consequences worth designing around. You serve these files, so an immutable Cache-Control on
them turns every visit after the first into a cache read. And sixty-odd megabytes is a real download
on a phone — gate the load behind the interaction that needs it rather than starting it on first
paint.
Where it runs
WebONNXRunner asks for the webgpu execution provider first and falls back to wasm when the
probe fails, which it does when the browser exposes no adapter. diagnostics.backend reports which
one answered — the string in step 2's output — and runner: { useWebGPU: false } skips the probe
entirely, which is what you want in a test environment where the failure path only adds latency.
Two constraints ride on that:
- The 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. runs on the threadthreadA parallel workstream within a release. Threads compose; they are not sequential milestones like phases. that called it. Nothing here moves 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. to a worker. Session creation reads a 39.4 MB 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.' and each 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 tens of milliseconds; put both in a worker of your own if your page has an animation to keep smooth.
- WebGPU availability is a browser and hardware property, not a configuration one. The fallback
is automatic, so a device without it still 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. — on the slower backend. Log
diagnostics.backendin production if you want to know which half of your traffic gets which.
Resolving in the browser
Components are not coordinates. The demo resolves them by range-loading a 1.65 GB 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.
over HTTP: sql.js-httpvfs fetches only the SQLite pages a lookup touches, which 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.'s own
build notes put at about a dozen range requests per session. That machinery is docs-site code rather
than a published package, and two things stand between it and your page.
The worker is one. sql.js-httpvfs runs SQLite in a Worker, and a Worker cannot be constructed
from a cross-origin script URL, so its worker JS and its .wasm must be served from your own origin
even when the database itself is remote. The demo carries a sqljsBaseURL option for exactly that
reason.
The data is the other. @mailwoman/resolver-wof-wasm is the published browser lookup, and its
loader fetches a whole database and opens it in memory — workable for a slim, purpose-built
distribution, not for the 1.65 GB worldwide one. buildSlimWOFDatabase from
@mailwoman/resolver-wof-sqlite/build-slim is what produces such a distribution: give it a source
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., a 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. set and a localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. cap, and it writes a 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.-schema database sized for a
static deploy.
So the shape that works today is: 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. in the browser, and either resolve against a slim database
you built for your own 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., or send the parsed components to a server that has the full one.
Run the API server is the second half of that arrangement, and its
POST /v1/resolve route takes an already-parsed tree.
How this page was verified
Steps 2 and 3 ran under Node.js 26.2.0 rather than in a browser, against the same onnxruntime-web
build a browser loads and through the same loadNeuralClassifierFromURLs entry point. It is one code
path, not two: the browser runtime's own test suite exercises the WASM execution provider in Node for
the same reason. The 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. output, the labelcomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. count, the byte counts and the timings are therefore
measured. Step 1's file set was copied out of this repository's own 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. workspace, which is what
the npm package publishes, and served over HTTP from a local directory for the step-2 run.
Three claims are not measured here, and each is marked where it appears. WebGPU cannot be exercised
without a browser, so the provider order and the fallback come from
web-onnx-runner.ts.
Which .wasm build a browser takes is a browser decision, and the sizes above are the files on disk.
And the cross-origin behavior of the demo's asset host was checked with a request carrying an Origin
header rather than from a page.
What you have now
An address parser that runs in the tab, from files you serve, with no request per 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. and no key to manage. It reads the same 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.' the CLI and the API server read, so a component it returns is the component they return.
Next
- Read everything a parse returns — the tree, the spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree., the confidences.
- Run the API server — the server half, for the resolve step this page leaves out.
- What ships today — 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.' artifacts, their sizes, and the localeslocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. that carry a claim.