File size: 4,010 Bytes
f16b2bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
04bce66
 
 
f16b2bf
 
 
 
04bce66
 
 
 
 
20aed59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f16b2bf
 
 
04bce66
 
 
f16b2bf
 
 
 
 
 
 
 
 
 
 
04bce66
 
 
 
 
f16b2bf
 
04bce66
 
 
 
 
 
f16b2bf
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
---
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).