tonibirat/neBrahma-Nepali-Pretrain-Corpus
Updated • 229
A 58M-parameter Nepali decoder-only language model trained from scratch on 1.16B tokens of Nepali text. This is the P3 base model for the neBrahma FYP project - a unified Nepali text+audio system targeting ASR and TTS.
The training engine is hand-written in C++/CUDA (llm.c style), targeting an RTX 3060 Mobile (6 GB VRAM). No HuggingFace Transformers used in training.
| Parameters | 57.7M |
| Vocabulary | 32,768 (SentencePiece BPE) |
| Training context | 256 tokens |
| Training tokens | 1.157B |
| Training steps | 70,624 |
| Final val loss | 3.8413 |
| Perplexity | 46.6 |
| Random baseline | 10.40 (ln 32768) |
| Hardware | RTX 3060 Mobile 6GB |
| Training time | ~4 days |
| Type | Decoder-only transformer |
| d_model | 512 |
| n_layers | 12 |
| n_heads | 8 (head_dim = 64) |
| FFN dim | 1,536 |
| Attention | Causal, no biases |
| Positional encoding | RoPE (theta=10000) |
| FFN activation | SwiGLU |
| Normalization | RMSNorm (eps=1e-5), pre-norm |
| Embeddings | Tied (tok_emb = LM head) |
| Dtype | FP32 (BF16 Tensor Cores via WMMA during training) |
| Step | Val Loss |
|---|---|
| 0 | 10.5076 |
| 1,000 | 6.1994 |
| 2,000 | 5.2937 |
| 5,000 | 4.5601 |
| 10,000 | 4.2322 |
| 20,000 | 4.1278 |
| 30,000 | 3.9827 |
| 40,000 | 3.9185 |
| 50,000 | 3.8962 |
| 60,000 | 3.8378 |
| 70,000 | 3.8174 |
| 70,624 | 3.8413 |
Trained on tonibirat/neBrahma-Nepali-Pretrain-Corpus:
| Documents | 20,321,968 |
| Tokens | 1.845B |
| Sources | IndicCorp v2, FineWeb-2, IRIIS, Sagarmatha ASR |
| Quality | FIT TO TRAIN certified (zero warnings) |
| Keep rate | 77.7% (5.8M docs rejected by quality gates) |
This model uses a custom architecture. Load with engine/oracle/model.py from the
neBrahma-llm repo:
from safetensors import safe_open
import torch
# Load weights
tensors = {}
with safe_open("model.safetensors", framework="pt") as f:
for k in f.keys():
tensors[k] = f.get_tensor(k)
# Build model (requires engine/oracle/model.py from neBrahma-llm repo)
from model import TinyLlama
cfg = {
"d_model": 512, "n_layers": 12, "n_heads": 8, "head_dim": 64,
"d_ff": 1536, "vocab_size": 32768, "rms_eps": 1e-5, "rope_theta": 10000.0,
}
model = TinyLlama(cfg)
# Load weights (ordered_params() gives canonical order matching safetensors keys)
param_keys = (
["model.tok_emb"] +
[f"model.layers.{l}.{n}" for l in range(12)
for n in ["attn_norm","wq","wk","wv","wo","ffn_norm","w_gate","w_up","w_down"]] +
["model.final_norm"]
)
for key, p in zip(param_keys, model.ordered_params()):
p.data.copy_(tensors[key])
model.eval()
# Tokenize with sentencepiece
import sentencepiece as spm
sp = spm.SentencePieceProcessor()
sp.Load("tokenizer.model")
text = "नेपाली भाषा"
tokens = torch.tensor([sp.encode(text)], dtype=torch.long)
with torch.no_grad():
logits = model(tokens)
AutoModelForCausalLM; requires the neBrahma engine@misc{nebrahma2026,
author = {Birat Gautam},
title = {neBrahma: A Nepali Multimodal Language Model Trained from Scratch},
year = {2026},
note = {Final Year Project, Birmingham City University},
url = {https://github.com/ToniBirat7/neBrahma-llm},
}