Skip to main content

Library API

Scope​

This page describes the five entry points a consumer calls from TypeScript: createRuntimePipeline, NeuralAddressClassifier, the geocodinggeocodingThe process of converting an address into geographic coordinates (latitude and longitude). Mailwoman geocodes in a multi-tier cascade: exact address-point match → street interpolation → locality centroid. Each tier is progressively coarser but more widely available. functions and the batchbatch sizeHow many examples the model processes before each parameter update. Larger batches give smoother gradients but cost more memory; gradient accumulation simulates a big batch on a small GPU. iterator in mailwoman/geocode, and createCalibrator. Each section contains a full runnable file and the output that file produced.

It does not describe the stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). packages (@mailwoman/normalize, @mailwoman/query-shape, @mailwoman/locale-hint, @mailwoman/kind-classifier, @mailwoman/phrase-grouper). Those are wired by createRuntimePipeline with production defaults, and a consumer who calls them directly is building a pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. rather than using one. For the command line, see CLI. For HTTP, see HTTP APIs.

Every example below ran under Node 26 against the packages in this repository at the version this page documents. The options tables are a subset: bias-magnitude and decision-threshold knobs that exist to be swept during evaluationevalRunning the model against a held-out golden dataset and computing per-component F1, exact-match, calibration, and resolved-coordinate error. are omitted, and their defaults are the shipped behavior. Where a table is a subset, it states that and lists what it left out.

Import map​

These are the import paths a consumer reaches for. One of them takes a wildcard suffix. On Node the package serves TypeScript source directly, so no build step stands between an installed package and a running script.

ImportWhat it exports
mailwomancreateRuntimePipeline, plus everything @mailwoman/core re-exports
mailwoman/geocodegeocodeAddress, parseForGeocode, USStateDatabaseProvider, geocodeStream, the result types
mailwoman/resolver-backendcreateResolverBackend and resolveCandidateDBPath
@mailwoman/core/data-rootdataRootPath and the other data-root path helpers
mailwoman/cli/kitInk helpers for building an interactive command
mailwoman/test-kitThe parser test helpers
mailwoman/poiThe POI intent stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). and executor
@mailwoman/poi-taxonomy/overpassemitOverpassQL, the OverpassQL export for a matched POIpoint of interest (POI). A named place that is not strictly an address — landmark, transit stop, venue, amenity, or franchise. Mailwoman tags these as venue and resolves them through the gazetteer. intent
mailwoman/gazetteer-pipelineGazetteergazetteerA 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. build internals, plus a wildcard subpath for its modules

geocodeAddress and its result types are reachable only through mailwoman/geocode. They are not re-exported from the bare specifier.

createRuntimePipeline​

function createRuntimePipeline(
opts?: CreateRuntimePipelineOpts
): (raw: string, runOpts?: PipelineOpts) => Promise<PipelineResult>

The factory is synchronous and the returned function is async. Every lazy load — the coarse 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. placer, the gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. index, 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.-morphology matcher, 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.-evidence index — happens on the first call to the returned function rather than in the factory.

Options​

Two stagesstageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). take an injected implementation. The rest have production defaults.

OptionTypeDefaultEffect
classifierAddressClassifiernoneStagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). 3. Without it the pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. runs the structural stagesstageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). only
resolverResolvernoneStagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). 6. Without it the tree has no coordinates
fst"auto", "none" or a matcher"auto"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. emission priorsemission priorA log-probability bias injected into the model's emission logits from an external signal — gazetteer frequency, an FST, a Wikipedia-importance score — combined with the learned weights at decode time.. Loaded from the classifier's 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
streetMorphology"auto", "none" or a matcher"auto"Signal source for 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.-context decision
streetEvidence"auto", "none" or a StreetLocalityEvidence"auto"Reranks 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. on atlas-confirmed evidence. Requires a spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree.-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. 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.'
placeCountry"auto", "none" or a function"auto": the bundled coarse placerA confident countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. guess becomes a soft ranking prior. It never filters
poiQueryKind"extract", "none" or { poiDatabasePath }"extract"Detects a POIpoint of interest (POI). A named place that is not strictly an address — landmark, transit stop, venue, amenity, or franchise. Mailwoman tags these as venue and resolves them through the gazetteer. query and extractsextractA partial output file of the corpus build, written in Parquet format. The training pipeline streams extracts row by row. its intent. The object form also executes it
caseNormalization"title-case" or "preserve""title-case"Title-cases detected all-caps ASCII input before 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.'
placerCountryUse"filter" | "prior""filter""filter" promotes a confident countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. guess to a filter, inside a 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. safelist
hardCountrySafelistReadonlySet<string>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 manifestWhich countries the hard filter applies to. Falls back to a built-in list
detectLocalefunction@mailwoman/locale-hintStagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). 2
classifyKindfunction@mailwoman/kind-classifierStagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). 2.5. An explicit override wins over the POIpoint of interest (POI). A named place that is not strictly an address — landmark, transit stop, venue, amenity, or franchise. Mailwoman tags these as venue and resolves them through the gazetteer.-aware default
groupPhrasesfunction@mailwoman/phrase-grouperStagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). 2.7

