Downloads · 30 days
3
5% of all-time downloads
MihaiPopa-1/NLLB-200-Distilled-600M-Middle-English-v1.5
NLLB-200-Distilled-600M-Middle-English-v1.5 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
3
5% of all-time downloads
All-time downloads
62
Public
Repo size
4.6 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 is v1.5 — an incremental improvement over v1.0 using the American Standard Version (ASV, 1901) as the Modern English source instead of KJV (1611), trained for 5 epochs instead of 3.
| Version | Source | Epochs | chrF++ | BLEU |
|---|---|---|---|---|
| v1.0 | KJV (1611) | 3 | 51.46 | 30.51 |
| v1.5 | ASV (1901) | 5 | 52.10 | 34.14 |
| v2.0 | ASV + Canterbury Tales | TBD | ~57-60 | TBD |
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. ASV.
| Metric | v1.0 | v1.5 | Delta |
|---|---|---|---|
| chrF++ | 51.46 | 52.10 | +0.64 |
| BLEU | 30.51 | 34.14 | +3.63 |
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. The theoretical ceiling is ~65-70 due to inconsistent spelling in Wycliffe manuscripts.
| 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. ASV (~28k pairs) |
| Validation data | ~1k pairs |
| MAX_LEN | 64 tokens |
| Batch size | 16 |
| Gradient accumulation | 2 (effective batch 32) |
| Epochs | 5 |
| Learning rate | 5e-4 |
| Label smoothing | 0.1 |
| Hardware | NVIDIA T4 (16GB) |
| Training time | 4h03m |
| Step | Train Loss | Val Loss |
|---|---|---|
| 500 | 3.5414 | 3.7975 |
| 1000 | 3.3115 | 3.4803 |
| 1500 | 3.1545 | 3.3265 |
| 2000 | 3.0797 | 3.2289 |
| 2500 | 3.0237 | 3.1554 |
| 3000 | 3.0227 | 3.1038 |
| 3500 | 2.9786 | 3.0669 |
| 4000 | 2.8930 | 3.0330 |
| 4500 | 2.8961 | 3.0073 |
| 5000 | 2.8697 | 2.9871 |
| 5500 | 2.8300 | 2.9708 |
| 6000 | 2.8213 | 2.9572 |
| 6500 | 2.7946 | 2.9450 |
| 7000 | 2.8198 | 2.9320 |
| 7500 | 2.7558 | 2.9282 |
| 8000 | 2.7709 | 2.9240 |
| 8500 | 2.7745 | 2.9192 |
Training data sourced from two public domain texts, aligned by book/chapter/verse:
V1.5 improvement over v1.0: ASV (1901) is significantly more modern than KJV (1611) — no
thou/thee/hath/spakeconstructions. This reduces register mismatch between training source and real-world modern English input.
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-v1.5' # update with your HF repo
# 1. Load tokenizer + add ME token
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)
EN_TOKEN_ID = tokenizer.convert_tokens_to_ids('eng_Latn')
# 2. Load base model + resize + adapter (order matters!)
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 you later in this nyyt."
print(translate("Let's meet at the coffee shop at noon."))
# → "Meete we in the coffee shop at myddai."
# Middle English → Modern English
print(translate("Y haue not ete ony thing fro the morewtid.",
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 you later in this nyyt. |
| The weather is really nice today. | The weie is ful plesaunt to dai. |
| Did you see the news this morning? | Whether thou siyist the news of this morewtid? |
| My phone battery is dead. | Y haue a deeth of the baterie of my phone. |
| Let's meet at the coffee shop at noon. | Meete we in the coffee shop at myddai. |
| She works at the hospital downtown. | Sche worchith in the hospital of the citee. |
| I haven't eaten anything since breakfast. | Y haue not ete ony thing fro the morewtid. |
| This is taking longer than expected. | This thing takith longer than it was abid. |
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)
@misc{nllb-middle-english-lora,
title = {NLLB-200 LoRA: English ↔ Middle English Translation (v1.5)},
year = {2025},
note = {Fine-tuned on Wycliffe Bible / ASV parallel corpus}
}