AksharaLP-1M
This is v1 (1.0.0). AksharaLP-1M-v2 is the recommended version (v2 live 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 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]). Keep using v1 only if the smaller 4.53 MB download matters more than chat-spelling accuracy. v1 stays available for reproducibility.
The world’s 3rd most spoken language, typed on the world’s most used keyboard. In 4.5 MB.
Hindi typed in English letters → Devanagari, fully offline.
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 |
Source: Ethnologue 200 (Ethnologue: Languages of the World, 29th edition, SIL Global), 2026 — https://www.ethnologue.com/insights/ethnologue200/ (accessed 2026-10-31). Counts first- and second-language speakers.
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).
Recorded from the live demo: inference runs in a Web Worker in the browser tab.
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. |
| 🧠 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.
Best in class for its size
70.4%top-1 — higher than IndicXlit (model only) (59.2%)at 5× smaller · Aksharantar Hindi test | 70.4%top-1 — higher than IndicXlit (full package) (69.3%)at 47× smaller · Aksharantar Hindi test | 8.1 pts/MBhighest top-1 accuracy per MB among compared modelsnext: IndicXlit (model only) at 1.28 pts/MB |
87.7%right word in the first 3 suggestions — vs 59.2% top-1 for IndicXlit (model only)Aksharantar Hindi test | 87.7%right word in the first 3 suggestions — vs 69.3% top-1 for IndicXlit (full package)Aksharantar Hindi test | 5×smaller than IndicXlit (model only)8.69 MB vs 46.0 MB on disk (fp32 weights) |
47×smaller than IndicXlit (full package)8.69 MB vs 404 MB on disk (fp32 weights + 358 MB rescoring dictionary) | 219.7 msper word (p50) in the browseran 8-vCPU Intel Xeon cloud VM (headless Chrome 156, Linux) | 4.53 MBcomplete downloadcore + 1.5M-word dictionary pack · 989K parameters |
0.57 MBto start typingthe core works on its own (53.4% top-1 without the pack); the dictionary pack streams in after and is cached |
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.
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).
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

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

| 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 [69.50, 71.26] | 87.66 | 92.79 | 87.55 | 21.66 | 219.70 ms browser |
| IndicXlit (model only) | 46.0 MB fp32 weights | 59.16 [58.14, 60.13] | 79.95 | 88.29 | 67.55 | 6.29 | 48.4 ms PyTorch CPU |
| IndicXlit (full package) | 404 MB fp32 weights + 358 MB rescoring dictionary | 69.33 [68.44, 70.23] | 85.40 | 88.29 | — | — | — |

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 % [95% CI] | top-3 % | top-8 % | Val top-1 % (2-fold CV) | 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 [52.36, 54.32] | 74.52 | 83.81 | 53.92 | — | 65.35 |
| Core + 200K-word dictionary | no (measured only) | 1.13 MB | 1.76 MB | 68.38 [67.48, 69.30] | 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 [69.50, 71.26] | 87.66 | 92.79 | 69.30 | 19.65 | 87.55 |
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.
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)
<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)
hf download sourojitdotcom/AksharaLP-1M --local-dir aksharalp
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)
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

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"]
- Tokenizer. Splits words, numbers and punctuation; URLs, e-mail addresses and @mentions are kept as typed.
- 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.
- 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). 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:
Transliteration by AksharaLP (Sourojit Dhua) — https://huggingface.co/sourojitdotcom/AksharaLP-1M
Recommended in-app credit (About, Settings or Licenses screen):
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 (AI4Bharat) | CC0 (mined data) / CC-BY (manually collected data) | romanized ↔ Devanagari training pairs |
| IndicXlit (AI4Bharat) | MIT | teacher model for distillation |
| IndicCorp v2 (AI4Bharat) | CC0 | Hindi lexicon and bigram language model |
| 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
@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}
}
AksharaLP · v1.0.0 · built 2026-10-31 · Questions and feedback: open a discussion on this repository.
- Downloads last month
- 18
Datasets used to train sourojitdotcom/AksharaLP-1M
ai4bharat/Aksharantar
Space using sourojitdotcom/AksharaLP-1M 1
Evaluation results
- Top-1 accuracy on Aksharantar (Hindi test)test set self-reported70.370
- Top-3 accuracy on Aksharantar (Hindi test)test set self-reported87.660
- Top-8 accuracy on Aksharantar (Hindi test)test set self-reported92.790
- Word accuracy on Dakshina (Hindi romanized sentences)test set self-reported87.550
- Sentence exact match on Dakshina (Hindi romanized sentences)test set self-reported21.660
- CER on Dakshina (Hindi romanized sentences)test set self-reported4.810