BharatMorph Embedding — Phoneme-Aware Multilingual Indic Embedding Model
A 76.8M parameter multilingual embedding model built from scratch for Indic languages.
Trained on 330K Wikipedia samples across 6 languages using MLM objective with morpheme diversity
and cross-lingual alignment losses.
Honest note: This model is best suited for cross-lingual retrieval tasks.
Within-language semantic search requires contrastive fine-tuning (planned for v2).
What Makes This Different
Most multilingual embedding models treat all languages the same — they tokenize text and learn
embeddings purely from context. BharatMorph takes a different approach:
Phoneme-aware character encoding — Tamil க, Hindi क, Malayalam ക all map to the same
phoneme ID. This means the model understands that these characters represent the same sound
across scripts — giving it a structural advantage for Indic cross-lingual tasks.
Morpheme-type soft mixture — Each token is analyzed as a soft mixture of 8 morpheme types
(root, prefix, suffix, infix, compound, sandhi, clitic, stem). This is differentiable — no hard
decisions, gradients flow through.
Cross-lingual concept alignment — A language-neutral concept space pulls same-meaning
representations together across languages without requiring parallel data.
Architecture
Input tokens
│
├──► Token Embedding (V × 1024)
│
└──► CharCNN (phoneme IDs)
k=3 : local morpheme patterns
k=7 : sandhi boundary context
│
▼
MorphemeAnalyzer
8-type soft mixture
│
▼
MorphemeAttn (bidirectional)
Q,K from morpheme space
│
▼
Gate(base, morph_vec) — content words use more morpheme signal
│
▼
CrossLingualAligner
language-neutral concept space
│
▼
Pooled sentence embedding (L2 normalized, dim=1024)
Component
Details
Total parameters
76.8M
Embedding dimension
1024
Morpheme types
8 (soft mixture)
Languages
Tamil, Hindi, Telugu, Kannada, Malayalam, English
Max sequence length
256 tokens
Tokenizer
Sarvam AI (sarvamai/sarvam-2b-v0.5)
Output
L2-normalized sentence embeddings
Training
Dataset — 330K Wikipedia Samples
Language
Samples
Script range
Tamil
80,000
U+0B80–0BFF
Hindi
80,000
U+0900–097F
Telugu
60,000
U+0C00–0C7F
Kannada
40,000
U+0C80–0CFF
Malayalam
40,000
U+0D00–0D7F
English
30,000
Latin
Validation
2,000
mixed
Training Config
GPU : NVIDIA Tesla T4 (Kaggle single GPU)
Epochs : 3
Batch size : 32
Grad accum : 4 (effective batch = 128)
Max seq len : 256
Learning rate : 2e-4
LR schedule : Cosine with warmup (1000 steps)
Optimizer : AdamW (β=0.9, 0.95, ε=1e-8)
Weight decay : 0.01
Grad clip : 1.0
Mixed precision: FP16 (AMP)
NaN batches : 0
Loss:
Total = MLM loss + 0.01 × Morpheme diversity loss + 0.005 × Alignment loss
Training Results
Epoch
Val Loss
Val PPL
1
0.9713
2.64
2
0.7500
2.12
3
0.7230
2.06
Evaluation Results
Cross-lingual Similarity (Same Meaning)
Pair
Cosine Similarity
Tamil ↔ Malayalam
0.9546
Tamil ↔ Telugu
0.9342
Tamil ↔ Hindi
0.8932
Tamil ↔ English
0.8754
All pairs exceed the 0.6 threshold — cross-lingual alignment is working well.
Honest Limitations
Within-language semantic search: Different Tamil sentences score ~0.96 cosine similarity
regardless of meaning. The model does not yet separate "cat sleeping" from "car going fast"
within the same language. This is because MLM-only training does not push apart unrelated
sentences — contrastive loss is needed.
Contrastive fine-tuning: Planned for v2 using SimCSE-style training.
Factual accuracy: Not applicable — this is an embedding model, not a generative model.
You also need bharatmorph_embedding.py — download it from the model repo or copy from below.
Load and Encode
python
1import torch
2import torch.nn.functional as F
3import safetensors.torch
4from transformers import AutoTokenizer
5from huggingface_hub import snapshot_download
6from bharatmorph_embedding import(7 BharatMorphEmbeddingConfig,8 BharatMorphEmbeddingModel,9 build_char_table,10 fast_char_ids,11)1213# ── Download model ────────────────────────────────────────────14local_dir = snapshot_download("Girinath11/bharatmorph-embedding")1516# ── Load tokenizer (must use Sarvam tokenizer) ────────────────17tok = AutoTokenizer.from_pretrained("sarvamai/sarvam-2b-v0.5", trust_remote_code=True)18tok.add_special_tokens({"additional_special_tokens":["[TA]","[HI]","[TE]","[KN]","[ML]","[EN]"]})19if tok.pad_token isNone:20 tok.pad_token = tok.eos_token
2122# ── Load model ────────────────────────────────────────────────23ecfg = BharatMorphEmbeddingConfig.from_pretrained(local_dir)24model = BharatMorphEmbeddingModel(ecfg)25model.resize_token_embeddings(len(tok))2627state_dict = safetensors.torch.load_file(f"{local_dir}/model.safetensors")28state_dict.pop("mlm_head.3.weight",None)# tied weight — safe to skip29model.load_state_dict(state_dict, strict=False)30model = model.eval().cuda()3132# ── Build char table (do once, reuse) ────────────────────────33CHAR_CPU = build_char_table(tok,len(tok),20,512)3435# ── Language IDs ─────────────────────────────────────────────36# ta=0 hi=1 te=2 kn=3 ml=4 en=53738defencode(texts, lang_ids):39"""
40 texts : list of strings
41 lang_ids : list of ints matching language of each text
42 returns : (N, 1024) L2-normalized tensor
43 """44 enc = tok(texts, max_length=256, truncation=True,45 padding="max_length", return_tensors="pt")46 ids = enc["input_ids"].cuda()47 mask = enc["attention_mask"].cuda()48 cids = fast_char_ids(ids.cpu(), CHAR_CPU).cuda()49 lids = torch.tensor(lang_ids, dtype=torch.long).cuda()50with torch.no_grad():51 out = model(input_ids=ids, attention_mask=mask,52 char_ids=cids, lang_ids=lids, run_mlm=False)53return out.pooled # (N, 1024) L2-normalized5455# ── Cosine similarity ─────────────────────────────────────────56defsimilarity(a, b):57return F.cosine_similarity(a, b, dim=-1).item()
Cross-lingual Retrieval Example
python
1# Same meaning, different languages — should score high2ta = encode(["அம்மா சாப்பிட்டாள்"],[0])# Tamil3hi = encode(["माँ ने खाना खाया"],[1])# Hindi4ml = encode(["അമ്മ ഭക്ഷണം കഴിച്ചു"],[4])# Malayalam5en = encode(["Mother ate food"],[5])# English67print(f"Tamil ↔ Hindi : {similarity(ta, hi):.4f}")# 0.89328print(f"Tamil ↔ Malayalam : {similarity(ta, ml):.4f}")# 0.95469print(f"Tamil ↔ English : {similarity(ta, en):.4f}")# 0.8754
Cross-lingual Document Search
python
1# Query in English, find matching documents in Tamil/Hindi2query = encode(["agriculture and farming"],[5])34tamil_docs =[5"விவசாயம் தமிழ்நாட்டின் முக்கிய தொழில்",# Agriculture is TN's main industry6"கணினி அறிவியல் படிப்பு பயனுள்ளது",# CS education is useful7"நெல் சாகுபடி அதிகமாக உள்ளது",# Rice cultivation is high8]9hindi_docs =[10"किसान खेती में मेहनत करते हैं",# Farmers work hard in farming11"मोबाइल फोन आज जरूरी है",# Mobile phones are necessary today12]1314all_docs = tamil_docs + hindi_docs
15all_lids =[0]*3+[1]*216doc_embs = encode(all_docs, all_lids)1718scores = F.cosine_similarity(query, doc_embs, dim=-1)19ranked =sorted(zip(scores.tolist(), all_docs), reverse=True)2021print("Query: 'agriculture and farming'\n")22for score, doc in ranked:23print(f" {score:.4f}{doc}")
Batch Encoding
python
1# Encode multiple sentences at once (efficient)2sentences =[3"தமிழ் மொழி மிகவும் பழமையானது",# Tamil is very ancient4"हिंदी भारत की राजभाषा है",# Hindi is India's official language5"Telugu is a Dravidian language",6"ಕನ್ನಡ ಕರ್ನಾಟಕದ ಅಧಿಕೃತ ಭಾಷೆ",# Kannada is Karnataka's official language7"Malayalam has palindrome script",8]9lang_ids =[0,1,5,3,4]1011embeddings = encode(sentences, lang_ids)12print(f"Shape: {embeddings.shape}")# (5, 1024)1314# Pairwise similarity matrix15sim_matrix = torch.matmul(embeddings, embeddings.T)16print(sim_matrix)
Use Cases
Task
Suitable?
Notes
Cross-lingual document retrieval
Yes
Main strength
Multilingual clustering
Yes
Language-neutral space
Cross-lingual semantic textual similarity
Yes
High cosine scores
Within-language semantic search
Partial
v2 with contrastive training planned
Within-language sentence ranking
Partial
Scores are compressed
Named entity recognition
No
Not designed for this
Text generation
No
Embedding model only
What I Learned / What's Next
What worked:
Phoneme-aware char encoding — cross-lingual similarity excellent
Morpheme soft mixture — differentiable, stable
Cross-lingual alignment loss — no parallel data needed
NaN-safe training — 0 NaN batches across 3 epochs
Loss curve healthy — 0.97 → 0.72 val loss
What needs improvement (v2):
SimCSE contrastive loss — within-language semantic separation
More training data — 330K is small
Harder negative mining — unrelated sentences too similar
Evaluation on standard benchmarks (MIRACL, XQuAD)
Citation
bibtex
1@misc{girinath2026bharatmorph,
2 author = {Girinath V},
3 title = {BharatMorph Embedding: Phoneme-Aware Multilingual
4 Embedding Model for Indic Languages},
5 year = {2026},
6 publisher = {Hugging Face},
7 howpublished = {\url{https://huggingface.co/Girinath11/bharatmorph-embedding}},
8 note = {76.8M parameter embedding model trained from scratch
9 with phoneme-aware CharCNN and cross-lingual alignment}
10}
Acknowledgments
Sarvam AI — tokenizer (sarvamai/sarvam-2b-v0.5)
Wikimedia Foundation — Wikipedia training data
HuggingFace — Transformers library
Kaggle — Free GPU access (T4)
Model status : Research / Cross-lingual retrieval use Author : Girinath V
Last updated : April 2026 License : MIT
license: mit