File size: 31,411 Bytes
843b037 5d04d17 843b037 5d04d17 843b037 5d04d17 843b037 5d04d17 843b037 9ac4892 843b037 9ac4892 843b037 9ac4892 843b037 9ac4892 843b037 9ac4892 843b037 9ac4892 843b037 5d04d17 843b037 | 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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | ---
license: apache-2.0
new_version: sourojitdotcom/AksharaLP-1M-v2
language:
- hi
- en
pipeline_tag: translation
tags:
- transliteration
- hindi
- devanagari
- romanized-hindi
- on-device
- browser
- javascript
- tiny
- indic
- input-method
- keyboard
- offline
- aksharalp
datasets:
- ai4bharat/Aksharantar
- ai4bharat/IndicCorpV2
metrics:
- accuracy
- cer
model-index:
- name: AksharaLP-1M
results:
- task:
type: translation
name: Romanized Hindi → Devanagari transliteration (word level)
dataset:
type: ai4bharat/Aksharantar
name: Aksharantar (Hindi test)
split: test
metrics:
- type: accuracy
name: Top-1 accuracy
value: 70.37
- type: accuracy
name: Top-3 accuracy
value: 87.66
- type: accuracy
name: Top-8 accuracy
value: 92.79
- task:
type: translation
name: Romanized Hindi → Devanagari transliteration (sentence level)
dataset:
type: google/dakshina
name: Dakshina (Hindi romanized sentences)
split: test
metrics:
- type: accuracy
name: Word accuracy
value: 87.55
- type: exact_match
name: Sentence exact match
value: 21.66
- type: cer
name: CER
value: 4.81
---
<p align="center">
<img src="https://huggingface.co/sourojitdotcom/AksharaLP-1M/resolve/main/assets/banner.png" alt="AksharaLP — Hindi transliteration in 4.53 MB" width="100%"/>
</p>
<p align="center">
<a href="https://huggingface.co/spaces/sourojitdotcom/AksharaLP-demo"><img src="https://img.shields.io/badge/%F0%9F%A4%97%20Live%20demo-Space-6d4aff" alt="Live demo"/></a>
<img src="https://img.shields.io/badge/core-0.57%20MB-6366f1" alt="Core download size"/>
<img src="https://img.shields.io/badge/with%20dictionary-4.53%20MB-a855f7" alt="Complete download size"/>
<img src="https://img.shields.io/badge/parameters-989K-ec4899" alt="Parameters"/>
<img src="https://img.shields.io/badge/runs-100%25%20on--device-10b981" alt="On-device"/>
<img src="https://img.shields.io/badge/license-Apache--2.0-f97316" alt="License"/>
</p>
# AksharaLP-1M
> [!IMPORTANT]
> **This is v1 (1.0.0). [AksharaLP-1M-v2](https://huggingface.co/sourojitdotcom/AksharaLP-1M-v2) is the recommended version** ([v2 live demo](https://huggingface.co/spaces/sourojitdotcom/AksharaLP-v2-demo)).
> Same 989K-parameter core architecture; v2 ships a 3M-word dictionary pack (v1: 1.5M) and a reranker refitted for chat-style spellings (*h*, *nhi*, *bht*).
>
> | | v1 (this repo) | v2 |
> |---|---|---|
> | Complete download (gzipped) | **4.53 MB** | 7.92 MB |
> | Aksharantar top-1 / top-3 / top-8 % | **70.37** / 87.66 / 92.79 | 70.04 / **88.31** / **93.63** |
> | Core-only top-1 % | 53.36 | **56.01** |
> | Dakshina word acc / sentence EM % | 87.55 / 21.66 | **89.02** / **25.70** |
> | Chat-spelling sentences, word acc % (480 held-out) | 80.16 | **91.54** |
> | Browser latency / word (p50) | 219.7 ms | **206.0 ms** |
>
> <sub>Numbers from the two model cards; the chat-spelling comparison is from the v2 card. Top-1 on Aksharantar differs by 0.33 points with overlapping 95% CIs ([69.50, 71.26] vs [69.16, 70.90]).</sub>
> Keep using v1 only if the smaller 4.53 MB download matters more than chat-spelling accuracy. v1 stays available for reproducibility.
<h3 align="center">The world’s 3rd most spoken language, typed on the world’s most used keyboard. In 4.5 MB.</h3>
<p align="center"><b>Hindi typed in English letters → Devanagari, fully offline.</b></p>
### Why it matters
| 🌏 **#3** | 🗣️ **611M** | 📦 **4.5 MB** |
|:---:|:---:|:---:|
| most spoken language in the world | people speak Hindi (first or second language) | is all it takes to type it — no server, no GPU |
<sub>Source: Ethnologue 200 (Ethnologue: Languages of the World, 29th edition, SIL Global), 2026 — <a href="https://www.ethnologue.com/insights/ethnologue200/">https://www.ethnologue.com/insights/ethnologue200/</a> (accessed 2026-10-31). Counts first- and second-language speakers.</sub>
On a Latin (QWERTY) keyboard, Hindi is often typed in English letters: *“kal meeting hai, kaise ho?”*. AksharaLP-1M turns that into
proper Devanagari — accurately, in context, and entirely offline in the browser. It transliterates (changes the script); it does not translate.
AksharaLP-1M is the 989K-parameter member of the **AksharaLP** family of tiny transliteration models.
For *“kal meeting hai, kaise ho?”* AksharaLP writes **कल मीटिंग है, कैसे हो?**, the way a Hindi speaker would.
It ships in two tiers: a **0.57 MB core** (character Transformer with 989K parameters, reranker and runtime) that works on its own,
and a **3.97 MB dictionary pack** (1.5M-word lexicon and sentence language model) that the runtime fetches on first use and caches.
The complete package is **4.53 MB** to download.
The complete package is **5× smaller** than the model weights of IndicXlit, the most widely used open Indic transliteration model,
and **47× smaller** than IndicXlit with its rescoring dictionary — while scoring **higher top-1 than both** on Aksharantar (70.37% vs 59.16% for the model and 69.33% for the full package; the gap to the full package is within overlapping 95% CIs).
<p align="center">
<a href="https://huggingface.co/spaces/sourojitdotcom/AksharaLP-demo"><img src="https://huggingface.co/sourojitdotcom/AksharaLP-1M/resolve/main/assets/typing.gif" alt="Live typing demo" width="88%"/></a>
<br/><sub>Recorded from the <a href="https://huggingface.co/spaces/sourojitdotcom/AksharaLP-demo">live demo</a>: inference runs in a Web Worker in the browser tab.</sub>
</p>
## Highlights
| | |
|---|---|
| 🪶 **Extremely small** | 0.57 MB core + 3.97 MB dictionary pack = 4.53 MB gzipped (8.69 MB on disk); 989K parameters, 4-bit weights. Fits in a keyboard app, a browser extension or a web page. |
| 🎯 **Accurate** | With the dictionary pack: 70.37% top-1 / 87.66% top-3 on the Aksharantar Hindi test set (9,991 words); 87.55% word accuracy on Dakshina sentences. Core-only numbers are in [Variants](#variants-core-only-vs-core--dictionary). |
| 🧠 **Context-aware** | A compact bigram language model picks the right word from its neighbours: the same *main* becomes मैं or में. |
| 📥 **Starts fast, degrades gracefully** | The core is enough to start typing; the dictionary pack streams in after and is cached. If the pack cannot be fetched, the runtime keeps working with the core alone. |
| 🔒 **Private & offline** | Pure JavaScript, zero dependencies, no server. Nothing you type leaves the device; works offline after first load. |
| ⚡ **Fast** | 219.7 ms per word (p50) in the browser on an 8-vCPU Intel Xeon cloud VM (headless Chrome 156, Linux). |
## What it brings on-device
Everything below happens on the user’s own phone or laptop: the model is a set of static files plus a dependency-free JavaScript runtime.
Each example output was produced by the released runtime when this card was built.
<table>
<tr>
<td width="33%" valign="top">
### ✈️ Fully offline
No network after the first load, so it keeps working in airplane mode, in a lift, or on a train.
`flight mein hoon, land karke call karta hoon`<br/>→ **फ्लाइट में हूं, लैंड करके कॉल करता हूं**
</td>
<td width="33%" valign="top">
### 🔒 Private by design
Text never leaves the device: no API call, no logging server. Suited to banking, health and personal chat.
`mera account balance kitna hai`<br/>→ **मेरा अकाउंट बैलेंस कितना है**<br/>
`doctor ne din mein do baar dawai lene ko kaha`<br/>→ **डॉक्टर ने दिन में दो बार दवाई लेने को कहा**
</td>
<td width="33%" valign="top">
### 🌐 Runs wherever JavaScript runs
A browser tab, an Android or iOS WebView, an installable PWA, or Node.js. CPU only: no GPU, no server, no inference bill.
`namaste, aapka swagat hai`<br/>→ **नमस्ते, आपका स्वागत है**
</td>
</tr>
<tr>
<td width="33%" valign="top">
### ⚡ Real-time, as you type
The sentence is re-decoded on every keystroke in a Web Worker, and earlier words are corrected as context arrives:
`main` → मैं<br/>
`main theek` → मैं ठीक<br/>
`main theek hoon` → **मैं ठीक हूं**
<sub>Browser latency: 219.7 ms per word (p50) on an 8-vCPU Intel Xeon cloud VM (headless Chrome 156, Linux).</sub>
</td>
<td width="33%" valign="top">
### ⌨️ Keyboard & input-box integration
Wire it to any `<input>` or `<textarea>`: chat, search, forms, CRM notes, customer-support replies. One call per keystroke: `transliterate(text, {k})`.
`aapka refund teen din mein aa jayega`<br/>→ **आपका रिफंड तीन दिन में आ जाएगा**
</td>
<td width="33%" valign="top">
### 🏷️ Brands your way
English words inside Hindi sentences are transliterated by the same model. Two writing styles for the same input:
Default → **कल व्हाट्सएप पे मीटिंग है**<br/>
Strict (brands stay in Latin) → **कल whatsapp पे मीटिंग है**
</td>
</tr>
<tr>
<td width="33%" valign="top">
### ☰ Top-k suggestions
Ranked candidates for every word, ready for a suggestion bar or candidate picker. Picking one re-decodes the rest of the sentence.
`main` → <b>मैं</b> · मैन · मेन · माइन · में
</td>
<td width="33%" valign="top">
### 📶 Built for Bharat
A 0.57 MB core to start, 4.53 MB in total, downloaded once and cached; after that, patchy or missing connectivity does not matter. Pure JavaScript on the CPU, with no GPU or native code, designed with entry-level Android phones in mind.
`signal nahi aa raha, baad mein baat karte hain`<br/>→ **सिग्नल नही आ रहा, बाद में बात करते हैं**
</td>
<td width="33%" valign="top">
### ₹0 per call at scale
Inference runs on your users’ devices, so there are no per-request API fees and no GPU servers to scale. Serving is static files from any CDN. Apache-2.0: free for commercial use.
`mera order kab tak deliver hoga`<br/>→ **मेरा ऑर्डर कब तक डिलीवर होगा**
</td>
</tr>
</table>
## Best in class for its size
<table>
<tr><td align="center" valign="top" width="33%"><h2>70.4%</h2><b>top-1 — higher than IndicXlit (model only) (59.2%)</b><br/><sub>at 5× smaller · Aksharantar Hindi test</sub></td><td align="center" valign="top" width="33%"><h2>70.4%</h2><b>top-1 — higher than IndicXlit (full package) (69.3%)</b><br/><sub>at 47× smaller · Aksharantar Hindi test</sub></td><td align="center" valign="top" width="33%"><h2>8.1 pts/MB</h2><b>highest top-1 accuracy per MB among compared models</b><br/><sub>next: IndicXlit (model only) at 1.28 pts/MB</sub></td></tr>
<tr><td align="center" valign="top" width="33%"><h2>87.7%</h2><b>right word in the first 3 suggestions — vs 59.2% top-1 for IndicXlit (model only)</b><br/><sub>Aksharantar Hindi test</sub></td><td align="center" valign="top" width="33%"><h2>87.7%</h2><b>right word in the first 3 suggestions — vs 69.3% top-1 for IndicXlit (full package)</b><br/><sub>Aksharantar Hindi test</sub></td><td align="center" valign="top" width="33%"><h2>5×</h2><b>smaller than IndicXlit (model only)</b><br/><sub>8.69 MB vs 46.0 MB on disk (fp32 weights)</sub></td></tr>
<tr><td align="center" valign="top" width="33%"><h2>47×</h2><b>smaller than IndicXlit (full package)</b><br/><sub>8.69 MB vs 404 MB on disk (fp32 weights + 358 MB rescoring dictionary)</sub></td><td align="center" valign="top" width="33%"><h2>219.7 ms</h2><b>per word (p50) in the browser</b><br/><sub>an 8-vCPU Intel Xeon cloud VM (headless Chrome 156, Linux)</sub></td><td align="center" valign="top" width="33%"><h2>4.53 MB</h2><b>complete download</b><br/><sub>core + 1.5M-word dictionary pack · 989K parameters</sub></td></tr>
<tr><td align="center" valign="top" width="33%"><h2>0.57 MB</h2><b>to start typing</b><br/><sub>the core works on its own (53.4% top-1 without the pack); the dictionary pack streams in after and is cached</sub></td></tr>
</table>
**Accuracy per MB** (top-1 on Aksharantar Hindi test ÷ on-disk size; systems measured by us with the same harness):
| # | System | On disk | Top-1 % | Top-1 pts per MB |
|---|---|---|---|---|
| 1 | **AksharaLP-1M** | 8.69 MB | 70.37 | **8.10** |
| 2 | IndicXlit (model only) | 46.0 MB | 59.16 | 1.28 |
| 3 | IndicXlit (full package) | 404 MB | 69.33 | 0.17 |
> 🏆 No compared model is both smaller and more accurate: AksharaLP-1M sits on the size–accuracy frontier.
<sub>Every tile above is generated by the release build from measured results and shown only if its rule holds (rules and outcomes are logged in the build report).</sub>
## What it does — real outputs
Every output below was produced by the released runtime (`aksharalp.mjs`) and the files in this repository when this card was built.
| Feature | You type | AksharaLP writes |
|---|---|---|
| Everyday Hindi | `kaise ho` | **कैसे हो** |
| Everyday Hindi | `mujhe bhookh lagi hai` | **मुझे भूख लगी है** |
| Context — *main* = “I” | `main theek hoon` | **मैं ठीक हूं** |
| Context — *main* = “in” | `ghar main kaun hai` | **घर में कौन है** |
| English words in Hindi | `kal office mein meeting hai` | **कल ऑफिस में मीटिंग है** |
| English words in Hindi | `whatsapp pe message karo` | **व्हाट्सएप पे मेसेज करो** |
| Acronyms | `sbi` | **एसबीआई** |
| Acronyms | `SBI ka ATM kahan hai` | **एसबीआई का एटीएम कहां है** |
| English words | `please mujhe call karna` | **प्लीज मुझे कॉल करना** |
| Kept as-is | `@rahul 5 baje milte hain, link: www.example.com` | **@rahul 5 बजे मिलते हैं, लिंक: www.example.com** |
### Two writing styles
The same sentence in each mode:
| Mode | `kal whatsapp pe meeting ka link bhej dena` |
|---|---|
| Default | कल व्हाट्सएप पे मीटिंग का लिंक भेज देना |
| Strict | कल whatsapp पे मीटिंग का लिंक भेज देना |
* **Default** — every word, English ones included, is written in Devanagari.
* **Strict** — brand and product names stay in Latin script.
### Top-k suggestions
Every word comes with ranked alternatives, ready for a keyboard suggestion bar:
| Input | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| `kaise` | **कैसे** | केसे | कइसे | कैस | किसे |
| `main` | **मैं** | मैन | मेन | माइन | में |
| `dhanyavaad` | **धन्यवाद** | धन्यावाद | धन्यवाद् | धान्यवाद | धन्यवादी |
### Core only vs. core + dictionary pack
The same inputs through the core alone (pack not loaded) and with the pack, from the released runtime:
| You type | Core only | Core + dictionary pack |
|---|---|---|
| `main theek hoon` | मैं थीक हूं | **मैं ठीक हूं** |
| `ghar main kaun hai` | घर मैं कौं है | **घर में कौन है** |
| `mujhe bhookh lagi hai` | मुझे भूख लगी है | **मुझे भूख लगी है** |
| `whatsapp pe message karo` | व्हाटसएप पीई मेसेज करो | **व्हाट्सएप पे मेसेज करो** |
| `doctor ne dawai lene ko kaha` | डॉक्टर ने दवाई लेने को कह | **डॉक्टर ने दवाई लेने को कहा** |
## Small by design
<p align="center"><img src="https://huggingface.co/sourojitdotcom/AksharaLP-1M/resolve/main/assets/chart_size.png" alt="Size comparison" width="92%"/></p>
What you download:
| File | What it is | On disk | gzipped |
|---|---|---|---|
| `xlit.q4` | core: transliteration Transformer, 4-bit weights | 589 KB | 544 KB |
| `params.json` | core: reranker weights + decoding settings | 12 KB | 5 KB |
| `aksharalp.mjs` | core: JavaScript runtime (zero dependencies) | 52 KB | 18 KB |
| **Core total** | works on its own | **0.65 MB** | **0.57 MB** |
| `dict/lex.bin` | dictionary pack: Hindi lexicon (trie + unigram scores) | 5,647 KB | 3,137 KB |
| `dict/lm.bin` | dictionary pack: word-bigram language model, 4-bit | 2,373 KB | 826 KB |
| `dict/params.json` | dictionary pack: reranker weights + decoding settings used with the pack | 12 KB | 5 KB |
| **Dictionary pack total** | fetched on first use, then cached | **8.03 MB** | **3.97 MB** |
| **Complete package** | core + pack | **8.69 MB** | **4.53 MB** |
For comparison, IndicXlit’s fp32 model weights are 46.0 MB and its official rescoring dictionary adds another 358 MB.
General-purpose LLMs that can transliterate are larger still, with hundreds of millions of parameters or more, and typically need a server or a GPU.
## Benchmarks
<p align="center"><img src="https://huggingface.co/sourojitdotcom/AksharaLP-1M/resolve/main/assets/chart_accuracy.png" alt="Accuracy comparison" width="92%"/></p>
| System | Download | Aksharantar top-1 % | top-3 % | top-8 % | Dakshina word acc % | Dakshina sentence EM % | Latency / word (p50) |
|---|---|---|---|---|---|---|---|
| **AksharaLP-1M** (core + dictionary pack) | **4.53 MB** | **70.37** <sub>[69.50, 71.26]</sub> | **87.66** | **92.79** | **87.55** | **21.66** | **219.70 ms** <sub>browser</sub> |
| IndicXlit (model only) | 46.0 MB <sub>fp32 weights</sub> | 59.16 <sub>[58.14, 60.13]</sub> | 79.95 | 88.29 | 67.55 | 6.29 | 48.4 ms <sub>PyTorch CPU</sub> |
| IndicXlit (full package) | 404 MB <sub>fp32 weights + 358 MB rescoring dictionary</sub> | 69.33 <sub>[68.44, 70.23]</sub> | 85.40 | 88.29 | — | — | — |
<p align="center"><img src="https://huggingface.co/sourojitdotcom/AksharaLP-1M/resolve/main/assets/chart_tradeoff.png" alt="Accuracy versus size" width="80%"/></p>
## Variants: core only vs. core + dictionary
The dictionary pack is optional. Each row below was scored once on the Aksharantar Hindi test set (9,991 words, beam 8); settings and the size of the
smaller dictionary were chosen on the validation set only. The 200K-word pack is measured for comparison but **not shipped** in this release.
| Variant | Shipped | Download (gz) | On disk | Test top-1 % <sub>[95% CI]</sub> | top-3 % | top-8 % | Val top-1 % <sub>(2-fold CV)</sub> | Test top-1 % with test words removed from the dictionary | Dakshina sentences word acc % |
|---|---|---|---|---|---|---|---|---|---|
| **Core only** | yes | 0.57 MB | 0.65 MB | 53.36 <sub>[52.36, 54.32]</sub> | 74.52 | 83.81 | 53.92 | — | 65.35 |
| Core + 200K-word dictionary | no (measured only) | 1.13 MB | 1.76 MB | 68.38 <sub>[67.48, 69.30]</sub> | 85.70 | 91.58 | 67.35 | 33.33 | 86.89 |
| **Core + 1.5M-word dictionary pack** | yes | 4.53 MB | 8.69 MB | 70.37 <sub>[69.50, 71.26]</sub> | 87.66 | 92.79 | 69.30 | 19.65 | 87.55 |
<sub>The “test words removed” column re-runs the same system with every Aksharantar test reference word deleted from the dictionary, so the dictionary cannot
simply look up the answer; it shows how much of the gain comes from dictionary coverage (see the caveat below). Dakshina sentences: 4,976 romanized sentences.</sub>
**How we measured.** All systems were run by us on the same machine with the same scoring script (Unicode NFC, punctuation and danda normalised).
Word-level: Aksharantar Hindi test set, 9,991 unique romanized words, beam 8 for every system; top-k = the reference appears among the first k candidates.
Sentence-level: Dakshina romanized Hindi sentences (4,976 sentences); word accuracy, sentence exact match, CER and WER.
IndicXlit “model only” is the released transformer checkpoint; “full package” adds rescoring with the official 4.2M-word dictionary (α = 0.9; our re-implementation of the released engine, which reproduces the published scores).
Browser latency is per word with the dictionary pack loaded, single tab, measured in headless Chrome on an 8-vCPU Intel Xeon cloud VM (headless Chrome 156, Linux); IndicXlit latency is PyTorch fp32 on one CPU thread and is shown for reference only (different runtime).
> **Caveat.** IndicXlit was trained on Aksharantar, so its Aksharantar test scores may benefit from train/test overlap. Our training pairs contain no Aksharantar test or validation native words (checked). The 1.5M-word dictionary pack is built from IndicCorp v2 text and naturally contains most test words: with every test reference word removed from the dictionary the same system scores 19.65% top-1 (47.27% top-3, 73.06% top-8), and the core alone scores 53.36% top-1. All tuning, the reranker fit and the choice of dictionary size used the validation set only; each test number comes from a single run.
## Quickstart
### Browser (ES module)
```html
<script type="module">
import { AksharaLP } from "https://huggingface.co/sourojitdotcom/AksharaLP-1M/resolve/main/aksharalp.mjs";
const base = "https://huggingface.co/sourojitdotcom/AksharaLP-1M/resolve/main/";
// core first (0.57 MB): usable immediately
const aklp = await AksharaLP.load(base, { dict: false });
// then the dictionary pack (3.97 MB): fetched once, kept in the Cache API; false = stays core-only
const ok = await aklp.loadDict();
const r = aklp.transliterate("kal meeting hai, kaise ho?");
console.log(r.output); // कल मीटिंग है, कैसे हो? (with the pack)
console.log(r.tokens[0].candidates); // ranked alternatives for the first word
</script>
```
`AksharaLP.load(base)` without options loads the core and the pack together. For production, copy the files (including `dict/`) into your app and load them from your own origin (they are static and cache well); run the model in a Web Worker as the demo Space does.
### Node.js (≥ 18)
```bash
hf download sourojitdotcom/AksharaLP-1M --local-dir aksharalp
```
```js
import { loadFromDir } from "./aksharalp/aksharalp.mjs";
const aklp = await loadFromDir("./aksharalp/"); // core + dict/ pack; { dict: false } for core only
console.log(aklp.transliterate("main theek hoon", { mode: "conversational" }).output); // मैं ठीक हूं
console.log(aklp.word("kaise", 5)); // top-5 candidates with scores
```
### Python (reference implementation)
```python
from huggingface_hub import snapshot_download
import sys
path = snapshot_download("sourojitdotcom/AksharaLP-1M")
sys.path.insert(0, f"{path}/python")
from bhc.translit2 import BhcTranslit2 # needs numpy + torch (CPU)
xl = BhcTranslit2(path) # use_dict=False for core only
print(xl.convert("kal meeting hai, kaise ho?"))
print(xl.translit_words(["kaise", "namaste"], k=5))
```
The Python package is the reference used for training and evaluation; the JavaScript runtime reproduces it exactly
(JS/Python parity test — core only: identical candidate sets and top-1 for 196/196 words, max feature difference 9.1e-06; with the dictionary pack: identical candidate sets and top-1 for 196/196 words, max feature difference 3.2e-05).
### API at a glance
| Call | Returns |
|---|---|
| `AksharaLP.load(baseUrl, {dict, cache})` | engine (fetches `manifest.json` and the core; with `dict: true`, the default, also the dictionary pack) |
| `loadDict({cache})` | fetches the dictionary pack (Cache API name `"aksharalp-dict"` by default) and attaches it; returns `false` and keeps the core working if it fails |
| `attachDict({lex, lm, params})` | attaches a pack you fetched yourself (e.g. from IndexedDB or app assets) |
| `transliterate(text, {mode, context, k, overrides})` | `{output, tokens[], ms}`; each token has `text, output, source, candidates[]`; `mode` is `"conversational"` (default) or `"strict"` |
| `word(romanWord, k)` | top-k `{text, score}` for one word |
| `info()` | parameter count, lexicon size, bytes on disk / gzipped, `hasDict`, `dictError` |
`overrides` pins a user-chosen suggestion (`{tokenStartOffset: "मैं"}`) and re-decodes the rest of the sentence around it.
## How it works
<p align="center"><img src="https://huggingface.co/sourojitdotcom/AksharaLP-1M/resolve/main/assets/architecture.png" alt="Architecture" width="100%"/></p>
```mermaid
flowchart LR
A["Romanized Hindi text"] --> T["① Tokenizer<br/>URLs, @mentions, numbers kept"]
T -->|Strict mode: brand| P["kept in Latin"]
T -->|word| X["② Char Transformer (core)<br/>d=128, 3+2 layers, 4 heads, FFN 384 · 4-bit · 989K"]
X --> C["Candidates<br/>free beam + acronyms<br/>(+ lexicon-trie beam + skeleton lookups with the pack)"]
C --> R["Learned reranker<br/>24-feature MLP"]
R --> V["③ Sentence Viterbi (pack)<br/>bigram LM · 1.5M words"]
P --> V
V --> O["Devanagari + top-k"]
```
1. **Tokenizer.** Splits words, numbers and punctuation; URLs, e-mail addresses and @mentions are kept as typed.
2. **Transliteration (core).** A character-level encoder–decoder Transformer (d=128, 3+2 layers, 4 heads, FFN 384) proposes spellings with a free beam; letter-name acronyms are added and scored by the same model. With the dictionary pack, a second beam constrained to the 1.5M-word Hindi lexicon trie and consonant-skeleton lookups add in-vocabulary candidates. A small learned reranker (24 features → 16 hidden units → 1, fitted on the validation set) orders the candidates; the core and the pack each carry their own reranker weights.
3. **Sentence context (pack).** A 4-bit quantized word-bigram language model (300K bigrams) runs Viterbi over the candidate lattice to choose the most fluent sentence. Core-only mode picks each word independently.
English words inside Hindi sentences go through the same model (Default) or, for brand names, stay in Latin script (Strict).
### Files
| File | Contents |
|---|---|
| `xlit.q4` | core: transliteration Transformer, 4-bit weights |
| `params.json` | core: reranker weights + decoding settings |
| `dict/lex.bin` | dictionary pack: Hindi lexicon (trie + unigram scores) |
| `dict/lm.bin` | dictionary pack: word-bigram language model, 4-bit |
| `dict/params.json` | dictionary pack: reranker weights + decoding settings used with the pack |
| `manifest.json` | file list, sizes, checksums (core + pack) |
| `aksharalp.mjs` | core: JavaScript runtime (zero dependencies) |
| `aksharalp.min.mjs` | same runtime, minified (attribution header preserved) |
| `python/` | reference Python implementation (numpy + PyTorch) |
| `LICENSE`, `NOTICE` | Apache-2.0 and third-party attributions |
## Intended use
* Hindi input methods: mobile and desktop keyboards, browser extensions, chat and messaging apps, search boxes.
* Converting romanized Hindi text (chat logs, social posts, transcripts) to Devanagari for downstream NLP.
* Privacy-sensitive or offline settings where text must not leave the device.
## Limitations
* **Hindi only.** Other Indic languages and scripts are not supported.
* **Names and rare words.** Proper nouns, rare or very long words, and unusual spellings are the main source of errors. Check the top-k list.
* **Ambiguity.** Some romanizations have several valid Devanagari spellings (e.g. हूं / हूँ). The model follows the most common written form, which may differ from a reference.
* **Short context.** The language model sees one word on each side (bigram), so long-range agreement is not modelled.
* **Core only is less accurate.** Without the dictionary pack, top-1 accuracy drops substantially (see [Variants](#variants-core-only-vs-core--dictionary)). Load the pack when you can.
* **Dictionary coverage.** Much of the accuracy with the pack comes from the lexicon: with every test reference word removed from it, top-1 falls well below the core-only score. Words outside the lexicon (new names, slang, rare spellings) are harder.
* **English words and language tags.** This release has no word-level language identifier and no loanword lexicon: English words are transliterated phonetically by the same model and can look unusual, and tokens are not tagged Hindi / English.
* **Short ambiguous words.** Without a loanword lexicon, short words that are both English and Hindi can go the wrong way in context (for example, in our tests *call* sometimes came out as कल and *do* as डॉ). Check the top-k list.
* **Chat-speak.** Heavy abbreviation (e.g. *kr, rhe, btw*) is handled only partly.
* **Speed** depends on the device. Very old phones may see higher per-word latency than reported here.
## License & attribution
**Commercial use is allowed.** Code and model weights are released under the **Apache License 2.0** (see `LICENSE`), Copyright 2026 Sourojit Dhua.
You may use, modify and ship AksharaLP-1M in commercial products, free of charge.
**Attribution is required when you redistribute it.** Apache-2.0 §4(d) requires every redistribution of the model or a derivative
(shipping the files in an app, web page, browser extension or SDK; publishing a fine-tuned, quantized or converted version)
to include the `NOTICE` file, and the JavaScript runtime keeps its `/*! … */` attribution header, including the minified `aksharalp.min.mjs`.
Please use this attribution text:
```text
Transliteration by AksharaLP (Sourojit Dhua) — https://huggingface.co/sourojitdotcom/AksharaLP-1M
```
**Recommended in-app credit** (About, Settings or Licenses screen):
```html
Hindi typing powered by <a href="https://huggingface.co/sourojitdotcom/AksharaLP-1M">AksharaLP by Sourojit Dhua</a>
```
Third-party data used to build the model is credited in `NOTICE`:
| Source | License | Used for |
|---|---|---|
| [Aksharantar](https://huggingface.co/datasets/ai4bharat/Aksharantar) (AI4Bharat) | CC0 (mined data) / CC-BY (manually collected data) | romanized ↔ Devanagari training pairs |
| [IndicXlit](https://github.com/AI4Bharat/IndicXlit) (AI4Bharat) | MIT | teacher model for distillation |
| [IndicCorp v2](https://github.com/AI4Bharat/IndicBERT/tree/main#indiccorp-v2) (AI4Bharat) | CC0 | Hindi lexicon and bigram language model |
| [CMUdict](https://github.com/cmusphinx/cmudict) (Carnegie Mellon University) | BSD-2-Clause-style | English word cues |
Fonts in the demo Space (Inter, Noto Sans Devanagari) are under the SIL Open Font License 1.1.
## Citation
```bibtex
@software{dhua_aksharalp_2026,
author = {Dhua, Sourojit},
title = {{AksharaLP}: Tiny, Context-Aware Hindi Transliteration for the Browser},
year = {2026},
version = {1.0.0},
url = {https://huggingface.co/sourojitdotcom/AksharaLP-1M},
license = {Apache-2.0}
}
```
<sub>AksharaLP · v1.0.0 · built 2026-10-31 · Questions and feedback: open a discussion on this repository.</sub>
|