@mailwoman/corpus 7.2.0 → 7.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +59 -27
- package/src/adapter.ts +153 -0
- package/src/adapters/ban/adapter.ts +189 -0
- package/src/adapters/ban/street-decompose.ts +98 -0
- package/src/adapters/fcc-bdc/adapter.ts +188 -0
- package/src/adapters/geonames/adapter.ts +185 -0
- package/src/adapters/geonames-postal/adapter.ts +111 -0
- package/src/adapters/gnaf/adapter.ts +139 -0
- package/src/adapters/gnaf/assemble.ts +200 -0
- package/src/adapters/index.ts +135 -0
- package/src/adapters/openaddresses/adapter.ts +237 -0
- package/src/adapters/overture/adapter.ts +149 -0
- package/src/adapters/state-hi-schools/adapter.ts +171 -0
- package/src/adapters/state-ia-contractors/adapter.ts +148 -0
- package/src/adapters/state-ny-notaries/adapter.ts +169 -0
- package/src/adapters/state-tx-notaries/adapter.ts +160 -0
- package/src/adapters/synth-po-box/adapter.ts +197 -0
- package/src/adapters/tiger/adapter.ts +232 -0
- package/src/adapters/tiger/street-decompose.ts +120 -0
- package/src/adapters/usgov-hrsa-fqhc/adapter.ts +189 -0
- package/src/adapters/usgov-imls-pls/adapter.ts +152 -0
- package/src/adapters/usgov-irs-bmf/adapter.ts +155 -0
- package/src/adapters/usgov-nad/adapter.ts +338 -0
- package/src/adapters/usgov-nppes/adapter.ts +169 -0
- package/src/adapters/usgov-samhsa-treatment-locator/adapter.ts +211 -0
- package/src/adapters/wof-admin-jp/adapter.ts +176 -0
- package/src/adapters/wof-admin-json/adapter.ts +280 -0
- package/src/adapters/wof-postalcode-json/adapter.ts +209 -0
- package/src/align.ts +317 -0
- package/src/build.ts +348 -0
- package/src/codex/us-fips-state.ts +109 -0
- package/src/format.ts +14 -0
- package/src/golden.ts +147 -0
- package/src/index.ts +28 -0
- package/src/license.ts +48 -0
- package/src/parquet-wrapper/index.ts +9 -0
- package/src/parquet-wrapper/reader.ts +67 -0
- package/src/parquet-wrapper/schema.ts +80 -0
- package/src/parquet-wrapper/writer.ts +102 -0
- package/src/parquet.ts +360 -0
- package/src/runner.ts +283 -0
- package/src/shard-recipes/anchor-absorption.ts +86 -0
- package/src/shard-recipes/boundary-stress.ts +87 -0
- package/src/shard-recipes/country-balanced.ts +471 -0
- package/src/shard-recipes/cz-pcfirst-preposition.ts +83 -0
- package/src/shard-recipes/fr-admin-split.ts +212 -0
- package/src/shard-recipes/fr-bare-street.ts +85 -0
- package/src/shard-recipes/fr-fragment.ts +304 -0
- package/src/shard-recipes/fr-order.ts +283 -0
- package/src/shard-recipes/german.ts +206 -0
- package/src/shard-recipes/house-venue.ts +78 -0
- package/src/shard-recipes/index.ts +76 -0
- package/src/shard-recipes/intersection.ts +617 -0
- package/src/shard-recipes/locale.ts +415 -0
- package/src/shard-recipes/nl-postcode.ts +105 -0
- package/src/shard-recipes/no-fragment.ts +206 -0
- package/src/shard-recipes/no-street-led.ts +130 -0
- package/src/shard-recipes/no-street.ts +78 -0
- package/src/shard-recipes/po-box-cedex.ts +853 -0
- package/src/shard-recipes/po-box.ts +111 -0
- package/src/shard-recipes/scaffold.ts +187 -0
- package/src/shard-recipes/si-bare-village.ts +88 -0
- package/src/shard-recipes/street-affix.ts +549 -0
- package/src/shard-recipes/street-bare.ts +90 -0
- package/src/shard-recipes/street.ts +74 -0
- package/src/shard-recipes/unit.ts +315 -0
- package/src/split.ts +251 -0
- package/src/synthesize-anchor-absorption.ts +263 -0
- package/src/synthesize-boundary-stress.ts +504 -0
- package/src/synthesize-german.ts +227 -0
- package/src/synthesize-house-venue.ts +192 -0
- package/src/synthesize-intersection.ts +205 -0
- package/src/synthesize-no-street.ts +341 -0
- package/src/synthesize-po-box.ts +307 -0
- package/src/synthesize-street.ts +264 -0
- package/src/synthesize.ts +872 -0
- package/src/tokenize.ts +68 -0
- package/src/tools/align-shard.ts +67 -0
- package/src/tools/audit.ts +352 -0
- package/src/tools/corpus-stats.ts +183 -0
- package/src/tools/fetch/ban.ts +288 -0
- package/src/tools/fetch/download.ts +119 -0
- package/src/tools/fetch/hrsa.ts +65 -0
- package/src/tools/fetch/imls-pls.ts +162 -0
- package/src/tools/fetch/index.ts +121 -0
- package/src/tools/fetch/nad.ts +304 -0
- package/src/tools/fetch/nppes.ts +177 -0
- package/src/tools/fetch/openaddresses.ts +380 -0
- package/src/tools/fetch/state-hi-schools.ts +217 -0
- package/src/tools/fetch/state-sources.ts +142 -0
- package/src/tools/fetch/tiger-full.ts +318 -0
- package/src/tools/golden-expand.ts +524 -0
- package/src/tools/golden-promote.ts +304 -0
- package/src/tools/index.ts +24 -0
- package/src/tools/ingest-csv.ts +420 -0
- package/src/tools/jsonl-to-parquet.ts +200 -0
- package/src/tools/lint-shard-vocab.ts +357 -0
- package/src/tools/lint-shard.ts +502 -0
- package/src/tools/overlay-manifest.ts +141 -0
- package/src/tools/shard-kryptonite.ts +131 -0
- package/src/tools/shard-translit.ts +244 -0
- package/src/types.ts +213 -0
- package/src/wof-json.ts +236 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Street-decomposition synthesizer for Stage 3 training. Generates address rows where
|
|
7
|
+
* `street_prefix`, `street`, and `street_suffix` are emitted as separate BIO spans (instead of
|
|
8
|
+
* monolithic `street`). Mirrors the PO box synthesizer pattern.
|
|
9
|
+
*
|
|
10
|
+
* Why this exists: TIGER/NAD/BAN adapter changes (committed earlier tonight) emit decomposed
|
|
11
|
+
* components from raw source data, but the v0.4.0 parquet shards on Modal were built BEFORE those
|
|
12
|
+
* changes. Rebuilding the full corpus requires downloading raw TIGER/NAD/BAN data and re-running
|
|
13
|
+
* adapters end-to-end — out of scope for a single night shift. This synthesizer takes (locality,
|
|
14
|
+
* region, postcode) tuples and produces freshly-decomposed Stage 3 training rows, same shape as
|
|
15
|
+
* the PO box pipeline.
|
|
16
|
+
*
|
|
17
|
+
* Note: uses the SAME decomposition logic as TIGER's `decomposeStreet()` so the synthetic
|
|
18
|
+
* distribution matches what the model would see if/when TIGER shards are rebuilt with the new
|
|
19
|
+
* adapter.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { decomposeStreet } from "./adapters/tiger/street-decompose.ts"
|
|
23
|
+
import type { CanonicalRow } from "./types.ts"
|
|
24
|
+
|
|
25
|
+
// Hand-curated US street name pool. Real frequency-weighted street names — sampled
|
|
26
|
+
// from US Census TIGER 2024 top-1000 by occurrence count. Keep ~50 entries so the
|
|
27
|
+
// synthesis distribution doesn't overfit to a tiny vocabulary.
|
|
28
|
+
const STREET_NAMES = [
|
|
29
|
+
"Main",
|
|
30
|
+
"Oak",
|
|
31
|
+
"Maple",
|
|
32
|
+
"Pine",
|
|
33
|
+
"Cedar",
|
|
34
|
+
"Elm",
|
|
35
|
+
"Washington",
|
|
36
|
+
"Lincoln",
|
|
37
|
+
"Jefferson",
|
|
38
|
+
"Park",
|
|
39
|
+
"Lake",
|
|
40
|
+
"Hill",
|
|
41
|
+
"Spring",
|
|
42
|
+
"Center",
|
|
43
|
+
"Church",
|
|
44
|
+
"Mill",
|
|
45
|
+
"School",
|
|
46
|
+
"River",
|
|
47
|
+
"Highland",
|
|
48
|
+
"Sunset",
|
|
49
|
+
"Forest",
|
|
50
|
+
"Meadow",
|
|
51
|
+
"Ridge",
|
|
52
|
+
"Valley",
|
|
53
|
+
"Lakeview",
|
|
54
|
+
"Hillcrest",
|
|
55
|
+
"1st",
|
|
56
|
+
"2nd",
|
|
57
|
+
"3rd",
|
|
58
|
+
"4th",
|
|
59
|
+
"5th",
|
|
60
|
+
"6th",
|
|
61
|
+
"7th",
|
|
62
|
+
"8th",
|
|
63
|
+
"9th",
|
|
64
|
+
"10th",
|
|
65
|
+
"Adams",
|
|
66
|
+
"Madison",
|
|
67
|
+
"Monroe",
|
|
68
|
+
"Jackson",
|
|
69
|
+
"Franklin",
|
|
70
|
+
"Kennedy",
|
|
71
|
+
"Roosevelt",
|
|
72
|
+
"Broadway",
|
|
73
|
+
"Market",
|
|
74
|
+
"Commerce",
|
|
75
|
+
"Industrial",
|
|
76
|
+
"Airport",
|
|
77
|
+
"Hospital",
|
|
78
|
+
"Sherman",
|
|
79
|
+
"Grant",
|
|
80
|
+
"Lee",
|
|
81
|
+
"Custer",
|
|
82
|
+
"Lewis",
|
|
83
|
+
"Clark",
|
|
84
|
+
] as const
|
|
85
|
+
|
|
86
|
+
const STREET_SUFFIXES = [
|
|
87
|
+
"St",
|
|
88
|
+
"Street",
|
|
89
|
+
"Ave",
|
|
90
|
+
"Avenue",
|
|
91
|
+
"Rd",
|
|
92
|
+
"Road",
|
|
93
|
+
"Blvd",
|
|
94
|
+
"Boulevard",
|
|
95
|
+
"Dr",
|
|
96
|
+
"Drive",
|
|
97
|
+
"Ln",
|
|
98
|
+
"Lane",
|
|
99
|
+
"Way",
|
|
100
|
+
"Ct",
|
|
101
|
+
"Court",
|
|
102
|
+
"Pl",
|
|
103
|
+
"Place",
|
|
104
|
+
"Pkwy",
|
|
105
|
+
"Parkway",
|
|
106
|
+
"Ter",
|
|
107
|
+
"Terrace",
|
|
108
|
+
"Cir",
|
|
109
|
+
"Circle",
|
|
110
|
+
"Hwy",
|
|
111
|
+
"Highway",
|
|
112
|
+
] as const
|
|
113
|
+
|
|
114
|
+
const DIRECTIONAL_PREFIXES = [
|
|
115
|
+
"",
|
|
116
|
+
"",
|
|
117
|
+
"",
|
|
118
|
+
"",
|
|
119
|
+
"", // 5 empty entries → 50% no prefix
|
|
120
|
+
"N",
|
|
121
|
+
"S",
|
|
122
|
+
"E",
|
|
123
|
+
"W",
|
|
124
|
+
"NE",
|
|
125
|
+
"NW",
|
|
126
|
+
"SE",
|
|
127
|
+
"SW",
|
|
128
|
+
"North",
|
|
129
|
+
"South",
|
|
130
|
+
"East",
|
|
131
|
+
"West",
|
|
132
|
+
] as const
|
|
133
|
+
|
|
134
|
+
const TRAILING_DIRECTIONALS = [
|
|
135
|
+
"",
|
|
136
|
+
"",
|
|
137
|
+
"",
|
|
138
|
+
"",
|
|
139
|
+
"",
|
|
140
|
+
"",
|
|
141
|
+
"",
|
|
142
|
+
"", // 8 empty → 80% no trailing
|
|
143
|
+
"N",
|
|
144
|
+
"S",
|
|
145
|
+
"E",
|
|
146
|
+
"W",
|
|
147
|
+
"NE",
|
|
148
|
+
"NW",
|
|
149
|
+
"SE",
|
|
150
|
+
"SW",
|
|
151
|
+
] as const
|
|
152
|
+
|
|
153
|
+
export interface StreetBaseTuple {
|
|
154
|
+
locality: string
|
|
155
|
+
region: string
|
|
156
|
+
postcode: string
|
|
157
|
+
country: string
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface SynthesizedStreetRow {
|
|
161
|
+
raw: string
|
|
162
|
+
components: CanonicalRow["components"]
|
|
163
|
+
locale: string
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface StreetSynthesisOpts {
|
|
167
|
+
random?: () => number
|
|
168
|
+
/** Probability of emitting house_number alongside the street. Default 0.85. */
|
|
169
|
+
includeHouseNumberProb?: number
|
|
170
|
+
/**
|
|
171
|
+
* Probability of emitting the street BARE — no `, City, ST ZIP` tail and no region/locality/ postcode components
|
|
172
|
+
* (just `street_prefix`/`street`/`street_suffix` + optional `house_number`). Default 0 (preserves the original
|
|
173
|
+
* full-address behavior exactly, including the RNG sequence). Set >0 to teach the model that a bare `10th Ave` /
|
|
174
|
+
* `Main St` is a STREET, not a locality — the functional-test failure cluster (bare streets mislabeled `locality`),
|
|
175
|
+
* the bare-format analogue of the v0.7.x intersection-bare fix.
|
|
176
|
+
*/
|
|
177
|
+
bareProb?: number
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function pick<T>(arr: ReadonlyArray<T>, random: () => number): T {
|
|
181
|
+
return arr[Math.floor(random() * arr.length)]!
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function randomHouseNumber(random: () => number): string {
|
|
185
|
+
// US house number distribution: skewed low. 1-99 (30%), 100-999 (40%),
|
|
186
|
+
// 1000-9999 (25%), 10000+ (5%).
|
|
187
|
+
const r = random()
|
|
188
|
+
|
|
189
|
+
if (r < 0.3) return String(1 + Math.floor(random() * 99))
|
|
190
|
+
|
|
191
|
+
if (r < 0.7) return String(100 + Math.floor(random() * 900))
|
|
192
|
+
|
|
193
|
+
if (r < 0.95) return String(1000 + Math.floor(random() * 9000))
|
|
194
|
+
|
|
195
|
+
return String(10000 + Math.floor(random() * 89999))
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Synthesize a US street address with decomposed Stage 3 components. The street is built from PREFIX + NAME + SUFFIX,
|
|
200
|
+
* then passed through the same `decomposeStreet()` utility the TIGER adapter uses — guarantees the synthetic
|
|
201
|
+
* distribution matches the canonical decomposition logic.
|
|
202
|
+
*/
|
|
203
|
+
export function synthesizeStreetRow(
|
|
204
|
+
base: StreetBaseTuple,
|
|
205
|
+
opts: StreetSynthesisOpts = {}
|
|
206
|
+
): SynthesizedStreetRow | null {
|
|
207
|
+
const random = opts.random ?? Math.random
|
|
208
|
+
const includeHN = opts.includeHouseNumberProb ?? 0.85
|
|
209
|
+
|
|
210
|
+
if (base.country !== "US") return null
|
|
211
|
+
|
|
212
|
+
const prefix = pick(DIRECTIONAL_PREFIXES, random)
|
|
213
|
+
const name = pick(STREET_NAMES, random)
|
|
214
|
+
const suffix = pick(STREET_SUFFIXES, random)
|
|
215
|
+
const trailing = pick(TRAILING_DIRECTIONALS, random)
|
|
216
|
+
|
|
217
|
+
// Build the "full" street string the adapter would receive from TIGER FULLNAME.
|
|
218
|
+
const parts = [prefix, name, suffix, trailing].filter(Boolean)
|
|
219
|
+
const fullStreet = parts.join(" ")
|
|
220
|
+
|
|
221
|
+
// Pass through the same decomposeStreet TIGER uses — match the training distribution.
|
|
222
|
+
const decomposed = decomposeStreet(fullStreet)
|
|
223
|
+
|
|
224
|
+
// NOTE: country is intentionally omitted. We don't emit "USA" or "US" in the raw
|
|
225
|
+
// string, and the aligner's fuzzy match (edit distance 2) will spuriously match
|
|
226
|
+
// "US" against any 2-char token (e.g. a house number "45" is exactly 2 substitutions
|
|
227
|
+
// from "US"). The PO box synthesizer skips country for the same reason.
|
|
228
|
+
// Bare mode is guarded by `> 0` so the default (bareProb=0) consumes no RNG and reproduces the
|
|
229
|
+
// original full-address output byte-for-byte.
|
|
230
|
+
const bareProb = opts.bareProb ?? 0
|
|
231
|
+
const bare = bareProb > 0 && random() < bareProb
|
|
232
|
+
|
|
233
|
+
const components: CanonicalRow["components"] = bare
|
|
234
|
+
? {}
|
|
235
|
+
: {
|
|
236
|
+
region: base.region,
|
|
237
|
+
locality: base.locality,
|
|
238
|
+
postcode: base.postcode,
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (decomposed.prefix) {
|
|
242
|
+
components.street_prefix = decomposed.prefix
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (decomposed.street) {
|
|
246
|
+
components.street = decomposed.street
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (decomposed.suffix) {
|
|
250
|
+
components.street_suffix = decomposed.suffix
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
let raw: string
|
|
254
|
+
|
|
255
|
+
if (random() < includeHN) {
|
|
256
|
+
const hn = randomHouseNumber(random)
|
|
257
|
+
components.house_number = hn
|
|
258
|
+
raw = bare ? `${hn} ${fullStreet}` : `${hn} ${fullStreet}, ${base.locality}, ${base.region} ${base.postcode}`
|
|
259
|
+
} else {
|
|
260
|
+
raw = bare ? fullStreet : `${fullStreet}, ${base.locality}, ${base.region} ${base.postcode}`
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return { raw, components, locale: "en-US" }
|
|
264
|
+
}
|