A "none" value for fst, streetMorphology, streetEvidence, placeCountry or poiQueryKind suppresses the auto-load. That is how a caller gets output identical to a build without that mechanism. machinePreferences takes the same "auto", "none" or explicit value.

Per-call options​

The second argument to the returned function is PipelineOpts. A per-call value overrides the factory default.

FieldTypeDefaultEffect
localestringderived by locale-hintBCP-47 tag, for example en-US
inputMode"fragmented", "formatted" or "auto""auto": derived from the kindWhich registerinput modeThe Decision-A register switch: 'fragmented' (human-typed fragments — feeds the evidence channels) vs 'formatted' (complete records — runs the trained absence identity). Explicit on CLI/API; per-endpoint defaults (batch→formatted, autocomplete→fragmented); kind-derived otherwise. the evidence channelsevidence 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). run in
resolveOptsResolveOptsnonePassed through to 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.
caseNormalization"title-case" or "preserve"the factory valueOverrides the factory default for this call
placetypePair"inherit", "off" or a prior"inherit"The classifier's placetypeplacetypeThe Who's On First hierarchical classification of places: planet → continent → country → region → county → locality → neighborhood. The resolver uses placetype to rank candidates — an exact locality match outranks a county-level match.-pair prior for this call
placerCountryUse"filter" | "prior"the factory valueOverrides the factory default for this call
forceFullPipelinebooleanoffDisables the structural fast paths. A debugging aid
signalAbortSignalnoneCancels the call

Return shape​

FieldTypeMeaning
inputstringThe raw string as passed
normalizedNormalizedInputLiteStagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). 1 output
queryShapeQueryShapeLiteCharacter classcharacter classA token's character category — digit, alpha, CJK, Cyrillic, Arabic, mixed — used by the query-shape stage as a structural signal for locale and kind inference., segmentation, known-format hits
localeLocaleHintTag, confidence, alternatives, and whether it was detected or given
kindQueryKindResultThe query kindquery kindThe coarse category the kind classifier assigns to the whole input — postcode_only, locality_only, structured_address, intersection, po_box, landmark, or vague — used to route processing., for example structured_address
phraseProposalsPhraseProposal[]StagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). 2.7 proposals. Empty when a fast path skipped the stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone).
treeAddressTreeThe 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.
poiIntentPOIQueryResult or absentPresent only when path is "poi"
timingRecord<string, number>Milliseconds per stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone).
path"fast-path", "full", or "poi"Which route the input took

Example​

import { decodeAsJSON } from "@mailwoman/core/decoder"
import { NeuralAddressClassifier } from "@mailwoman/neural"
import { createRuntimePipeline } from "mailwoman"

const classifier = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" })
const pipeline = createRuntimePipeline({ classifier })
const result = await pipeline("350 5th Ave, New York, NY 10118")

console.log(JSON.stringify(decodeAsJSON(result.tree), null, 2))
console.log(result.kind.kind, "|", result.path, "|", result.locale.locale)

Output:

{
"region": "NY",
"locality": "New York",
"street": "5th",
"house_number": "350",
"street_suffix": "Ave",
"postcode": "10118"
}
structured_address | full | en-US

decodeAsJSON flattens the tree to a tag-to-value object and drops the containment nesting. Read result.tree directly when the nesting matters.

NeuralAddressClassifier​

Reach for the classifier directly in three cases: you need 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. distribution rather than the argmax tree, you are serving several localeslocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. from one process and want to hold each 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.' open, or you are running 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.' in an environment createRuntimePipeline does not fit. For a single 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., the pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. is the shorter path and it applies the structural stagesstageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' was trained beside.

