--- license: mit tags: - language-detection - cyrillic - fasttext - text-classification language: - rus - ukr - bel - bul - mkd - srp - kaz - kir - tgk - uzn - tat - bak - chv - sah - tyv - mon - oss - che - udm - mhr - kpv - eng - spa - fra - por - deu - cmn - jpn - hin - ara --- # spellman model Runtime model for **spellman** — a Cyrillic-optimized language detector. 30 classes: the G10 world languages plus ~20 Cyrillic-script languages, built for the regime general-purpose detectors fail at — closely-related Cyrillic pairs (ru/be/uk, bg/mk/sr, kk/ky/tt/ba) on wild, short, real internet text — at single-digit µs/sample CPU speed. ## Languages (30) - **Cyrillic group (21):** rus ukr bel bul mkd srp kaz kir tgk uzn tat bak chv sah tyv mon oss che udm mhr kpv - **Latin group (5):** eng spa fra por deu - **Script-routed, no model columns (4):** cmn jpn hin ara ## Files - `model.json` — the runtime contract (`version: 3`): language order (model columns), hash id/seed, char n-gram config (1..=5), canonicalization + lexical flags, calibrated confidence threshold θ. - `model.safetensors` — `P` `[131073×30]` f16 (the algebraic fold `P = E·W` of a fastText-style model) + `bias` `[30]` f16. Inference is pure table lookups — no embedding gathers, no matmul. The feature space is char n-grams **plus a lexical channel**: every word also contributes its whole-word FNV-1a-64 key and an adjacent-word bigram key (fastText's word / wordNgram features) hashed into the same bucket space. ## Storage formats The same model in every folded-table storage format; the runtime dequantizes at load and the graph is unchanged — every variant is accuracy-identical to the f16 original within ±0.02pp. | ref | format | size | |---|---|---| | `vpermilp/spellman` (root) | f16 | 7.86 MB | | `vpermilp/spellman/int8-row` | int8, per-row scales | 4.46 MB | | `vpermilp/spellman/int8-col` | int8, per-column scales | 3.93 MB | | `vpermilp/spellman/fp8-row` | fp8 e4m3, per-row scales | 4.46 MB | | `vpermilp/spellman/fp8-col` | fp8 e4m3, per-column scales | 3.93 MB | The spellman CLI fetches any of them straight from the Hub: ```bash spellman detect --model hf:vpermilp/spellman/int8-col < text.txt ``` ## Usage This is not a standalone checkpoint: the featurizer (canonicalizing char n-grams + lexical word n-grams + signed feature hashing) lives in the runtime, so the model is consumed by the spellman Rust workspace (detector crate + CLI): ```bash hf download vpermilp/spellman --local-dir model echo "Съешь ещё этих мягких французских булок" | spellman detect # rus printf 'Қазақша\nHello\n' | spellman detect --lines # kaz / eng ``` ## Metrics | eval | accuracy | |---|---| | held-out mix (85,283 rows, pristine test) | 98.28% | | Tatoeba (37,051, out-of-domain) | 98.66% | | Tatoeba granularity ladder (word / pair / triple) | 68.5 / 87.1 / 94.1 | | wild Russian tweets (2,679; 61% @mentions, 20% URLs) | 93.73% | | throughput | ~3.5 µs/sample (fp16 JIT plan, CPU) | On identical eval rows it beats fastText lid.176 (Tatoeba 94.90% → 98.66%) and lingua 1.8 high-accuracy on the shared Cyrillic close pairs at ~30× its speed; whichlang and lingua cover only 10 and 17 of these 30 classes respectively. Against open-LID SOTA GlotLID v3 it wins the wild held-out workload (98.28 vs 96.43) and the single-word rung (68.5 vs 43.9) while running ~100× faster; GlotLID's much larger training set still wins clean out-of-domain sentences (99.25 vs 98.66). ## Training data FineWeb-2 per-language configs sampled as line-windows (ODC-BY) + FineWeb (English), ~104k Tatoeba sentences (CC BY 2.0 FR), and per-language community/parallel corpora for the weak classes (Tatar, Bashkir, Chuvash, Tuvan, Kyrgyz, Udmurt, Mari, Macedonian, Chechen, …), hygiene-filtered with twin-language protection. Training methodology and the full recipe are documented in the spellman repository (design doc + training guide).