Spaces:
Running on Zero
Running on Zero
| """CPU translation backend using billingsmoore/mlotsawa-ground-base | |
| (a Tibetan->English seq2seq T5 model). Used whenever no OpenRouter API key is | |
| available. The model is loaded once, lazily, on first use. | |
| Generation uses the model's own task_specific_params["translation_bo_to_en"] | |
| (prefix "translate Tibetan to English: ", num_beams=4, max_length=300) rather | |
| than transformers' old pipeline("translation", ...) task, which was removed | |
| in transformers>=5 (raises "Unknown task translation"). Calling generate() | |
| directly with the model's documented settings works on any transformers | |
| version that ships AutoModelForSeq2SeqLM/AutoTokenizer. | |
| This backend ignores the editable translation prompt — it's a plain | |
| seq2seq model, not an instruction-following LLM. | |
| translate_batch is decorated with @spaces.GPU so this runs on HF ZeroGPU | |
| Spaces (which refuse to boot a gradio-sdk app with no @spaces.GPU function | |
| at all); the decorator is a no-op outside a ZeroGPU Space. | |
| """ | |
| import spaces | |
| MODEL_ID = "billingsmoore/mlotsawa-ground-base" | |
| _PREFIX = "translate Tibetan to English: " | |
| _model = None | |
| _tokenizer = None | |
| def _load(): | |
| global _model, _tokenizer | |
| if _model is None: | |
| from transformers import AutoModelForSeq2SeqLM, AutoTokenizer | |
| print(f"[INFO] Loading local CPU translation model: {MODEL_ID}") | |
| _tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) | |
| _model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_ID) | |
| _model.eval() | |
| return _model, _tokenizer | |
| def translate_batch(texts: list[str]) -> list[str]: | |
| if not texts: | |
| return [] | |
| import torch | |
| model, tokenizer = _load() | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| model.to(device) | |
| inputs = tokenizer( | |
| [_PREFIX + t for t in texts], | |
| return_tensors="pt", padding=True, truncation=True, | |
| ).to(device) | |
| with torch.no_grad(): | |
| outputs = model.generate(**inputs, max_length=300, num_beams=4, early_stopping=True) | |
| return [tokenizer.decode(o, skip_special_tokens=True) for o in outputs] | |