PulaarAI / app.py
kawkumputer's picture
ui: retire les sections d exemples (Coran/Quotidien/juridique)
c5b2a73 verified
Raw
History Blame Contribute Delete
3.35 kB
import torch
import gradio as gr
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
from peft import PeftModel
BASE_MODEL = "facebook/nllb-200-distilled-1.3B"
LORA_REPO = "kawkumputer/pulaar-ai-nllb-1.3b-v9"
DEVICE = "cpu"
LANG_FR = "fra_Latn"
LANG_AR = "arb_Arab"
LANG_PUL = "fuv_Latn"
DIRECTION_MAP = {
"fr → pul": (LANG_FR, LANG_PUL),
"ar → pul": (LANG_AR, LANG_PUL),
"pul → fr": (LANG_PUL, LANG_FR),
"pul → ar": (LANG_PUL, LANG_AR),
}
print("Chargement du tokenizer...")
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)
print("Chargement du modèle de base...")
base_model = AutoModelForSeq2SeqLM.from_pretrained(
BASE_MODEL,
torch_dtype=torch.float32,
low_cpu_mem_usage=True,
)
print(f"Application des adaptateurs LoRA depuis {LORA_REPO}...")
model = PeftModel.from_pretrained(base_model, LORA_REPO)
model.eval()
print("Modèle prêt.")
def translate(text: str, direction: str) -> str:
if not text or not text.strip():
return ""
src_lang, tgt_lang = DIRECTION_MAP[direction]
tokenizer.src_lang = src_lang
inputs = tokenizer(
text.strip(),
return_tensors="pt",
truncation=True,
max_length=256,
)
forced_bos = tokenizer.convert_tokens_to_ids(tgt_lang)
with torch.no_grad():
out = model.generate(
**inputs,
forced_bos_token_id=forced_bos,
num_beams=4,
max_length=256,
repetition_penalty=1.3,
no_repeat_ngram_size=3,
early_stopping=True,
)
return tokenizer.decode(out[0], skip_special_tokens=True)
with gr.Blocks(title="PulaarAI — Traducteur Pulaar") as demo:
gr.Markdown(
"# PulaarAI — Traducteur Pulaar\n"
"**Traduction fr/ar ↔ Pulaar** · Dialecte Fouta-Toro · "
"Développé par Hamath Kane, Abou Sy & Bocar Amadou Ba (ARPRIM)\n\n"
"Basé sur **NLLB-200-distilled-1.3B** + LoRA fine-tuné · "
"⚠️ Inférence CPU — comptez 20-40 secondes par traduction"
)
gr.Markdown(
"> **Modèle actif : v9** — NLLB-1.3B · dataset quotidien + ARPRIM (juridique/santé/histoire) · "
"chrF++ Coran fr→pul : **37.67** · chrF++ Quotidien fr→pul : **42.99** (+4.45 vs v7)"
)
with gr.Row():
with gr.Column(scale=1):
input_text = gr.Textbox(
label="Texte source",
placeholder="Saisissez le texte à traduire...",
lines=5,
)
direction = gr.Dropdown(
choices=list(DIRECTION_MAP.keys()),
value="fr → pul",
label="Direction",
)
with gr.Row():
btn_clear = gr.Button("Effacer", variant="secondary")
btn = gr.Button("Traduire", variant="primary", scale=2)
with gr.Column(scale=1):
output_text = gr.Textbox(
label="Traduction",
lines=5,
interactive=False,
)
btn.click(fn=translate, inputs=[input_text, direction], outputs=output_text)
input_text.submit(fn=translate, inputs=[input_text, direction], outputs=output_text)
btn_clear.click(fn=lambda: ("", ""), outputs=[input_text, output_text])
demo.launch(theme=gr.themes.Soft())