@mailwoman/kind-classifier 4.0.0
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/out/classify.d.ts +28 -0
- package/out/classify.d.ts.map +1 -0
- package/out/classify.js +49 -0
- package/out/classify.js.map +1 -0
- package/out/index.d.ts +18 -0
- package/out/index.d.ts.map +1 -0
- package/out/index.js +17 -0
- package/out/index.js.map +1 -0
- package/out/rules.d.ts +67 -0
- package/out/rules.d.ts.map +1 -0
- package/out/rules.js +234 -0
- package/out/rules.js.map +1 -0
- package/out/types.d.ts +37 -0
- package/out/types.d.ts.map +1 -0
- package/out/types.js +7 -0
- package/out/types.js.map +1 -0
- package/package.json +28 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `classifyKind` — entry point for Stage 2.5 (kind classification).
|
|
7
|
+
*
|
|
8
|
+
* Composes the per-kind rules from `rules.ts` and picks the winner. Returns alternatives sorted by
|
|
9
|
+
* confidence so the coordinator can offer fallback paths when the top kind isn't actionable.
|
|
10
|
+
*
|
|
11
|
+
* Per the project's "possibilities not constraints" principle, every kind that fires above 0
|
|
12
|
+
* surfaces in `alternatives` — the caller decides whether to act on the top kind only or consider
|
|
13
|
+
* runner-ups.
|
|
14
|
+
*/
|
|
15
|
+
import type { LocaleHint, NormalizedInputLite, QueryKindResult, QueryShapeLike } from "./types.js";
|
|
16
|
+
/**
|
|
17
|
+
* Classify the query shape into a `QueryKind`. Synchronous + pure — produces the same result for
|
|
18
|
+
* the same `(input, shape)` pair.
|
|
19
|
+
*/
|
|
20
|
+
export declare function classifyKindSync(input: NormalizedInputLite, shape: QueryShapeLike): QueryKindResult;
|
|
21
|
+
/**
|
|
22
|
+
* Async variant matching the runtime-pipeline's `classifyKind` contract.
|
|
23
|
+
*
|
|
24
|
+
* The locale parameter is accepted for future locale-aware rules (Japanese honorifics, etc.) but
|
|
25
|
+
* not currently used.
|
|
26
|
+
*/
|
|
27
|
+
export declare function classifyKind(input: NormalizedInputLite, shape: QueryShapeLike, _locale?: LocaleHint): Promise<QueryKindResult>;
|
|
28
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAa,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAiB7G;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,eAAe,CAcnG;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CACjC,KAAK,EAAE,mBAAmB,EAC1B,KAAK,EAAE,cAAc,EACrB,OAAO,CAAC,EAAE,UAAU,GAClB,OAAO,CAAC,eAAe,CAAC,CAE1B"}
|
package/out/classify.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `classifyKind` — entry point for Stage 2.5 (kind classification).
|
|
7
|
+
*
|
|
8
|
+
* Composes the per-kind rules from `rules.ts` and picks the winner. Returns alternatives sorted by
|
|
9
|
+
* confidence so the coordinator can offer fallback paths when the top kind isn't actionable.
|
|
10
|
+
*
|
|
11
|
+
* Per the project's "possibilities not constraints" principle, every kind that fires above 0
|
|
12
|
+
* surfaces in `alternatives` — the caller decides whether to act on the top kind only or consider
|
|
13
|
+
* runner-ups.
|
|
14
|
+
*/
|
|
15
|
+
import { scoreIntersection, scoreLandmark, scoreLocalityOnly, scorePoBox, scorePostcodeOnly, scoreStructuredAddress, scoreVague, scoreVenueLandmark, } from "./rules.js";
|
|
16
|
+
const SCORERS = [
|
|
17
|
+
{ kind: "po_box", score: scorePoBox },
|
|
18
|
+
{ kind: "landmark", score: (i, s) => Math.max(scoreLandmark(i, s), scoreVenueLandmark(i, s)) },
|
|
19
|
+
{ kind: "intersection", score: scoreIntersection },
|
|
20
|
+
{ kind: "postcode_only", score: scorePostcodeOnly },
|
|
21
|
+
{ kind: "locality_only", score: scoreLocalityOnly },
|
|
22
|
+
{ kind: "structured_address", score: scoreStructuredAddress },
|
|
23
|
+
{ kind: "vague", score: scoreVague },
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Classify the query shape into a `QueryKind`. Synchronous + pure — produces the same result for
|
|
27
|
+
* the same `(input, shape)` pair.
|
|
28
|
+
*/
|
|
29
|
+
export function classifyKindSync(input, shape) {
|
|
30
|
+
const scored = SCORERS.map((s) => ({ kind: s.kind, confidence: s.score(input, shape) })).filter((s) => s.confidence > 0);
|
|
31
|
+
scored.sort((a, b) => b.confidence - a.confidence);
|
|
32
|
+
const top = scored[0] ?? { kind: "vague", confidence: 0.3 };
|
|
33
|
+
const alternatives = scored.slice(1).map((s) => ({ kind: s.kind, confidence: s.confidence }));
|
|
34
|
+
return {
|
|
35
|
+
kind: top.kind,
|
|
36
|
+
confidence: top.confidence,
|
|
37
|
+
alternatives,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Async variant matching the runtime-pipeline's `classifyKind` contract.
|
|
42
|
+
*
|
|
43
|
+
* The locale parameter is accepted for future locale-aware rules (Japanese honorifics, etc.) but
|
|
44
|
+
* not currently used.
|
|
45
|
+
*/
|
|
46
|
+
export async function classifyKind(input, shape, _locale) {
|
|
47
|
+
return classifyKindSync(input, shape);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACN,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,kBAAkB,GAClB,MAAM,YAAY,CAAA;AAQnB,MAAM,OAAO,GAA8B;IAC1C,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE;IACrC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;IAC9F,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,iBAAiB,EAAE;IAClD,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,iBAAiB,EAAE;IACnD,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,iBAAiB,EAAE;IACnD,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,sBAAsB,EAAE;IAC7D,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE;CACpC,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA0B,EAAE,KAAqB;IACjF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAC9F,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CACvB,CAAA;IACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAA;IAElD,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,OAAoB,EAAE,UAAU,EAAE,GAAG,EAAE,CAAA;IACxE,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAA;IAE7F,OAAO;QACN,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,YAAY;KACZ,CAAA;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,KAA0B,EAC1B,KAAqB,EACrB,OAAoB;IAEpB,OAAO,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AACtC,CAAC"}
|
package/out/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `@mailwoman/kind-classifier` — Stage 2.5 of the runtime pipeline.
|
|
7
|
+
*
|
|
8
|
+
* Categorize inputs into one of seven `QueryKind`s by composing rule-based scorers over the
|
|
9
|
+
* QueryShape sub-system's output. Pure functions, no ML, no place-name dictionaries. Returns
|
|
10
|
+
* possibilities (alternatives) alongside the top pick so the coordinator can fall back when the
|
|
11
|
+
* winning kind isn't actionable.
|
|
12
|
+
*
|
|
13
|
+
* See `docs/articles/plan/reference/STAGES.md` § Stage 2.5 for the contract.
|
|
14
|
+
*/
|
|
15
|
+
export { classifyKind, classifyKindSync } from "./classify.js";
|
|
16
|
+
export { scoreIntersection, scoreLandmark, scoreLocalityOnly, scorePoBox, scorePostcodeOnly, scoreStructuredAddress, scoreVague, } from "./rules.js";
|
|
17
|
+
export type { LocaleHint, NormalizedInputLite, QueryKind, QueryKindResult, QueryShapeLike } from "./types.js";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC9D,OAAO,EACN,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,GACV,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
|
package/out/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `@mailwoman/kind-classifier` — Stage 2.5 of the runtime pipeline.
|
|
7
|
+
*
|
|
8
|
+
* Categorize inputs into one of seven `QueryKind`s by composing rule-based scorers over the
|
|
9
|
+
* QueryShape sub-system's output. Pure functions, no ML, no place-name dictionaries. Returns
|
|
10
|
+
* possibilities (alternatives) alongside the top pick so the coordinator can fall back when the
|
|
11
|
+
* winning kind isn't actionable.
|
|
12
|
+
*
|
|
13
|
+
* See `docs/articles/plan/reference/STAGES.md` § Stage 2.5 for the contract.
|
|
14
|
+
*/
|
|
15
|
+
export { classifyKind, classifyKindSync } from "./classify.js";
|
|
16
|
+
export { scoreIntersection, scoreLandmark, scoreLocalityOnly, scorePoBox, scorePostcodeOnly, scoreStructuredAddress, scoreVague, } from "./rules.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
package/out/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC9D,OAAO,EACN,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,GACV,MAAM,YAAY,CAAA"}
|
package/out/rules.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Rule-based classifiers for each `QueryKind`. Each rule inspects the normalized input + QueryShape
|
|
7
|
+
* and returns a confidence score in [0, 1], or 0 if the rule doesn't fire.
|
|
8
|
+
*
|
|
9
|
+
* Bitter-lesson-safe: only universal structural patterns — no place-name dictionaries. ~1 small
|
|
10
|
+
* regex set per new locale, not 50K dictionary entries.
|
|
11
|
+
*/
|
|
12
|
+
import type { NormalizedInputLite, QueryShapeLike } from "./types.js";
|
|
13
|
+
/**
|
|
14
|
+
* `po_box` rule: high-confidence iff QueryShape detected a po_box format hit. Confidence comes
|
|
15
|
+
* directly from the hit; covers all locale variants (US "PO Box 123", FR "BP 42", etc.).
|
|
16
|
+
*/
|
|
17
|
+
export declare function scorePoBox(_input: NormalizedInputLite, shape: QueryShapeLike): number;
|
|
18
|
+
/**
|
|
19
|
+
* `intersection` rule: text matches one of the conventional intersection phrasings.
|
|
20
|
+
*/
|
|
21
|
+
export declare function scoreIntersection(input: NormalizedInputLite, _shape: QueryShapeLike): number;
|
|
22
|
+
/**
|
|
23
|
+
* `landmark` rule: text begins with a landmark-leader phrase. These inputs are not addresses proper
|
|
24
|
+
* — they describe a location relative to another place.
|
|
25
|
+
*/
|
|
26
|
+
export declare function scoreLandmark(input: NormalizedInputLite, _shape: QueryShapeLike): number;
|
|
27
|
+
/**
|
|
28
|
+
* `landmark` rule (venue/named-place variant): short capitalized input with no street suffixes, no
|
|
29
|
+
* postcode hits, and no region abbreviations. Captures "Pier 39", "Empire State Building", "Wrigley
|
|
30
|
+
* Field", "Grand Central Terminal".
|
|
31
|
+
*
|
|
32
|
+
* Fires at moderate confidence (0.65) — below structured_address (0.9) so addresses always win, but
|
|
33
|
+
* above vague (0.3) so the pipeline can route landmark queries to the venue resolver.
|
|
34
|
+
*/
|
|
35
|
+
export declare function scoreVenueLandmark(input: NormalizedInputLite, shape: QueryShapeLike): number;
|
|
36
|
+
/**
|
|
37
|
+
* Test whether a format string is a postcode variant. Use the set rather than ad-hoc
|
|
38
|
+
* string-matching to avoid the `us_zip4.endsWith("_zip")` false-negative trap.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isPostcodeFormat(format: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* `postcode_only` rule: input is short AND has a postcode format hit covering most of it.
|
|
43
|
+
*
|
|
44
|
+
* The "covering most of it" check is what distinguishes `"10118"` (postcode-only) from `"350 5th
|
|
45
|
+
* Ave 10118"` (structured-address with a postcode in it).
|
|
46
|
+
*/
|
|
47
|
+
export declare function scorePostcodeOnly(input: NormalizedInputLite, shape: QueryShapeLike): number;
|
|
48
|
+
/**
|
|
49
|
+
* `locality_only` rule: short input, alpha-class, single segment, no format hits.
|
|
50
|
+
*
|
|
51
|
+
* Examples: `"Paris"`, `"NYC NY"`, `"Tokyo"`. Distinguishes from `structured_address` (multiple
|
|
52
|
+
* segments) and `vague` (long or mixed-class).
|
|
53
|
+
*/
|
|
54
|
+
export declare function scoreLocalityOnly(input: NormalizedInputLite, shape: QueryShapeLike): number;
|
|
55
|
+
/**
|
|
56
|
+
* `structured_address` rule: looks like a real multi-component address. Either has multiple
|
|
57
|
+
* segments or is long and mixed-class.
|
|
58
|
+
*/
|
|
59
|
+
export declare function scoreStructuredAddress(input: NormalizedInputLite, shape: QueryShapeLike): number;
|
|
60
|
+
/**
|
|
61
|
+
* `vague` rule: nothing else fired with high confidence — input is ambiguous.
|
|
62
|
+
*
|
|
63
|
+
* Returns a moderate baseline so `vague` always shows up as an alternative, even when other rules
|
|
64
|
+
* dominate. The coordinator decides whether to trust vague as the primary kind.
|
|
65
|
+
*/
|
|
66
|
+
export declare function scoreVague(_input: NormalizedInputLite, _shape: QueryShapeLike): number;
|
|
67
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAwBrE;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAMrF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAM5F;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAMxF;AA6BD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CA4C5F;AAaD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAU3F;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAU3F;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAahG;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAEtF"}
|
package/out/rules.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Rule-based classifiers for each `QueryKind`. Each rule inspects the normalized input + QueryShape
|
|
7
|
+
* and returns a confidence score in [0, 1], or 0 if the rule doesn't fire.
|
|
8
|
+
*
|
|
9
|
+
* Bitter-lesson-safe: only universal structural patterns — no place-name dictionaries. ~1 small
|
|
10
|
+
* regex set per new locale, not 50K dictionary entries.
|
|
11
|
+
*/
|
|
12
|
+
/** Landmark vocabulary — phrases that suggest a vague-location description rather than an address. */
|
|
13
|
+
const LANDMARK_LEADERS = [
|
|
14
|
+
"behind",
|
|
15
|
+
"near",
|
|
16
|
+
"across from",
|
|
17
|
+
"opposite",
|
|
18
|
+
"next to",
|
|
19
|
+
"by the",
|
|
20
|
+
"in front of",
|
|
21
|
+
"close to",
|
|
22
|
+
"beside",
|
|
23
|
+
];
|
|
24
|
+
/** Intersection vocabulary — words that signal "where two streets cross" rather than an address. */
|
|
25
|
+
const INTERSECTION_PATTERNS = [
|
|
26
|
+
/\bcorner of\b/i,
|
|
27
|
+
/\bintersection of\b/i,
|
|
28
|
+
/\bat the corner of\b/i,
|
|
29
|
+
// "5th and Main", "Broadway & 42nd"
|
|
30
|
+
/\b\w+(?:st|nd|rd|th|street|ave|avenue|blvd|boulevard|road|rd|lane|ln)?\s+(?:and|&|@)\s+\w+/i,
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* `po_box` rule: high-confidence iff QueryShape detected a po_box format hit. Confidence comes
|
|
34
|
+
* directly from the hit; covers all locale variants (US "PO Box 123", FR "BP 42", etc.).
|
|
35
|
+
*/
|
|
36
|
+
export function scorePoBox(_input, shape) {
|
|
37
|
+
const hit = shape.knownFormats.find((f) => f.format === "po_box");
|
|
38
|
+
if (!hit)
|
|
39
|
+
return 0;
|
|
40
|
+
// Boost slightly above the raw hit confidence so po_box wins ties with structured_address when
|
|
41
|
+
// both rules fire on the same input.
|
|
42
|
+
return Math.min(1, hit.confidence + 0.1);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* `intersection` rule: text matches one of the conventional intersection phrasings.
|
|
46
|
+
*/
|
|
47
|
+
export function scoreIntersection(input, _shape) {
|
|
48
|
+
const text = input.normalized;
|
|
49
|
+
for (const pattern of INTERSECTION_PATTERNS) {
|
|
50
|
+
if (pattern.test(text))
|
|
51
|
+
return 0.85;
|
|
52
|
+
}
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* `landmark` rule: text begins with a landmark-leader phrase. These inputs are not addresses proper
|
|
57
|
+
* — they describe a location relative to another place.
|
|
58
|
+
*/
|
|
59
|
+
export function scoreLandmark(input, _shape) {
|
|
60
|
+
const lc = input.normalized.toLowerCase().trim();
|
|
61
|
+
for (const leader of LANDMARK_LEADERS) {
|
|
62
|
+
if (lc.startsWith(leader + " ") || lc === leader)
|
|
63
|
+
return 0.9;
|
|
64
|
+
}
|
|
65
|
+
return 0;
|
|
66
|
+
}
|
|
67
|
+
/** Street-suffix tokens that indicate an address, not a venue name. */
|
|
68
|
+
const STREET_SUFFIXES = new Set([
|
|
69
|
+
"st",
|
|
70
|
+
"street",
|
|
71
|
+
"ave",
|
|
72
|
+
"avenue",
|
|
73
|
+
"blvd",
|
|
74
|
+
"boulevard",
|
|
75
|
+
"rd",
|
|
76
|
+
"road",
|
|
77
|
+
"dr",
|
|
78
|
+
"drive",
|
|
79
|
+
"ln",
|
|
80
|
+
"lane",
|
|
81
|
+
"ct",
|
|
82
|
+
"court",
|
|
83
|
+
"pl",
|
|
84
|
+
"place",
|
|
85
|
+
"way",
|
|
86
|
+
"pkwy",
|
|
87
|
+
"parkway",
|
|
88
|
+
"hwy",
|
|
89
|
+
"highway",
|
|
90
|
+
"cir",
|
|
91
|
+
"circle",
|
|
92
|
+
]);
|
|
93
|
+
/**
|
|
94
|
+
* `landmark` rule (venue/named-place variant): short capitalized input with no street suffixes, no
|
|
95
|
+
* postcode hits, and no region abbreviations. Captures "Pier 39", "Empire State Building", "Wrigley
|
|
96
|
+
* Field", "Grand Central Terminal".
|
|
97
|
+
*
|
|
98
|
+
* Fires at moderate confidence (0.65) — below structured_address (0.9) so addresses always win, but
|
|
99
|
+
* above vague (0.3) so the pipeline can route landmark queries to the venue resolver.
|
|
100
|
+
*/
|
|
101
|
+
export function scoreVenueLandmark(input, shape) {
|
|
102
|
+
const text = input.normalized.trim();
|
|
103
|
+
const len = text.length;
|
|
104
|
+
if (len === 0 || len > 50)
|
|
105
|
+
return 0;
|
|
106
|
+
// Must have at least one capitalized word.
|
|
107
|
+
if (!/[A-Z]/.test(text))
|
|
108
|
+
return 0;
|
|
109
|
+
// Reject if any known postcode format hit exists.
|
|
110
|
+
if (shape.knownFormats.length > 0)
|
|
111
|
+
return 0;
|
|
112
|
+
// Reject if it looks like a multi-segment structured address (City, ST ZIP).
|
|
113
|
+
const segCount = shape.segments?.length ?? 1;
|
|
114
|
+
if (segCount > 2)
|
|
115
|
+
return 0;
|
|
116
|
+
// Reject if any word is a street suffix.
|
|
117
|
+
const words = text.split(/[\s,]+/);
|
|
118
|
+
for (const w of words) {
|
|
119
|
+
if (STREET_SUFFIXES.has(w.toLowerCase()))
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
// Reject if the first token is a pure number (house-number-leading pattern).
|
|
123
|
+
if (/^\d+\s/.test(text))
|
|
124
|
+
return 0;
|
|
125
|
+
// Boost if the input has a number NOT at the start (venue-style: "Pier 39", "Terminal 5").
|
|
126
|
+
const hasInternalNumber = /\s\d+/.test(text) && !/^\d/.test(text);
|
|
127
|
+
// Check if every word starts with uppercase (proper-noun pattern).
|
|
128
|
+
const allProperCase = words.length > 1 && words.every((w) => /^[A-Z]/.test(w));
|
|
129
|
+
// Boost for short single-segment capitalized phrases (2-4 words).
|
|
130
|
+
const wordCount = words.length;
|
|
131
|
+
if (wordCount >= 2 && wordCount <= 4 && segCount === 1) {
|
|
132
|
+
if (hasInternalNumber)
|
|
133
|
+
return 0.88;
|
|
134
|
+
if (allProperCase)
|
|
135
|
+
return 0.88;
|
|
136
|
+
return 0.65;
|
|
137
|
+
}
|
|
138
|
+
// Longer single-segment capitalized phrases get moderate confidence.
|
|
139
|
+
if (wordCount <= 6 && segCount === 1 && allProperCase) {
|
|
140
|
+
return 0.75;
|
|
141
|
+
}
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
/** Known QueryShape format strings that indicate "this token is a postcode". */
|
|
145
|
+
const POSTCODE_FORMATS = new Set([
|
|
146
|
+
"us_zip",
|
|
147
|
+
"us_zip4",
|
|
148
|
+
"uk_postcode",
|
|
149
|
+
"fr_postcode",
|
|
150
|
+
"de_postcode",
|
|
151
|
+
"ca_postcode",
|
|
152
|
+
"jp_postcode",
|
|
153
|
+
]);
|
|
154
|
+
/**
|
|
155
|
+
* Test whether a format string is a postcode variant. Use the set rather than ad-hoc
|
|
156
|
+
* string-matching to avoid the `us_zip4.endsWith("_zip")` false-negative trap.
|
|
157
|
+
*/
|
|
158
|
+
export function isPostcodeFormat(format) {
|
|
159
|
+
return POSTCODE_FORMATS.has(format);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* `postcode_only` rule: input is short AND has a postcode format hit covering most of it.
|
|
163
|
+
*
|
|
164
|
+
* The "covering most of it" check is what distinguishes `"10118"` (postcode-only) from `"350 5th
|
|
165
|
+
* Ave 10118"` (structured-address with a postcode in it).
|
|
166
|
+
*/
|
|
167
|
+
export function scorePostcodeOnly(input, shape) {
|
|
168
|
+
const len = input.normalized.length;
|
|
169
|
+
if (len === 0 || len > 16)
|
|
170
|
+
return 0;
|
|
171
|
+
const postcodeHit = shape.knownFormats.find((f) => isPostcodeFormat(f.format));
|
|
172
|
+
if (!postcodeHit)
|
|
173
|
+
return 0;
|
|
174
|
+
const hitLen = postcodeHit.span.end - postcodeHit.span.start;
|
|
175
|
+
// At least 70% of the input must be the postcode for the rule to fire confidently.
|
|
176
|
+
if (hitLen / len < 0.7)
|
|
177
|
+
return 0;
|
|
178
|
+
// Confidence scales with how much of the input is the postcode and how confident the format hit was.
|
|
179
|
+
return Math.min(1, postcodeHit.confidence * (hitLen / len) + 0.1);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* `locality_only` rule: short input, alpha-class, single segment, no format hits.
|
|
183
|
+
*
|
|
184
|
+
* Examples: `"Paris"`, `"NYC NY"`, `"Tokyo"`. Distinguishes from `structured_address` (multiple
|
|
185
|
+
* segments) and `vague` (long or mixed-class).
|
|
186
|
+
*/
|
|
187
|
+
export function scoreLocalityOnly(input, shape) {
|
|
188
|
+
const len = input.normalized.length;
|
|
189
|
+
if (len === 0 || len > 30)
|
|
190
|
+
return 0;
|
|
191
|
+
if (shape.characterClass !== "alpha")
|
|
192
|
+
return 0;
|
|
193
|
+
if (shape.knownFormats.length > 0)
|
|
194
|
+
return 0;
|
|
195
|
+
// Locality-only inputs typically have 1-3 segments (e.g. "New York" is 1 segment, "Paris, FR" is 2).
|
|
196
|
+
// We allow up to 2 segments before deciding it's structured.
|
|
197
|
+
const segCount = shape.segments?.length ?? 1;
|
|
198
|
+
if (segCount > 2)
|
|
199
|
+
return 0;
|
|
200
|
+
return 0.85;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* `structured_address` rule: looks like a real multi-component address. Either has multiple
|
|
204
|
+
* segments or is long and mixed-class.
|
|
205
|
+
*/
|
|
206
|
+
export function scoreStructuredAddress(input, shape) {
|
|
207
|
+
const len = input.normalized.length;
|
|
208
|
+
if (len === 0)
|
|
209
|
+
return 0;
|
|
210
|
+
const segCount = shape.segments?.length ?? 1;
|
|
211
|
+
// Multi-segment input with mixed character class = high confidence structured.
|
|
212
|
+
if (segCount >= 2 && shape.characterClass === "alphanumeric")
|
|
213
|
+
return 0.9;
|
|
214
|
+
// Single-segment but reasonably long and alphanumeric = moderate confidence.
|
|
215
|
+
if (len >= 15 && shape.characterClass === "alphanumeric")
|
|
216
|
+
return 0.75;
|
|
217
|
+
// Multi-segment but pure-alpha = moderate (could be a multi-word locality).
|
|
218
|
+
if (segCount >= 2)
|
|
219
|
+
return 0.6;
|
|
220
|
+
// Single-segment, short, alphanumeric (e.g. "10118-1234" with no other content) — weak.
|
|
221
|
+
if (len < 15 && shape.characterClass === "alphanumeric")
|
|
222
|
+
return 0.4;
|
|
223
|
+
return 0;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* `vague` rule: nothing else fired with high confidence — input is ambiguous.
|
|
227
|
+
*
|
|
228
|
+
* Returns a moderate baseline so `vague` always shows up as an alternative, even when other rules
|
|
229
|
+
* dominate. The coordinator decides whether to trust vague as the primary kind.
|
|
230
|
+
*/
|
|
231
|
+
export function scoreVague(_input, _shape) {
|
|
232
|
+
return 0.3;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=rules.js.map
|
package/out/rules.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../rules.ts"],"names":[],"mappings":"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"}
|
package/out/types.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
/** Re-exports of the canonical types from `@mailwoman/core/pipeline`. */
|
|
7
|
+
export type { LocaleHint, QueryKind, QueryKindResult } from "@mailwoman/core/pipeline";
|
|
8
|
+
/**
|
|
9
|
+
* Minimal `NormalizedInput` shape consumed by `classifyKind`. Compatible with
|
|
10
|
+
* `@mailwoman/normalize`'s output.
|
|
11
|
+
*/
|
|
12
|
+
export interface NormalizedInputLite {
|
|
13
|
+
raw: string;
|
|
14
|
+
normalized: string;
|
|
15
|
+
appliedLocale?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Minimal `QueryShape` shape consumed by `classifyKind`. Compatible with `@mailwoman/query-shape`'s
|
|
19
|
+
* output.
|
|
20
|
+
*/
|
|
21
|
+
export interface QueryShapeLike {
|
|
22
|
+
knownFormats: ReadonlyArray<{
|
|
23
|
+
format: string;
|
|
24
|
+
span: {
|
|
25
|
+
start: number;
|
|
26
|
+
end: number;
|
|
27
|
+
};
|
|
28
|
+
confidence: number;
|
|
29
|
+
}>;
|
|
30
|
+
segments?: ReadonlyArray<{
|
|
31
|
+
body: string;
|
|
32
|
+
index: number;
|
|
33
|
+
}>;
|
|
34
|
+
characterClass?: string;
|
|
35
|
+
totalLength?: number;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yEAAyE;AACzE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAEtF;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,YAAY,EAAE,aAAa,CAAC;QAC3B,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAA;QACpC,UAAU,EAAE,MAAM,CAAA;KAClB,CAAC,CAAA;IACF,QAAQ,CAAC,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACzD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB"}
|
package/out/types.js
ADDED
package/out/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mailwoman/kind-classifier",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"description": "Stage 2.5 of the runtime pipeline — categorize inputs by query shape (postcode_only / locality_only / structured_address / intersection / po_box / landmark / vague). Rule-based for v1.",
|
|
5
|
+
"license": "AGPL-3.0-only",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/sister-software/mailwoman.git",
|
|
9
|
+
"directory": "kind-classifier"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"exports": {
|
|
13
|
+
"./package.json": "./package.json",
|
|
14
|
+
".": "./out/index.js"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@mailwoman/core": "4.0.0"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"out/**/*.js",
|
|
21
|
+
"out/**/*.js.map",
|
|
22
|
+
"out/**/*.d.ts",
|
|
23
|
+
"out/**/*.d.ts.map"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
}
|
|
28
|
+
}
|