--- license: mit language: - en - hi - bn - ta - te - mr - gu - kn - ml - pa - or - ur tags: - translation - onnx - indic - indictrans2 - browser pipeline_tag: translation library_name: onnx base_model: naklitechie/indictrans2-en-indic-dist-200M --- # IndicTrans2 200M (en→indic) — ONNX bundle for in-browser inference ONNX-exported version of [`naklitechie/indictrans2-en-indic-dist-200M`](https://huggingface.co/naklitechie/indictrans2-en-indic-dist-200M) (itself a verbatim mirror of [`ai4bharat/indictrans2-en-indic-dist-200M`](https://huggingface.co/ai4bharat/indictrans2-en-indic-dist-200M), AI4Bharat's distilled 200M en→indic model). Built for use with [Transformers.js](https://github.com/huggingface/transformers.js) and [onnxruntime-web](https://onnxruntime.ai/docs/get-started/with-javascript.html) in the browser, with fast BPE tokenizer.json files that don't require the SentencePiece WASM runtime. ## Benchmarks vs PyTorch original **Token-level AND text-level bit-exact equivalent** to the original PyTorch model at [`naklitechie/indictrans2-en-indic-dist-200M`](https://huggingface.co/naklitechie/indictrans2-en-indic-dist-200M) on greedy decoding. | Test | Pass rate | |---|---| | 528 fixtures × greedy decode, token-exact match vs PyTorch | **528/528 (100%)** | | 528 fixtures × greedy decode, text-exact match vs PyTorch | **528/528 (100%)** | Fixtures span 4 categories (generic, politics, numerals, lexicon) × 11 main Indic languages × 12 sentences each. The PyTorch baseline was captured by running the original model with `num_beams=1, do_sample=False, max_new_tokens=128`. The verification chain: ``` fp32 ONNX bundle → encoder.run + decoder.run loop (onnxruntime CPU) → output token IDs ‖ exact-match PyTorch original → model.generate(num_beams=1) → output token IDs ``` Reproducer: [`scripts/04_parity_test.py`](https://github.com/prashnam/prashnam-voice/blob/main/browser-prep/scripts/04_parity_test.py) in the source repo. Full report: `parity_report.json` in this repo. > See the int8-quantized variant at > [`naklitechie/indictrans2-en-indic-dist-200M-ONNX-int8`](https://huggingface.co/naklitechie/indictrans2-en-indic-dist-200M-ONNX-int8) > for a 4× smaller bundle (~360 MB) at the cost of ~20% sentences drifting > in word choice. Use this fp32 repo for any production / research use. ## Files | File | Purpose | Size | |---|---|---| | `encoder_model.onnx` + `.data` | encoder graph (fp32, weights externalised) | 280 MB | | `decoder_model.onnx` + `.data` | decoder first-step (no past KV in, full KV out) | 530 MB | | `decoder_with_past_model.onnx` + `.data` | decoder steps 2..N (past KV in/out) | 495 MB | | `tokenizer_src.json` | encoder-side fast tokenizer (BPE + lang-tag AddedTokens + NFKC) | 3.2 MB | | `tokenizer_tgt.json` | decoder-side fast tokenizer | 17 MB | | `tokenizer_meta.json` | dict-size cutoffs for the extended-vocab → ` ` remap | = tokenizer_meta.src_dict_size` (= 32322) must be replaced with the ` ` ID (3) before feeding to ONNX — the model's encoder embedding only goes up to 32,322. Same applies to `tokenizer_tgt.json` with `tgt_dict_size = 122,672`. The slow HF tokenizer does this implicitly via `encoder.get(token, unk_id)`. 2. **Devanagari-normalized output.** For non-Devanagari Indic languages (Tamil, Bengali, Telugu, etc.), the model emits its output in Devanagari script. AI4Bharat's `IndicProcessor.postprocess_batch` handles the script conversion. A JS port lives in the source repo at `browser-prep/js/indic_processor.js`. 3. **fp32, not yet quantized.** The bundle is ~1.3 GB total — not browser-ready for many users without quantization. q4f16 weights bring this to roughly 200 MB; tooling for that is in progress. ## Source Built via the `01_export_onnx_manual.py` → `02_build_tokenizer.py` → `03_capture_truth.py` → `04_parity_test.py` pipeline at [prashnam/prashnam-voice](https://github.com/prashnam/prashnam-voice) (`browser-prep/scripts/`). ## License MIT (preserved from upstream AI4Bharat). See `LICENSE` and `NOTICE.md`.