MIC-Off / translator.py
VethaNarayananG's picture
Add spaces.GPU dummy function to fix ZeroGPU startup error
b125f4b
Raw
History Blame Contribute Delete
5.61 kB
"""
translator.py — NLLB-200 offline translation engine
Wraps Meta's NLLB-200-distilled-600M for any-to-any translation.
"""
import time
import traceback
from typing import Dict, Any, Optional
from config import NLLB_MODEL_NAME, NLLB_LANGS, LANGUAGE_NAMES, NLLB_TO_ISO
try:
import spaces
@spaces.GPU
def dummy_gpu_func():
pass
except ImportError:
pass
class Translator:
"""Offline translation using Meta NLLB-200."""
def __init__(self):
self.model = None
self.tokenizer = None
self.ready = False
self.model_name = NLLB_MODEL_NAME
def load(self):
"""Load the NLLB model and tokenizer."""
try:
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
print(f"[Translator] Loading NLLB model: {self.model_name}...")
self.tokenizer = AutoTokenizer.from_pretrained(
self.model_name,
local_files_only=True
)
print("[Translator] Tokenizer loaded.")
self.model = AutoModelForSeq2SeqLM.from_pretrained(
self.model_name,
local_files_only=True
)
print("[Translator] Model loaded.")
self.ready = True
print("[Translator] NLLB ready for translation!")
except Exception as e:
print(f"[Translator] ERROR loading NLLB: {e}")
traceback.print_exc()
# Try downloading if not available locally
try:
print("[Translator] Trying to download model...")
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
self.model = AutoModelForSeq2SeqLM.from_pretrained(self.model_name)
self.ready = True
print("[Translator] NLLB downloaded and loaded!")
except Exception as e2:
print(f"[Translator] Download also failed: {e2}")
traceback.print_exc()
self.ready = False
def translate(self, text: str, source_lang: str, target_lang: str,
max_length: int = 512) -> Dict[str, Any]:
"""
Translate text from source language to target language.
Args:
text: Text to translate
source_lang: ISO language code (e.g., 'en', 'fr', 'ta')
target_lang: ISO language code
max_length: Maximum output token length
Returns:
dict with translated text, timing info, etc.
"""
if not self.ready or self.model is None or self.tokenizer is None:
return {
"translated": text,
"error": "NLLB model not loaded",
"time_ms": 0
}
# Get NLLB codes
source_nllb = NLLB_LANGS.get(source_lang)
target_nllb = NLLB_LANGS.get(target_lang)
if not source_nllb:
return {
"translated": text,
"error": f"Unsupported source language: {source_lang}",
"time_ms": 0
}
if not target_nllb:
return {
"translated": text,
"error": f"Unsupported target language: {target_lang}",
"time_ms": 0
}
# Same language — no translation needed
if source_lang == target_lang:
return {
"translated": text,
"source_lang": source_lang,
"target_lang": target_lang,
"time_ms": 0,
"error": None
}
try:
start = time.time()
# Set source language
self.tokenizer.src_lang = source_nllb
# Tokenize
inputs = self.tokenizer(text, return_tensors="pt", truncation=True,
max_length=max_length)
# Get target language token ID
target_token_id = self.tokenizer.convert_tokens_to_ids(target_nllb)
# Generate translation
translated_tokens = self.model.generate(
**inputs,
forced_bos_token_id=target_token_id,
max_length=max_length
)
# Decode
translated_text = self.tokenizer.batch_decode(
translated_tokens,
skip_special_tokens=True
)[0]
elapsed = round((time.time() - start) * 1000) # ms
return {
"translated": translated_text,
"source_lang": source_lang,
"target_lang": target_lang,
"source_nllb": source_nllb,
"target_nllb": target_nllb,
"time_ms": elapsed,
"error": None
}
except Exception as e:
print(f"[Translator] Translation error: {e}")
traceback.print_exc()
return {
"translated": text,
"error": str(e),
"time_ms": 0
}
def get_supported_languages(self) -> Dict[str, str]:
"""Return all supported languages as {code: name}."""
return dict(sorted(LANGUAGE_NAMES.items(), key=lambda x: x[1]))
def get_language_count(self) -> int:
"""Return the number of supported languages."""
return len(NLLB_LANGS)
def is_language_supported(self, lang_code: str) -> bool:
"""Check if a language is supported."""
return lang_code in NLLB_LANGS