Downloads · 30 days
4
5% of all-time downloads
MihaiPopa-1/NLLB-200-Distilled-600M-Middle-English
NLLB-200-Distilled-600M-Middle-English is a translation model from MihaiPopa-1. Use it when you need text moved from one language to another. It is set up for peft. The card lists the license as mit.
Downloads · 30 days
4
5% of all-time downloads
All-time downloads
88
Public
Repo size
2.3 GB
Likes
0
Public
Click a slice to open those files.
.safetensors3.3 GB · 95%
From the Hugging Face model README
A LoRA adapter fine-tuned on top of facebook/nllb-200-distilled-600M for bidirectional translation between Modern English and Middle English (Wycliffe/Chaucer era, ~1380–1400).
This adapter teaches NLLB-200 to translate between Modern English and Middle English in the style of the Wycliffe Bible (~1382). It is the faithful back-translation component of a two-model pipeline — optimized for meaning preservation rather than stylistic fluency.
The companion fluency model (Qwen3-4B LoRA) is trained using synthetic data generated by this model.
Evaluated on 100 held-out verse pairs from the Wycliffe Bible vs. KJV.
| Metric | Score |
|---|---|
| chrF++ | 51.46 |
| BLEU | 30.51 |
Note: The gap between chrF++ and BLEU is expected — BLEU penalizes valid Middle English spelling variants (e.g.
echvseuery,figisvsfigus). chrF++ is the more appropriate metric for this task.
| Parameter | Value |
|---|---|
| Base model | facebook/nllb-200-distilled-600M |
| LoRA rank | 16 |
| LoRA alpha | 32 |
| Target modules | q_proj, k_proj, v_proj, out_proj, fc1, fc2 |
| Trainable params | 8,650,752 (1.39%) |
| Training data | Wycliffe Bible vs. KJV (~27k pairs) |
| MAX_LEN | 128 tokens |
| Batch size | 16 |
| Gradient accumulation | 2 (effective batch 32) |
| Epochs | 3 |
| Learning rate | 5e-4 |
| Label smoothing | 0.1 |
| Hardware | NVIDIA T4 (16GB) |
| Training time | 8428s (~2h20min) |
| Samples/sec | 19.2 |
| Total FLOPS | 4.49 × 10¹⁶ |
| Average train loss | 3.215 |
| Final step train loss | 2.907 (step 5000) |
| Final val loss | 3.024 (step 5000) |
| Step | Train Loss | Val Loss |
|---|---|---|
| 500 | 3.5559 | 3.7685 |
| 1000 | 3.3317 | 3.4527 |
| 1500 | 3.2002 | 3.2972 |
| 2000 | 3.0826 | 3.2185 |
| 2500 | 3.0477 | 3.1452 |
| 3000 | 3.0020 | 3.0992 |
| 3500 | 2.9551 | 3.0730 |
| 4000 | 2.9471 | 3.0504 |
| 4500 | 2.9321 | 3.0293 |
| 5000 | 2.9070 | 3.0241 |
Training data sourced from two public domain texts, aligned by book/chapter/verse:
Note: KJV is Early Modern English (1611), not contemporary Modern English. This means the model performs best on formal/biblical register input. For everyday modern text, use the companion Qwen3-4B LoRA adapter.
Data pipeline available at: [me_data_pipeline.py]
from transformers import NllbTokenizer, AutoModelForSeq2SeqLM
from peft import PeftModel
import torch
MODEL_ID = 'facebook/nllb-200-distilled-600M'
ADAPTER = 'MihaiPopa-1/NLLB-200-Distilled-600M-Middle-English' # update with your HF repo
tokenizer = NllbTokenizer.from_pretrained(MODEL_ID)
ME_TOKEN = 'enm_Latn'
if ME_TOKEN not in tokenizer.additional_special_tokens:
tokenizer.add_special_tokens({'additional_special_tokens': [ME_TOKEN]})
ME_TOKEN_ID = tokenizer.convert_tokens_to_ids(ME_TOKEN)
model = AutoModelForSeq2SeqLM.from_pretrained(
MODEL_ID,
torch_dtype=torch.float16,
device_map='auto'
)
model.resize_token_embeddings(len(tokenizer))
model = PeftModel.from_pretrained(model, ADAPTER)
model.eval()
def translate(text, src_lang='eng_Latn', tgt_token_id=ME_TOKEN_ID):
tokenizer.src_lang = src_lang
inputs = tokenizer(text, return_tensors='pt', truncation=True, max_length=64).to(model.device)
with torch.no_grad():
out = model.generate(
**inputs,
forced_bos_token_id=tgt_token_id,
max_new_tokens=64,
num_beams=4
)
return tokenizer.decode(out[0], skip_special_tokens=True)
# Modern English → Middle English
print(translate("I will call you later tonight."))
# → "Y schal clepe to thee later this nyyt."
print(translate("She works at the hospital downtown."))
# → "Sche werkith in the hospital in the myddil of the town."
# Middle English → Modern English
EN_TOKEN_ID = tokenizer.convert_tokens_to_ids('eng_Latn')
print(translate("Y haue not etun ony thing fro breakfast.", src_lang='enm_Latn', tgt_token_id=EN_TOKEN_ID))
# → "I have not eaten anything since breakfast."
| Modern English | Middle English |
|---|---|
| I will call you later tonight. | Y schal clepe to thee later this nyyt. |
| The weather is really nice today. | The weier is trewe to dai. |
| Did you see the news this morning? | Whether thou seest the wordis of the morewtid? |
| My phone battery is dead. | My phone baterie is deed. |
| Let's meet at the coffee shop at noon. | Meete we in the coffee shop at noon. |
| She works at the hospital downtown. | Sche werkith in the hospital in the myddil of the town. |
| I haven't eaten anything since breakfast. | Y haue not etun ony thing fro breakfast. |
Shupham → Sufam).This model is part of a two-model English ↔ Middle English translation system:
NLLB-600M LoRA → faithful back-translation → synthetic training data
↓
Qwen3-4B LoRA → fluent, natural ME output → daily use (texts, messages)
If you use this model, please cite:
@misc{nllb-middle-english-lora,
title = {NLLB-200 LoRA: English ↔ Middle English Translation},
year = {2025},
note = {Fine-tuned on Wycliffe Bible / KJV parallel corpus}
}