/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * #727 stage-2 Phase 3 — the k-best semi-Markov segment decode, JS side. * * The counterpart to `corpus-python`'s `SemiMarkovCRF.decode`: the model scores every span up to * `maxSpan` tokens per segment type (the `span_scores` ONNX output), a segment-level transition * table carries the address grammar, and this decodes whole SEGMENTATIONS — scoring "these k tokens * are ONE street" as a single decision rather than letting it emerge from independent token votes. * * Deliberately OUTSIDE the ONNX graph (the Phase-2 design): span enumeration + this DP need dynamic * shapes, which the graph can't express cheaply and the browser shouldn't pay for. Fetching the * scores costs ~0.75ms (CPU, S=128); this decode runs over the pruned candidate set. * * K-BEST, not 1-best, from day one: the whole point of the arc is a LIST of hypotheses with * comparable scores for the resolver to rerank (a rank-2 parse that resolves to a real place beats * a rank-1 that resolves to a country centroid). Scores within one input share the partition * function, so they are directly comparable; ACROSS inputs they are not (that needs the Phase-4 * isotonic pass). * * The segment-type axis is NEVER hardcoded here — it arrives from the weights bundle's * `semi-crf-transitions.json` (the PLACETYPE_ORDER dual-maintenance class: a retrained head that * reorders types would otherwise silently mislabel every decode). */ /** * The decode-time transition grammar, as shipped in `semi-crf-transitions.json`. */ export interface SemiCRFTransitions { /** * Segment-type axis, index-aligned with the `span_scores` inner dim. Index 0 is always `O`. */ segmentTypes: string[]; /** * Max span length in tokens — the `L` axis of `span_scores`. */ maxSpan: number; /** * `transitions[from][to]` — additive score for a `from`→`to` segment-type transition. */ transitions: number[][]; /** * `startTransitions[t]` — additive score for a segmentation whose FIRST segment is type `t`. */ startTransitions: number[]; /** * `endTransitions[t]` — additive score for a segmentation whose LAST segment is type `t`. */ endTransitions: number[]; } /** * One decoded segment: tokens `[start, start + length)` carry type `segmentTypes[typeID]`. */ export interface DecodedSegment { start: number; length: number; typeID: number; } /** * One whole-segmentation hypothesis. `score` is comparable to its siblings from the SAME input. */ export interface SegmentationHypothesis { score: number; segments: DecodedSegment[]; } /** * Parse the `semi-crf-transitions.json` sidecar. Throws on a shape mismatch rather than decoding with a half-valid * grammar — a silently-wrong transition table trains nothing but corrupts every decode. */ export declare function parseSemiCRFTransitions(raw: unknown): SemiCRFTransitions; /** * K-best semi-Markov decode over `spanScores`. * * `spanScores[i][l][t]` scores the segment starting at token `i`, of length `l + 1`, typed `t` — the exact layout of * the `span_scores` ONNX output. `O` segments are length 1 by construction (every non-entity token is its own `O`), * which keeps the state space small and matches the training-side DP that produced the scores. * * State = (token index, last non-O segment type); the top-`k` paths are kept per state. Returns up to `k` complete * segmentations, best first. Every returned segmentation covers `[0, seqLen)` exactly — no gaps, no overlaps. */ export declare function decodeSegmentationsKBest(spanScores: number[][][], seqLen: number, grammar: SemiCRFTransitions, k?: number): SegmentationHypothesis[]; //# sourceMappingURL=semi-markov-decode.d.ts.map