static async loadFromWeights(opts?: {
locale?: string
modelPath?: string
tokenizerPath?: string
modelCardPath?: string
tier?: "server" | "pocket"
cacheRoot?: string
postcodeAnchorLookup?: AnchorLookup
executionProviders?: string[]
intraOpNumThreads?: number
}): Promise<NeuralAddressClassifier>

Resolution runs in one order: an explicit cacheRoot holding both binaries, then explicit paths in opts, then the installed @mailwoman/neural-weights-<locale> package, then the user-level 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. cache that mailwoman parse --download-weights writes, then a single actionable error naming all of them. A package that resolves but ships no binaries fails loudly rather than falling through to the cache — that is the metadata-only checkout trap, and silence there would look like a working install.

The method is Node-only: it imports onnxruntime-node and node:fs dynamically. In a browser, use loadNeuralClassifierFromURLs from @mailwoman/neural/web/loader. Both runtimes are optional peer dependencies, so whichever side you are on, install it yourself: onnxruntime-node on a server, onnxruntime-web in a browser build.

intraOpNumThreads defaults to 4. That value is a cap rather than a core count. Measured over 120 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 2026-08-03: one threadthreadA parallel workstream within a release. Threads compose; they are not sequential milestones like phases. costs 18.3 ms 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., two cost 12.5 ms, four cost 9.2 ms, and all cores cost 9.3 ms — so the cap is free. Pin it to 1 only when you are running several classifier instances in one process and want to bound total threadthreadA parallel workstream within a release. Threads compose; they are not sequential milestones like phases. count, and expect twice the latency.

One classifier instance holds one localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.. Construct one per localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. you serve.

MethodReturnsUse it for
parse(text, opts?)Promise<AddressTree>The nested tree
parseJSON(text, opts?)Promise<Partial<Record<ComponentTag, string>>>A flat tag-to-value object
parseTuples(text, opts?)Promise<Array<[ComponentTag, string]>>Ordered tag/value pairs
parseXML(text, opts?)Promise<string>An XML projection
parseWithLogits(text, opts?)Promise<ParseWithLogitsResult>The tree plus 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. 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 piece offsets
traceParse(text, opts?)Promise<NeuralParseTrace>StagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone).-by-stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). diagnostics

Three readonly properties surface paths and grammar the caller's 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. consumes: fstPath, streetMorphologyPath, and spanGrammar. @mailwoman/neural deliberately contains no 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. dependency, so it reports where the gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. index is and leaves deserialization to the caller. createRuntimePipeline reads all three.

Parse options​

These are the fields of ParseOpts a consumer sets. ParseOpts has 20 fields. The ten omitted here are the 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. bias magnitudes and decision thresholds (fstBiasScale, fstStreetContextRequirement and their siblings, four of which the source marks internal), the queryShapeBiasScale magnitude, the morphology-prior override, the pre-v4.4.0 bridgePunctuationGaps switch, and trailingLocality, which is deprecated and scheduled for deletion at the next major.

FieldTypeDefaultEffect
fstFSTMatcherLikenoneGazetteergazetteerA 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. matches become additive emission biasesadditive biasA logit adjustment added before softmax from a prior or external knowledge source, typically soft-capped so it influences but never overrides the model's prediction. The mechanism behind shallow fusion.
inputMode"fragmented" or "formatted""fragmented"Which registerinput modeThe Decision-A register switch: 'fragmented' (human-typed fragments — feeds the evidence channels) vs 'formatted' (complete records — runs the trained absence identity). Explicit on CLI/API; per-endpoint defaults (batch→formatted, autocomplete→fragmented); kind-derived otherwise. the evidence channelsevidence 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). run in
queryShapeQueryShapeLikenoneKnown-format hits become additive emission biasesadditive biasA logit adjustment added before softmax from a prior or external knowledge source, typically soft-capped so it influences but never overrides the model's prediction. The mechanism behind shallow fusion.
caseNormalization"title-case" or "preserve""title-case"Title-cases detected all-caps ASCII input
calibrateCalibratoroffMaps raw 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. confidence through a calibration table
enforceWordConsistency"off" or WordConsistencyOptsthe shipped settingsPer-word BIO vote, skipping byte-fallback words. {} runs the unthresholded vote
postcodeRepairbooleanoffDeterministic postcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. repair pass
unitRepairbooleanoffDeterministic unitunitA subdivision of a building — apartment, suite, floor — that refines a street address. Mailwoman's unit component; a designator plus identifier forms a subpremise. repair pass
spanProposer"inherit", "auto", "none" or a config"inherit": the classifier's proposerSpanspanA 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.-proposal priors. "auto" uses the default proposer even if the config disabled it
addressSystemConventions"inherit", "off", "auto" or a system code"inherit": from the model cardmodel cardA JSON metadata file (model-card.json) shipped with each weights bundle. It declares the model version, lineage, label set, required inference channels (anchor, gazetteer), calibration data, and training provenance.Which address-system conventions apply
placetypePair"inherit", "off" or PlacetypePairPriorOpts"inherit": 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's pair index"off" disables the prior for the call. A prior object replaces the package value

