/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * `NeuralAddressClassifier` ties together the tokenizer, the ONNX inference runner, and the * `@mailwoman/core` decoder. Single user-facing entrypoint: `parse(text)` returns an * `AddressTree` ready for projection into JSON / tuple / XML. * * Convenience wrappers `parseJSON` / `parseTuples` / `parseXML` project the tree on the way out. */ import { decodeAsXML, type AddressTree, type ComponentTag, type SerializeJSONOpts, type SerializeTuplesOpts, type UnknownSpan } from "@mailwoman/core/decoder"; import { type InferResult } from "#onnx-runner"; import { type AnchorLookup } from "./anchor-inference.ts"; import type { NeuralAddressClassifierConfig, ParseOpts, ParseWithLogitsResult } from "./classifier-options.ts"; import { type SemiCRFTransitions } from "./semi-markov-decode.ts"; import type { NeuralParseTrace } from "./trace.ts"; import type { ResolveWeightsOpts } from "./weights.ts"; export type { NeuralAddressClassifierConfig, ParseOpts, ParseWithLogitsResult, SpanProposerConfig, } from "./classifier-options.ts"; /** * Structural type the classifier needs from a runner. Lets callers swap the Node-side `ONNXRunner` for a browser-side * runner (e.g. `@mailwoman/neural-web`'s `WebONNXRunner`) without inheritance — the classifier only ever calls * `infer(ids)`. */ export interface NeuralRunner { infer(tokenIDs: number[], anchor?: { features: ReadonlyArray>; confidence: ReadonlyArray; }, gazetteer?: { features: ReadonlyArray>; confidence: ReadonlyArray; }, country?: { features: ReadonlyArray>; confidence: ReadonlyArray; }, evidence?: { streetType?: { features: ReadonlyArray>; confidence: ReadonlyArray; }; localitySurface?: { features: ReadonlyArray>; confidence: ReadonlyArray; }; }): Promise; } export declare class NeuralAddressClassifier { #private; private readonly labels; private readonly decodeMode; private readonly transitions; private readonly startTransitions; private readonly endTransitions; private readonly cfg; constructor(cfg: NeuralAddressClassifierConfig); /** * The parsed semi-Markov segment-transition grammar (`semi-crf-transitions.json`), when the loaded bundle shipped it. * Consumed by the #727 phase-4c k-best name-evidence rerank; `undefined` on a pre-v3 (span-less) bundle. */ get spanGrammar(): SemiCRFTransitions | undefined; /** * Path to the per-locale FST gazetteer binary (`fst-.bin`) when the resolved weights package shipped one, * else `undefined`. The runtime pipeline deserializes + auto-wires it as the default `opts.fst` (opt out with `fst: * false` at pipeline construction); direct `classifier.parse` callers can do the same or pass their own. */ get fstPath(): string | undefined; /** * Path to the locale-general street-morphology FST (`fst-street-morphology.bin`) when the resolved weights package * (or its base) shipped one, else `undefined`. The runtime pipeline's street-context gate (#1315) deserializes it * through the shared loader ladder instead of rebuilding from the libpostal dictionaries per process. */ get streetMorphologyPath(): string | undefined; /** * The `model.onnx` this instance loaded, and which rung of the resolution ladder produced it. * * `undefined` on an instance built through the plain constructor rather than {@link loadFromWeights} — there was no * resolution, so there is nothing to report, which is absence and not an unknown model. */ get resolvedWeights(): { modelPath: string; source: string; } | undefined; /** * The default-ON Stage 2.7 config: codex lexicon (us/au/nz), frozen measured scales (the prior builder's own * defaults). Built once per instance, only when a parse actually needs it. */ private defaultProposer; /** * One-call factory that resolves the weights package (or explicit paths), loads the tokenizer and ONNX runner, and * returns a ready-to-use classifier. * * Resolution order: explicit paths in `opts` → `@mailwoman/neural-weights-` package → throws a single * actionable error. * * **Node-only.** The dynamic imports keep `ONNXRunner` (onnxruntime-node) + `resolveWeights` (uses Node fs) out of * the static dependency graph, so this file can be bundled for the browser by `@mailwoman/neural-web`. Calling this * method in a browser will throw at runtime — use `loadNeuralClassifierFromURLs` from `@mailwoman/neural-web` * instead. */ static loadFromWeights(opts?: ResolveWeightsOpts & { postcodeAnchorLookup?: AnchorLookup; executionProviders?: string[]; intraOpNumThreads?: number; /** * Explicit `placetype-census-.bin` path, overriding the build-local data-root lookup (`loadPlacetypeCensus`). * For a harness that built a census to a scratch directory — the data root is read-only on the lab host, so * "build it and point at it" is the only way to exercise a FRESH artifact. A wrong-country file is still refused * by the loader's header gate. */ placetypeCensusPath?: string; }): Promise; /** * Tokenize → infer → Viterbi (or argmax) → decoder tree. */ parse(text: string, opts?: ParseOpts): Promise; /** * Like `parse`, but also returns the raw per-token logits and piece offsets needed for per-span logit aggregation * (Option C joint-reconcile integration). Shares the ENTIRE decode path with `parse` (one `#decode`, #481) — repair * passes included, because reconcile must consume the same tokens the argmax path serves users, under the same repair * opts. `logits` stay RAW (pre-prior, pre-repair) — they are the model's emissions, not the decode's opinions. */ parseWithLogits(text: string, opts?: ParseOpts): Promise; /** * Like `parse`, but returns the full decode-path trace instead of a tree: pieces, soft-feature channels as fed, raw * logits, locale head, prior participation, post-prior emissions, viterbi path, repair diffs, and the final tokens. * Shares the ENTIRE decode path with `parse` (one `#decode`, #481) and mirrors `parse`'s case normalization, so * `buildAddressTree(trace.text, trace.tokens)` reproduces `parse(text)`'s tree exactly — modulo `opts.calibrate`, * which `parse` forwards into the tree build to recalibrate node confidences and which the trace does not carry * (tokens/labels/spans still match; re-pass the calibrator to the rebuild if calibrated confidences matter). * Serializable by construction — see `./trace.js` for the schema and the spec reference. */ traceParse(text: string, opts?: ParseOpts): Promise; parseJSON(text: string, opts?: ParseOpts): Promise>>; parseJSON(text: string, opts: ParseOpts & SerializeJSONOpts): Promise> & { unknown?: UnknownSpan[]; }>; parseTuples(text: string, opts?: ParseOpts): Promise>; parseTuples(text: string, opts: ParseOpts & SerializeTuplesOpts): Promise>; parseXML(text: string, opts?: ParseOpts & { xml?: Parameters[1]; }): Promise; /** * Guard against a silent label/emission shape overrun. When the model emits MORE logits per token than the configured * label vocabulary (e.g. a Stage 3 bundle loaded with the default Stage 2 labels), viterbi indexes past the * transition matrix and dies with an opaque `Cannot read properties of undefined (reading '0')`. Fail fast here with * a message that names the contract the caller violated. * * The opposite shape (model narrower than labels) is intentionally permitted — STAGE2_BIO_LABELS prefix-extends * STAGE1_BIO_LABELS so a Stage 1 model loaded with Stage 2 labels decodes correctly via the first 15 logits. See * labels.ts for the contract. */ private assertEmissionWidth; } //# sourceMappingURL=classifier.d.ts.map