You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

NLLB French β†’ shiNgazidja (fine-tuned)

This model is a fine-tuned version of facebook/nllb-200-distilled-600M for French β†’ shiNgazidja (zdj) translation.

Note on language code: NLLB-200 does not include a native token for shiNgazidja, a Comorian language. During fine-tuning, the closest available NLLB language tag, swh_Latn (Swahili), was reused as a stand-in token to represent shiNgazidja. This is purely an internal tokenizer artifact β€” the model's actual output language is shiNgazidja (zdj), not Swahili. Keep this in mind if you inspect the code below: every reference to sw / swh_Latn refers to shiNgazidja.

The model also uses custom control tokens prepended to each input (target language, source language, domain, dialect) that were introduced during fine-tuning. You must reproduce the same prefix format at inference time, or translation quality will degrade significantly.

Model details

  • Base model: facebook/nllb-200-distilled-600M
  • Source language: French β€” fra_Latn
  • Target language: shiNgazidja β€” internally tagged swh_Latn (proxy for zdj, no native NLLB code available)
  • Direction: src2tgt (French β†’ shiNgazidja)
  • Fine-tuning framework: πŸ€— Transformers

Input format

Every input sentence must be prefixed like this:

<to_sw> <src_fr> <dom_unknown> <dialect_default> your sentence here
  • <to_sw> / <src_fr> β€” target/source short language codes used at training time (sw is the internal proxy tag for shiNgazidja, see note above)
  • <dom_unknown> / <dialect_default> β€” the model was trained with optional domain/dialect tags (e.g. <dom_dictionary>, <dom_picture_book>); this README fixes both to their default values since no domain/dialect metadata is used at inference here

The build_prefix helper below reproduces this exactly as used during training.

Installation

pip install -q "transformers>=4.56,<4.57" sentencepiece sacremoses sacrebleu datasets pandas numpy tqdm protobuf

Inference

import torch
from transformers import AutoModelForSeq2SeqLM, NllbTokenizer

MODEL_ID = "NextGenU/translator-french-shiNgazidja"  # replace with your repo id

SOURCE_LANG, TARGET_LANG = "fr", "sw"          # "sw" = internal proxy tag for shiNgazidja (zdj)
SOURCE_LID, TARGET_LID = "fra_Latn", "swh_Latn"  # swh_Latn = internal proxy for shiNgazidja
DIRECTION = "src2tgt"

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")


# --- Prefix builder (must match training) -------------------------------
# Domain and dialect are fixed to their default values here since this
# deployment does not use per-sentence domain/dialect metadata.

def build_prefix(direction=DIRECTION) -> str:
    src_short = SOURCE_LANG if direction == "src2tgt" else TARGET_LANG
    tgt_short = TARGET_LANG if direction == "src2tgt" else SOURCE_LANG
    return f"<to_{tgt_short}> <src_{src_short}> <dom_unknown> <dialect_default>"


# --- Load model -----------------------------------------------------------

tokenizer = NllbTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_ID).to(device).eval()

# NLLB decoder starts on EOS
model.config.decoder_start_token_id = tokenizer.eos_token_id
if getattr(model, "generation_config", None) is not None:
    model.generation_config.decoder_start_token_id = tokenizer.eos_token_id


def ensure_token(token: str) -> int:
    tid = tokenizer.convert_tokens_to_ids(token)
    if tid == tokenizer.unk_token_id or tokenizer.convert_ids_to_tokens(tid) != token:
        raise ValueError(f"{token} is not a known token in the tokenizer")
    return int(tid)


# --- Single sentence translation ------------------------------------------

@torch.no_grad()
def translate(text, max_new_tokens=128, num_beams=4):
    prefix = build_prefix()
    prompt = f"{prefix} {text}"

    tokenizer.src_lang = SOURCE_LID
    enc = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=256).to(device)

    out = model.generate(
        **enc,
        forced_bos_token_id=ensure_token(TARGET_LID),
        decoder_start_token_id=tokenizer.eos_token_id,
        eos_token_id=tokenizer.eos_token_id,
        pad_token_id=tokenizer.pad_token_id,
        max_new_tokens=max_new_tokens,
        num_beams=num_beams,
        no_repeat_ngram_size=3,
        repetition_penalty=1.15,
        length_penalty=1.0,
    )
    return tokenizer.batch_decode(out, skip_special_tokens=True)[0]


# --- Batch translation ------------------------------------------------------

@torch.no_grad()
def translate_batch(texts, batch_size=16,
                     max_length=256, max_new_tokens=128, num_beams=4):
    prefix = build_prefix()
    forced_id = ensure_token(TARGET_LID)
    outputs = []

    for start in range(0, len(texts), batch_size):
        batch = [f"{prefix} {str(t)}" for t in texts[start:start + batch_size]]
        tokenizer.src_lang = SOURCE_LID
        enc = tokenizer(
            batch, return_tensors="pt", padding=True, truncation=True,
            max_length=max_length, return_token_type_ids=False,
        ).to(device)

        gen = model.generate(
            **enc,
            forced_bos_token_id=forced_id,
            decoder_start_token_id=tokenizer.eos_token_id,
            eos_token_id=tokenizer.eos_token_id,
            pad_token_id=tokenizer.pad_token_id,
            max_new_tokens=max_new_tokens,
            num_beams=num_beams,
            no_repeat_ngram_size=3,
            repetition_penalty=1.15,
            length_penalty=1.0,
        )
        outputs.extend(tokenizer.batch_decode(gen, skip_special_tokens=True))

    return outputs


# --- Example ----------------------------------------------------------------

if __name__ == "__main__":
    print(translate("Demain matin nous irons lΓ -bas."))
    print(translate_batch(["Je pense qu'il va pleuvoir.", "Les enfants n'ont pas encore mangΓ©."]))

Notes

  • Set MODEL_ID to the actual repository id once uploaded.
  • Domain and dialect are fixed to <dom_unknown> / <dialect_default>.
  • Translation quality depends on prefix consistency β€” omitting the prefix or using a different format than training will produce degraded output.
  • Beam search (num_beams=4) and repetition_penalty=1.15 are the defaults used during evaluation; adjust for your speed/quality trade-off.
  • All sw / swh_Latn references in this model and code are an internal proxy for shiNgazidja (zdj) β€” see the note above.

Limitations

  • This model is fine-tuned for French β†’ shiNgazidja only (src2tgt direction). A tgt2src (shiNgazidja β†’ French) direction requires either a separately fine-tuned checkpoint or the tags/prefix swapped accordingly, if the base model supports it.
  • Because shiNgazidja has no native NLLB language token, the model relies entirely on the fine-tuning data to associate the swh_Latn proxy token with shiNgazidja vocabulary and grammar β€” any residual bias toward actual Swahili is possible, especially on out-of-domain text.
  • As with any NMT model, performance may vary across domains not well represented in the fine-tuning data.
Downloads last month
17
Safetensors
Model size
0.6B params
Tensor type
F32
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for NextGenU/translator-french-shingazidja

Finetuned
(426)
this model