Skip to content

detect: rank only systems whose source script matches the input - #27

Closed
ronaldtse wants to merge 4 commits into
mainfrom
fix/detect-script-prefilter
Closed

ronaldtse wants to merge 4 commits into
mainfrom
fix/detect-script-prefilter

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

Problem

detect transliterated the input through all 288 systems per request. On the Workers free plan (10 ms CPU budget) that intermittently exceeds the limit — production right now returns partial rankings that vary per call (47–96 entries of 288) or fails outright with error 1102 (Worker exceeded CPU time limit):

$ for i in 1..12; curl /v1/detect ... → 5×47 entries, 2×96, 5×HTTP 503 (1102)

The single-map CPU cost also explains why library-dependent systems (which load 2–4 JSONs) 1102 on cold isolates — see the capacity note below.

Fix

  • detectInputScript() — majority Unicode-block scan of the input; a single non-Latin letter outranks any amount of Latin.
  • maps/scripts.js — build-time generated code → source_script index (emitted by scripts/build-maps.mjs from the artifact metadata).
  • detect() walks only the matching family: Georgian input → 8 systems (was 288); Hangul input also matches the mixed Kore sources; Han input also matches Hans/Kore/Hrkt.
  • Script-less input (digits/punctuation only) returns an empty ranking instead of walking the corpus.

Top hits are unchanged for real queries (ქართული → alalc-kat-Geor-Latn-1997 @ 0, 한국 → distance 0, 阜康 → acadsin-zho).

Tests

  • new test/detect.test.ts: script detection, prefilter (asserts the asset-fetch count drops to ≤ 10), Korean/Han family matching, script-less input
  • full suite 37/37; detect fixture re-recorded from the prefiltered engine

Capacity note for the owner (not addressed here)

The API sits on the Workers free plan (10 ms CPU); even single transliterations of library-dependent maps 1102 on cold isolates. The durable fix is a plan tier with real CPU — Workers Standard (usage-priced, currently $0.30/M requests) plus limits.cpu_ms in the deploy wrangler.jsonc. That is a spending decision, so it is only documented here.

…5.1 (289 systems)

Built with build-maps.rb against the ISC corpus through interscript-ruby's NodeAdapter (funcall-node casing fix + array-valued Any serialisation). 293 files: 289 systems + 4 libraries (posix, unicode, var-Cyrl, var-kor). One corpus-data gap noted: bgnpcgn-tuk-Cyrl-Latn-1993 depends on a 1979 map absent from the maps repo.
Replaces the corpus built by interscript-ruby's JsonIR with output of
the canonical builder — interscript-ts's ISC converter, the same
pipeline that produces the interscript/maps release artifact. 273 of
289 system JSONs were not byte-identical to production; the parity
gate caught Tamil (தமிழ் came out 'tamail̮a').

Also picks up interscript/maps#194: the four dependency libraries
(posix, unicode, var-Cyrl, var-kor) ship in the corpus again, and the
16 maps referencing var-kor aliases declare the dependency. This
restores bgnpcgn-deu (Tschüß! -> Tschueß!) and the other 17
library-dependent maps that api.interscript.org currently fails with
'Map dependency missing'.

The detect ranking (288 systems) and systemCodes count (289
addressable) are re-baselined to the corrected corpus; production
currently returns a truncated 48-map detect ranking and null for
library-dependent maps, so test/fixtures/parity.json records the
corrected behavior until the deploy catches up.

scripts/build-maps.rb pointed at the retired Ruby pipeline; it now
defers to scripts/build-maps.mjs, which runs the canonical TS builder
and regenerates manifest.js.
The detect walk loaded all 288 maps per request. On the Workers free
plan (10ms CPU) that intermittently dies with 1102 — production
returns anywhere between 47 and 96 partial rankings per call, or 503s.
Loading every map to rank unrelated scripts was also semantically
empty: Georgian input ranked 280 irrelevant systems at distance 9.

detectInputScript() picks the majority Unicode script of the input
(non-Latin beats Latin when tied); a build-time generated
maps/scripts.js maps each system to its source script, and detect
walks only the matching family (Hangul input also matches the mixed
Kore sources, Han input also matches Hans/Kore/Hrkt). Georgian input
now loads 8 systems instead of 288 and the top hits are unchanged.

Test fixtures: the detect fixture records the prefiltered ranking.
@ronaldtse

Copy link
Copy Markdown
Contributor Author

Superseded by #28 (same change rebased on the squash-merged main).

@ronaldtse ronaldtse closed this Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant