/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * Splits corpus rows into train, val and test by holding out whole places: a random row split leaks by * neighborhood, because the model can memorize a street it saw in train. Rows inside a held-out place * go to val or test 50/50 by a hash of `source_id`; every other row goes to train. * * A holdout change takes effect at the next corpus rebuild. Each versioned corpus keeps the * `SPLIT_MANIFEST.json` it was built with, because adding a holdout to a built corpus would leak rows * the model already trained on. */ import { type PathBuilderLike } from "path-ts"; import type { CanonicalRow, LabeledRow } from "#types"; /** * The name of one corpus split. */ export type SplitName = "train" | "val" | "test"; /** * The component values that identify the places one country holds out. * * Sources represent a place in different components: `usgov-nad` and `tiger` emit `region`, * but BAN emits none, so a French holdout must also match on postcode. * A row is held out when any declared matcher fires. * A policy with no matchers holds out no entry. */ export interface HoldoutPolicy { regions?: readonly string[]; /** * Prefixes matched against `row.components.postcode`; use one only where it identifies * a single place by itself, such as the first two digits of a French postcode. */ postcodePrefixes?: readonly string[]; localities?: readonly string[]; } /** * One country's holdout as a bare region list or a {@link HoldoutPolicy}. * * Older committed `SPLIT_MANIFEST.json` files use a bare array of region values. */ export type CountryHoldout = readonly string[] | HoldoutPolicy; /** * Options for {@link splitRows}. */ export interface SplitOptions { /** * The holdout policy keyed by ISO 3166-1 alpha-2 country code. */ holdouts?: Record; } /** * The `source_id` lists for each split. */ export interface SplitManifest { train: string[]; val: string[]; test: string[]; holdouts: Record; /** * The corpus version, read from the first row that has one. */ corpus_version: string; counts: { train: number; val: number; test: number; total: number; }; } /** * Returns the default holdouts — small, peripheral places in each country. * A change here takes effect at the next base corpus rebuild. */ export declare function defaultHoldouts(): Record; /** * Returns the matchers for one country, reading a bare array as a region list. */ export declare function holdoutPolicyFor(holdout: CountryHoldout | undefined): HoldoutPolicy; type SplitInputRow = Pick; /** * Returns the split for one row. * * Both `splitRows` and the streaming `buildCorpus` loop call this, so every * caller assigns a row to the same split. */ export declare function splitForRow(row: Pick, holdouts?: Record): SplitName; /** * Builds a `SplitManifest` in memory from labeled or canonical rows. * * Tests and small fixtures use this, while `buildCorpus` uses `splitForRow` * and `writeSplitManifestsFromLabeledFiles` so it never holds every row's split in memory. */ export declare function splitRows(rows: Iterable, opts?: SplitOptions): SplitManifest; /** * Returns a deterministic bucket in `0..n-1` for an id, from the first four bytes * of the SHA-256 digest read as a big-endian uint32. */ export declare function hashBucket(id: string, n: number): number; /** * Writes a `SplitManifest` to `/{train,val,test}.txt` (sorted `source_id` values, one per line) * and `SPLIT_MANIFEST.json` (the corpus version, holdouts and counts). */ export declare function writeSplitManifests(manifest: SplitManifest, outputDir: PathBuilderLike): Promise; /** * The `LabeledRow` fields that the split functions read. */ export type SplitInputLabeledRow = Pick; /** * Writes the same files as `writeSplitManifests` by streaming one labeled JSONL file per split. * * `buildCorpus` calls this after its align loop partitions rows with `splitForRow`. * The caller passes the counts to avoid rescanning the files. * `sort(1)` spills to disk, so memory stays constant. */ export declare function writeSplitManifestsFromLabeledFiles(opts: { labeledPaths: Record; outputDir: PathBuilderLike; corpusVersion: string; counts: Record; holdouts?: Record; }): Promise; export {}; //# sourceMappingURL=split.d.ts.map