The table above is the classifier's own defaults, and createRuntimePipeline pins two of them on every call it makes: postcodeRepair: true, and the shipped word-consistency settings. enforceWordConsistency is on either way — the pin only removes the caller's ability to change it mid-pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package.. postcodeRepair is the one that differs: off on a bare classifier call, on through the pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package..

Pass the gazetteer index to a bare call​

fst is the option a bare classifier call has to pass, and the one whose absence is hardest to notice. The gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. index turns 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. match into an additive emission biasadditive biasA logit adjustment added before softmax from a prior or external knowledge source, typically soft-capped so it influences but never overrides the model's prediction. The mechanism behind shallow fusion., and it is what tells 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.' that a bare 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. naming a real place is a localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. rather than a streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.. No other code loads it for you outside createRuntimePipeline: the pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. reads the index out of the classifier's 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 on its first call and passes it to every 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., while a classifier you call directly receives no index at all. geocodeAddress does not wire it either, and GeocodeDeps has no field for it.

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. still succeeds without it. It is a prior rather than a stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone)., so most inputs are unaffected and the failure is silent — which is why this section exists rather than a note on the table row.

Wire it from the path the classifier already resolved. fstPath is optional, because a localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. overlay that ships no gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. index leaves it undefined, so guard it rather than reading it straight into readFile.

import { readFile } from "node:fs/promises"

import { NeuralAddressClassifier } from "@mailwoman/neural"
import { deserializeFST } from "@mailwoman/resolver-wof-sqlite/fst-serialize"

const classifier = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" })

// `fstPath` is optional — a locale overlay that ships no gazetteer index leaves it undefined.
const fst = classifier.fstPath ? deserializeFST(await readFile(classifier.fstPath)) : undefined

for (const input of ["Hollywood", "big spring"]) {
console.log(input)
console.log(" without fst:", JSON.stringify(await classifier.parseJSON(input)))
console.log(" with fst: ", JSON.stringify(await classifier.parseJSON(input, { fst })))
}

Output:

Hollywood
without fst: {"street":"Hollywood"}
with fst: {"locality":"Hollywood"}
big spring
without fst: {"street":"Big","street_suffix":"Spring"}
with fst: {"locality":"Big Spring"}

resolveWeights from @mailwoman/neural/weights returns the same fstPath without constructing a classifier. It is synchronous, so do not await it, and its fstPath is optional for the same reason.

This is the main reason to prefer the pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. for a single 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.: it wires the index, 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.-morphology matcher 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.-evidence rerank, and a bare classifier call gets none of the three.

Resolve coordinates​

mailwoman/geocode turns a string into a coordinate with a resolution tier and an uncertainty radius.

function geocodeAddress(input: string, deps: GeocodeDeps): Promise<GeocodeResult>

geocodeAddress always returns a result. With no coordinate databases wired it returns the admin tier rather than failing. It throws only on a fatal 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. or resolve error, so batchbatch sizeHow many examples the model processes before each parameter update. Larger batches give smoother gradients but cost more memory; gradient accumulation simulates a big batch on a small GPU. callers catch per row.

Dependencies​

GeocodeDeps has 18 fields. The 16 below are the ones a consumer sets; osmExtracts and hardCountrySafelist are omitted as evaluationevalRunning the model against a held-out golden dataset and computing per-component F1, exact-match, calibration, and resolved-coordinate error. and build-time wiring.

