Skip to main content

A compact, from-scratch English↔Khmer neural machine translation model.

Project description

Netra Lab Netra Lab

GitHub | Model Download | Dataset Download | Inference Space |

A Compact Bidirectional Encoder-Decoder Transformer-Based Model for English-Khmer Translation

Inference Speed Benchmark on CPU Using Greedy, and Beam Search Decoding Strategy

1. Abstract

This repository present Netra-NMT a 90M-parameter encoder-decoder transformer-based model trained on 220 million tokens of English-Khmer parallel text (4.2M bidirectional examples). The encoder uses bidirectional self-attention, much like BERT, to capture global contextual representation. The decoder perform autoregressive generation through causal self-attention and encoder-decoder cross attention.

Unlike traditional transformer block, Netra-NMT incorporates several architectural improvements, including Pre-Layer Normalization (Pre-LN) for stable optimization, SwiGLU feed-forward networks for enhanced representational capacity, and weight tying between the decoder embedding layer and output projection head to reduce parameter redundancy.

2. Dataset

Netra-NMT was trained on 220 million tokens drawn from approximately 2.4 million unique English-Khmer sentence pairs (4.2 million examples after bidirectional augmentation). The corpus combines LLM-generated synthetic data with web-crawled parallel text, spanning legal, literary, medical, technical, and conversational domains.

2.1 Sources

Dataset Type Pairs Domains
Darayut/khmer-english-pairs-raw Synthetic 200K Legal, Literary, Governmental
lyfeyvutha/nllb-en-km-316K Synthetic 316K General
KrorngAI/ParaCrawl-English-Khmer-v2 Web crawl (ParaCrawl) 1.5M Web / general
SeyhaLite/Translate-English-Khmer-All --- 366K General
Total 2.4M

2.2 Preprocessing

Raw data was cleaned through the following pipeline:

  1. Deduplication: exact duplicate pairs removed across all sources.
  2. Length filtering: pairs with extreme source/target length mismatches were discarded.
  3. Empty/null removal: pairs where either side was empty or below a minimum token count were dropped.

After cleaning, each surviving pair is duplicated in both directions (EN→KM and KM→EN) with a direction prefix token (<2km> / <2en>), yielding ~4.2 million training examples.

3. Model Architecture

Netra-NMT Architecture

Figure 1: Overview of the Netra-NMT encoder-decoder architecture. The encoder (left) processes the source sentence with bidirectional self-attention; the decoder (right) generates the target sentence autoregressively via causal self-attention and cross-attention over the encoder output. Both sides share a 32K SentencePiece tokenizer.

Netra-NMT follows a standard encoder-decoder transformer architecture with several modifications for training stability and parameter efficiency.

Encoder takes the source sentence tokenized by the shared 32K SentencePiece tokenizer, adds learned positional embeddings, and passes the sequence through 6 transformer layers with bidirectional self-attention (every token attends to every other token, similar to BERT). A final Pre-LN layer norm is applied to the encoder output before it is passed to the decoder via cross-attention.

Decoder takes the (partially generated) target sentence through the same tokenizer, adds positional embeddings, and passes it through 6 transformer layers. Each decoder layer applies three sub-layers in order: (1) causal (masked) self-attention over previously generated tokens, (2) cross-attention over the full encoder output, and (3) a feed-forward block. A final Pre-LN layer norm feeds into the tied linear projection head to produce output token probabilities.

Architectural improvements over the vanilla transformer:

Feature Detail
Pre-Layer Normalization Layer norm applied before each sub-layer (Pre-LN) rather than after, improving gradient flow and training stability
SwiGLU FFN Feed-forward blocks use the SwiGLU activation instead of ReLU, providing richer representational capacity at no parameter cost
Weight tying The decoder input embedding matrix is shared with the output linear projection head, reducing redundant parameters

Hyperparameters:

d_model 512
Encoder / Decoder layers 6 / 6
Attention heads 8
FFN hidden size 2048
Vocabulary 32K (SentencePiece unigram, shared)
Total parameters ~89.7M

4. Evaluation Results

Install

pip install netra-nmt              # core (Python API + CLI)
pip install "netra-nmt[web]"       # + FastAPI web app & REST API

Or from source:

git clone https://github.com/NDarayut/netra-nmt
cd netra-nmt
pip install -e ".[web]"

The first translation downloads the weights (~180 MB fp16) from the Hugging Face Hub and caches them under ~/.cache/huggingface.

Usage

1. Python API

from netra_nmt import NetraTranslator

t = NetraTranslator()                       # auto-detect GPU/CPU; downloads weights once
t.translate("Hello, how are you?", direction="en2km")   # → "សួស្តី សុខសប្បាយអត់?"
t.translate("ខ្ញុំស្រឡាញ់ប្រទេសរបស់ខ្ញុំ។", direction="km2en")

# Batch + decoding options
t.translate_batch(["Good morning.", "See you tomorrow."], direction="en2km")
t.translate("Good morning, my friend.", direction="en2km", mode="beam", beam_size=5)

One-shot helper (caches a default translator):

from netra_nmt import translate
translate("Hello", direction="en2km")

direction is "en2km" (English→Khmer) or "km2en" (Khmer→English). mode is "greedy" (default), "beam", or "sample".

2. CLI

# Single sentence (default direction en2km):
netra-translate --text "Hello, how are you?"

# Khmer → English with beam search:
netra-translate --text "សួស្តី, តើអ្នកសុខសប្បាយទេ?" --direction km2en --mode beam

# Translate a file (one sentence per line):
netra-translate --file input.txt --output output.txt --direction en2km

# Interactive REPL (omit --text / --file):
netra-translate

3. Web app + REST API (FastAPI)

netra-web                      # serves the web UI + API at http://127.0.0.1:8000
netra-web --port 8080 --device cpu
netra-web --local-dir export   # load weights from a local export dir

A two-pane translation site (source left, output right, EN⇄KM swap button) plus a JSON API:

curl -X POST http://127.0.0.1:8000/api/translate \
  -H 'Content-Type: application/json' \
  -d '{"text": "Hello, how are you?", "direction": "en2km"}'
# {"translation": "...", "direction": "en2km"}

Requires the web extra (pip install "netra-nmt[web]").

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

netra_nmt-0.1.0.tar.gz (1.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

netra_nmt-0.1.0-py3-none-any.whl (509.5 kB view details)

Uploaded Python 3

File details

Details for the file netra_nmt-0.1.0.tar.gz.

File metadata

  • Download URL: netra_nmt-0.1.0.tar.gz
  • Upload date:
  • Size: 1.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for netra_nmt-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a11dae78ce88d32d99b11c0f781cc30c08b95e369f70c25967e78aea007d91e1
MD5 62175d4cba5ceca6add0864339889aff
BLAKE2b-256 bd85671c443f3760d4e51be29c12aeed3090ebb9ad71cac53a9cec2dfd63775a

See more details on using hashes here.

File details

Details for the file netra_nmt-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: netra_nmt-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 509.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for netra_nmt-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 48373433c90cd0f73199a06aa8353027e85caf0f5db052acfdb95226530ca5e4
MD5 bd02b1d1422444aae9cb7e5c0aa497fc
BLAKE2b-256 37e820e15920b344857af4884f656122dbfba952a62ff6b70f3a24ffc4ee1a61

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page