IYRA Akshara Tokenizer (IAT)
Linguistically-correct tokenization for six Brahmic (Indic) scripts. The tokenizer treats the Akshara (orthographic syllable) as the atomic writing unit rather than the byte. It has two layers: a rule-based Akshara segmenter (pure Unicode rules, no model) that never splits an Akshara, and a SentencePiece model trained on the segmented stream. The Python library that provides the segmenter and the high-level tokenizer lives on GitHub and PyPI, linked below.
This repository holds two model versions:
| Version | Vocab | Status | Files |
|---|---|---|---|
| v1.2 | 64,000 | current | akshara_tokenizer_v1_2.model, akshara_tokenizer_v1_2.map.json |
| v1.1 | 16,000 | legacy | akshara_tokenizer_v1_1.model, akshara_tokenizer_v1_1.vocab |
Supported scripts
| Script | Languages |
|---|---|
| Devanagari | Hindi, Sanskrit, Marathi |
| Gurmukhi | Punjabi |
| Tamil | Tamil |
| Telugu | Telugu |
| Bengali | Bengali |
| Kannada | Kannada |
What is new in v1.2: lossless round-trip
In v1.2 each Akshara the map covers is replaced by a single private-use codepoint
before SentencePiece, so no token boundary can fall inside a covered Akshara.
decode(encode(text)) is byte-identical, reconstructed from the id stream alone
with no side channel. This was verified on a 20-string probe set covering the six
scripts, mixed script, nukta forms, conjuncts, and whitespace edges (20 of 20), and
on 1,750 FLORES-200 devtest lines, 250 each from the six Indic scripts and English
(1,750 of 1,750). v1.1 could not round-trip at all, because its pipeline space-joins
aksharas and the model normalizes whitespace. 45,274 of the 64,000 v1.2 vocabulary
pieces span two or more aksharas.
Fertility
FLORES-200 devtest, tokens per whitespace-delimited word (lower is better). Numbers
match the GitHub README (benchmark_2026_07/results_v1_2.md).
| Script (language) | v1.2 (64k) | v1.1 (16k) | Qwen3-14B |
|---|---|---|---|
| Devanagari (Hindi) | 1.374 | 2.451 | 4.757 |
| Gurmukhi (Punjabi) | 1.445 | 2.684 | 7.758 |
| Tamil (Tamil) | 1.953 | 5.007 | 10.064 |
| Telugu (Telugu) | 2.001 | 3.710 | 11.406 |
| Bengali (Bengali) | 1.797 | 3.384 | 7.117 |
| Kannada (Kannada) | 2.058 | 4.166 | 11.876 |
| Overall (six Indic) | 1.717 | 3.411 | 8.398 |
| English (info) | 2.151 | 5.084 | 1.261 |
v1.2 roughly halves v1.1's token count on every Indic script and stays far below Qwen3-14B. On English, Qwen3 is more efficient, as expected for an English-centric byte-level BPE.
Akshara split rate
FLORES-200 devtest, percent of aksharas whose token boundaries fall inside them (lower is better).
| Script | v1.2 (64k) | v1.1 (16k) |
|---|---|---|
| Devanagari | 0.0945 | 1.6906 |
| Gurmukhi | 0.3345 | 0.9348 |
| Tamil | 0.0000 | 0.1467 |
| Telugu | 0.0643 | 3.6511 |
| Bengali | 0.0721 | 1.7465 |
| Kannada | 0.1154 | 3.6202 |
| Overall | 0.1109 | 1.8559 |
For v1.2, a covered akshara is one codepoint, so the residual is only the coverage-trim tail, not vocabulary pressure. v1.2 byte-fallback is near zero on all six scripts (0.00 to 0.04 percent).
The mapping table is required
The v1.2 ids are not decodable without the mapping table. Each piece is built from
private-use codepoints, and the map (akshara_tokenizer_v1_2.map.json) translates
those back to aksharas. The map ships next to the model and is bound to it by
sha256, so loading refuses a mismatched pair. Always fetch the model and its map
together, and do not store ids without both.
Versions and compatibility
v1.1 and v1.2 produce different, incompatible id streams. Nothing in the API records
which model produced a stream, so decoding v1.1 ids with the v1.2 model returns
silent garbage rather than an error. If you already have a corpus tokenized with
v1.1, keep using v1.1 (the files remain in this repository, and PyPI 1.1.0
installs it) rather than upgrading in place.
Gurmukhi precomposed nukta letters
Precomposed Gurmukhi nukta letters (U+0A36 SHA, U+0A5E FA, U+0A59 KHHA) encode to 2 or 3 pieces rather than 1, because the map holds their decomposed equivalents. This costs tokens, never correctness: these aksharas carry zero byte-fallback and round-trip remains byte-identical. On FLORES-200 it affects 0.33 percent of Gurmukhi aksharas. Users who prefer efficiency over byte-identity may NFC-normalize their input before encoding.
Usage (v1.2, fetching files from this repo)
Install the library (it provides the segmenter and the AksharaTokenizer class),
then download both v1.2 files and load them together:
pip install "akshara-tokenizer[model]"
from huggingface_hub import hf_hub_download
from akshara_tokenizer import AksharaTokenizer
repo = "GursimranSinghBasra/akshara-tokenizer"
model_path = hf_hub_download(repo, "akshara_tokenizer_v1_2.model")
map_path = hf_hub_download(repo, "akshara_tokenizer_v1_2.map.json")
tok = AksharaTokenizer.from_files(model_path, map_path)
tok.encode("न्याय दर्शन") # [7645, 531, 7572]
tok.decode([7645, 531, 7572]) # "न्याय दर्शन" (byte-identical)
tok.pieces("ਪੰਜਾਬ") # ["ਪੰਜਾਬ"]
The simpler path is PyPI: pip install "akshara-tokenizer[model]" already bundles
the v1.2 model and map, so AksharaTokenizer.load() works with no download.
The rule-based segmenter alone needs no model:
from akshara_tokenizer import segment_aksharas, count_aksharas
segment_aksharas("ਨਿਆਯ ਦਰਸ਼ਨ")
# ['ਨਿ', 'ਆ', 'ਯ', ' ', 'ਦ', 'ਰ', 'ਸ਼', 'ਨ']
count_aksharas("ਪੰਜਾਬ")
# 3
Usage (v1.1, legacy)
v1.1 has no map and does not round-trip. Fetch the model and use the space-join pipeline:
from huggingface_hub import hf_hub_download
import sentencepiece as spm
from akshara_tokenizer import segment_aksharas
model_path = hf_hub_download("GursimranSinghBasra/akshara-tokenizer", "akshara_tokenizer_v1_1.model")
sp = spm.SentencePieceProcessor(model_file=model_path)
ids = sp.encode(" ".join(segment_aksharas("न्याय दर्शन")))
Links
- Library, PyPI package, and reproducible benchmarks: https://github.com/1322Guru/akshara-tokenizer
- PyPI: https://pypi.org/project/akshara-tokenizer/ (
pip install "akshara-tokenizer[model]") - Fertility and split-rate methodology and raw numbers:
benchmark_2026_07/results_v1_2.mdin the GitHub repository.
Patent and copyright
Patent pending: Indian provisional patent application 202611071450. Copyright 2026 Gursimran Singh.
License
Apache License 2.0. See LICENSE and NOTICE.