FieldTypeDefaultEffect
classifierGeocodeClassifierrequiredThe parser
inputMode"fragmented", "formatted" or "auto""auto": from the query kindquery kindThe coarse category the kind classifier assigns to the whole input — postcode_only, locality_only, structured_address, intersection, po_box, landmark, or vague — used to route processing.Which registerinput modeThe Decision-A register switch: 'fragmented' (human-typed fragments — feeds the evidence channels) vs 'formatted' (complete records — runs the trained absence identity). Explicit on CLI/API; per-endpoint defaults (batch→formatted, autocomplete→fragmented); kind-derived otherwise. the evidence channelsevidence 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). run in
resolverResolverrequiredThe 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. walk
extractsRegionDatabaseResolvernonePer-state rooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. and interpolationinterpolationA geocoding technique that estimates a coordinate along a street segment based on the house number range. Used as the middle tier of Mailwoman's geocode cascade when exact address-point data is unavailable. lookups
nationalExtracts(country) => RegionDatabasesnonePer-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. lookups, for example the French rooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. database
defaultCountry{ country, source: "caller" | "inferred" }noneScopes 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. to one 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.. "inferred" marks a localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. guess that stronger evidence can override
biasproximity pointsnoneSoft re-rank toward a viewport or a user location
interpCalibrationnumber or a tablethe database's valueMultiplier on the interpolationinterpolationA geocoding technique that estimates a coordinate along a street segment based on the house number range. Used as the middle tier of Mailwoman's geocode cascade when exact address-point data is unavailable. tier's uncertainty radius
caseNormalization"title-case" or "preserve""title-case"Title-cases detected all-caps input
normalizeInputbooleanonRuns the normalizenormalizeStage 1 of the runtime pipeline: deterministic input preprocessing (Unicode NFC, punctuation normalization, whitespace collapse). Returns a NormalizedInput with an offsetMap that maps normalized positions back to the raw input. stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone).
placeCountry"auto", "none" or a function"auto": the bundled placerSoft countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. prior
placerCountryUse"filter" | "prior""filter""filter" hard-filters inside the 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. safelist
adminCoherencebooleanonJoint admin-consistency re-pick
postcodeCountryPriorbooleanonPostcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. shape informs 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.
parsedTreeAddressTreenoneSkips 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. when you already have the tree

Resolution tiers​

The tier states which artifact produced the coordinate, best first. Condition any house-grade rendering on the tier rather than on the presence of house_number: the parsed 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. is populated whatever tier answered.

TierCoordinate sourceuncertainty_m
address_pointRooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. or parcelparcelA property polygon or record carrying a situs (site) address and often a separate owner mailing address. County GIS parcel aggregations are a training source for address-point variety and situs-vs-owner divergence. centroidA small floor, about 1 m
interpolatedHouse-number estimate along a streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.The calibrated bracket 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.
streetStreetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. centroid for a streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. queryHalf 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. bounding-box diagonal
adminAdmin centroid from 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.null — no sub-localitydependent localityA sub-locality (neighborhood or borough) hierarchically inside a larger locality — e.g. Brooklyn within New York City. Provides finer geographic specification below the primary locality. estimate exists

Result​

FieldTypeMeaning
inputstringThe raw string as passed
lat, lonnumber or nullThe resolved coordinate
resolution_tierResolutionTierWhich tier produced it
uncertainty_mnumber or nullRadius in meters. null on the admin tier
localitystring or nullParsed localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. 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.
regionstring or nullParsed regionregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality. 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.
postcodestring or nullParsed postcodepostcodeThe country-specific postcode (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.
house_numberstring or nullParsed house numberhouse numberThe numeric or alphanumeric identifier of a building on a street. Mailwoman's house_number component; its position relative to the street name flips between locales., whatever the tier
streetstring or nullParsed streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels., reassembled from prefix, base and suffix
venuestring or nullParsed venuevenueA named, non-address place — a business, building, park, or stadium. Mailwoman's free-text point-of-interest component, added as a Tier 2 fine label. 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.
dependent_localitystring or nullParsed sub-localitydependent localityA sub-locality (neighborhood or borough) hierarchically inside a larger locality — e.g. Brooklyn within New York City. Provides finer geographic specification below the primary locality. 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.
countryCodestring or nullISO 3166 alpha-2 of the deepest resolved node
hierarchyarray, most specific firstThe resolved admin chain, each with a name and 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. place ID
candidatesarray, winner firstRanked alternatives for the primary place

hierarchy is the resolved view and contains only nodes the resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. decorated. The flat 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. fields are the parsed view. The two disagree whenever 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. found something 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. did not.

USStateDatabaseProvider​

USStateDatabaseProvider opens per-state rooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. and interpolationinterpolationA geocoding technique that estimates a coordinate along a street segment based on the house number range. Used as the middle tier of Mailwoman's geocode cascade when exact address-point data is unavailable. databases on demand, caches the handles, and swaps them atomically when the data release changes. It implements the RegionDatabaseProvider interface from @mailwoman/core/resolver, which the per-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. providers in @mailwoman/ban and @mailwoman/osm share.

class USStateDatabaseProvider implements RegionDatabaseProvider {
static create(factory: RegionDatabaseFactory, dataRoot: PathBuilderLike): Promise<USStateDatabaseProvider>
readonly for: RegionDatabaseResolver
versions(): DataReleaseManifest | null
reload(): Promise<DataReleaseManifest | null>
close(): void
[Symbol.dispose](): void
}

The constructor is private; create reads the release manifest and warms the path map before it returns. Its arguments are positional. factory is the @mailwoman/resolver-wof-sqlite module namespace in practice. for is a property rather than a method so it can be passed unbound as deps.extracts.

Example​

This file resolves against a downloaded candidate.db with no streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. databases wired, so it answers on the admin tier. It also runs without 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. emission priorsemission priorA log-probability bias injected into the model's emission logits from an external signal — gazetteer frequency, an FST, a Wikipedia-importance score — combined with the learned weights at decode time.: geocodeAddress never wires the index, and GeocodeDeps has no field for it — see Wiring the gazetteer index on a bare call.

import { NeuralAddressClassifier } from "@mailwoman/neural"
import { createWOFResolver } from "@mailwoman/resolver"
import { WOFCandidateTableLookup } from "@mailwoman/resolver-wof-sqlite"
import { geocodeAddress } from "mailwoman/geocode"

const classifier = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" })
// Replace <CANDIDATE_DB> with the path `mailwoman data pull candidate` printed.
using lookup = new WOFCandidateTableLookup({ databasePath: "<CANDIDATE_DB>" })
const resolver = createWOFResolver(lookup)

const result = await geocodeAddress("350 5th Ave, New York, NY 10118", { classifier, resolver })

console.log(JSON.stringify(result, null, 2))

Output:

{
"input": "350 5th Ave, New York, NY 10118",
"lat": 40.694457,
"lon": -73.93045,
"resolution_tier": "admin",
"epistemic_status": "observed",
"uncertainty_m": null,
"locality": "New York",
"region": "NY",
"postcode": "10118",
"house_number": "350",
"street": "5th Ave",
"venue": null,
"dependent_locality": null,
"countryCode": "US",
"hierarchy": [
{
"tag": "locality",
"value": "New York",
"name": "New York",
"lat": 40.694457,
"lon": -73.93045,
"placeID": "wof:85977539"
},
{
"tag": "region",
"value": "NY",
"name": "New York",
"lat": 42.921227,
"lon": -75.596537,
"placeID": "wof:85688543"
}
],
"candidates": [
{
"name": "New York",
"tag": "locality",
"lat": 40.694457,
"lon": -73.93045,
"countryCode": "US",
"placeID": "wof:85977539"
}
]
}

Batch​

function geocodeStream(
records: AsyncIterable<SourceRecord> | Iterable<SourceRecord>,
opts: GeocodeStreamOptions
): AsyncIterableIterator<SourceRecord>

geocodeStream runs a worker pool over a record stream and yields enriched records in completion order rather than input order. It 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. once per row and shares the tree between the returned components and the geocode.

OptionTypeDefaultEffect
mappingColumnMappingrequiredWhich columns hold the address
geocodeGeocodeStreamConfigrequiredwofDBPath, dataRoot, locale, country
concurrencynumberMath.min(4, availableParallelism())Worker count
batchSizenumber32Records handed to a worker at a time
workerstring or URLthe bundled workerA replacement worker entry point

One constraint decides whether this function fits your setup. Its worker constructs a WOFSQLitePlaceLookup directly, so it resolves against a full Who's On FirstWOF (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. SQLite distribution and cannot use a candidate.db. If your setup is the candidate.db one the tutorials teach, run your own pool over geocodeAddress instead — Batch geocode at volume has that loop.

Concurrency is low on purpose. A measured sweep over a single 4 GB database on a 16-core host peaked at two workers, about 1.4 times baseline, and degraded above that.

Confidence​

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. confidences from the shipped 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.' are under-confident. createCalibrator builds the mapping that corrects them.

function createCalibrator(table: CalibrationTable | CalibrationBin[]): Calibrator
type Calibrator = (rawConfidence: number) => number

The returned function clamps its input to the range 0 to 1, mapping a non-numeric input to 0. Below the first bin center and above the last it returns that bin's calibrated value. Between two centers it interpolates linearly. It is not a nearest-bin lookup, and it does not return the input unchanged anywhere.

The table ships inside each 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 as calibration.json, and a per-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. sibling ships as calibration-per-locale.json. The per-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. file has no top-level table key, so pass one of its tables entries to the bare-array form.

import { readFile } from "node:fs/promises"

import { createCalibrator } from "@mailwoman/core/decoder"

// Replace <WEIGHTS_DIR> with your node_modules/@mailwoman/neural-weights-en-us directory.
const table = JSON.parse(await readFile("<WEIGHTS_DIR>/calibration.json", "utf8"))
const calibrate = createCalibrator(table)

for (const raw of [0, 0.25, 0.5, 0.75, 0.9, 0.99, 1]) {
console.log(raw.toFixed(2), "->", calibrate(raw).toFixed(4))
}

Output:

0.00 -> 0.0444
0.25 -> 0.6341
0.50 -> 0.8258
0.75 -> 0.9354
0.90 -> 0.9631
0.99 -> 0.9908
1.00 -> 0.9908

A raw 0.50 becomes 0.83 after calibration. That gap is the under-confidence this table corrects. The curve saturates at 0.9908, the top bin's calibrated value, so a calibrated score never reaches 1.

Pass the calibrator 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. as ParseOpts.calibrate. It is opt-in: omitting it leaves the raw softmaxsoftmaxThe function that converts a vector of logits into a probability distribution summing to 1, applied after priors and biases are added to the emission logits. confidences. Those are the byte-stable default.

Errors​

ConditionWhat happensNext step
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 for a localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. is absentloadFromWeights throws one actionable error naming the packagenpm install @mailwoman/neural-weights-<locale>
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 resolves but 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.' fails to loadloadFromWeights throws with the underlying error preservedReinstall the package. A partial or truncated 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. is the usual cause
A model cardmodel cardA JSON metadata file (model-card.json) shipped with each weights bundle. It declares the model version, lineage, label set, required inference channels (anchor, gazetteer), calibration data, and training provenance. declares a channel the package does not shipThe classifier warns once and runs that channel offReinstall. A soft-fed channel changes accuracy rather than correctness
createRuntimePipeline has no classifierThe pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. runs the structural stagesstageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). only; tree may be emptyPass a classifier
createRuntimePipeline has no resolverThe tree has no coordinatesPass a createWOFResolver instance
The gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. index fails to deserializeA warning on stderr, and 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 without 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. priorsReinstall 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
createCalibrator gets an empty tableThrows createCalibrator: empty calibration tablePass the parsed calibration.json rather than an empty array
geocodeAddress hits a fatal 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. or resolve errorThrowsCatch per row. Every non-fatal case returns a result on the admin tier

Rationale​

The classifier 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. are the two stagesstageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). with no default. The omission is deliberate rather than unfinished. 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.' is a 39 MB download and the gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. is 2.88 GB. A factory that acquired either implicitly would make import "mailwoman" an unpredictable amount of disk and network for a caller who wanted 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. one string.

Everything else defaults on. Each mechanism that reached default-on cleared an evaluationevalRunning the model against a held-out golden dataset and computing per-component F1, exact-match, calibration, and resolved-coordinate error. against the shipped 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.' on the first-class localeslocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for., so the shipped defaults are the measured configuration and a deviation from them is the thing that needs justifying.

false rather than omission is the disable signal for the auto-loading options because omission has to keep meaning "give me the default". A caller who needs byte-identical output against a build without a mechanism has one unambiguous way to say so.

See also​

  • CLI — the same pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. behind a command.
  • Component tags — what each tag in 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. means.
  • Runtime flags — the environment variables these functions read.
  • Understand a parse — the same calls, walked through.
  • Tune confidence thresholds — using the calibrator against your own data.