Download scripts/predict_seq2seq.py from krislette/salinlahi: direct link, hf CLI and curl.
- Browser
- Download file 3.16 kB
-
https://huggingface.co/spaces/krislette/salinlahi/resolve/main/scripts/predict_seq2seq.py
- Command line
-
hf download hf://spaces/krislette/salinlahi/scripts/predict_seq2seq.py
-
curl -L -o predict_seq2seq.py https://huggingface.co/spaces/krislette/salinlahi/resolve/main/scripts/predict_seq2seq.py
3.16 kB
| import sys | |
| import yaml | |
| import torch | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| from src.models.recurrent.seq2seq import build_model | |
| from src.models.recurrent.tokenizer import SPMTokenizer, BOS_IDX, EOS_IDX | |
| from scripts.preprocess import preprocess_text | |
| LANGUAGE_PAIRS = { | |
| "fil_war": {"name": "Filipino -> Waray", "dir": "fil_war"}, | |
| "war_fil": {"name": "Waray -> Filipino", "dir": "war_fil"}, | |
| } | |
| def load_config(path: str = "config/model_config.yml") -> dict: | |
| with open(path, "r") as f: | |
| return yaml.safe_load(f) | |
| def load_translator(lang_key: str, config: dict, device: torch.device) -> tuple: | |
| artifact_dir = Path("models/recurrent") / LANGUAGE_PAIRS[lang_key]["dir"] | |
| checkpoint_path = artifact_dir / "best_model.pt" | |
| if not checkpoint_path.exists(): | |
| raise FileNotFoundError(f"No checkpoint at {checkpoint_path}.") | |
| # Load SPM from processed data dir (that's where it was trained) | |
| spm_path = str( | |
| Path(config["paths"]["processed_data_dir"]) | |
| / LANGUAGE_PAIRS[lang_key]["dir"] | |
| / "spm.model" | |
| ) | |
| source_tokenizer = SPMTokenizer(spm_path) | |
| target_tokenizer = SPMTokenizer(spm_path) | |
| checkpoint = torch.load(checkpoint_path, map_location=device) | |
| train_config = checkpoint.get("config", config) | |
| model = build_model( | |
| train_config, len(source_tokenizer), len(target_tokenizer), device | |
| ) | |
| model.load_state_dict(checkpoint["model_state_dict"]) | |
| model.eval() | |
| return model, source_tokenizer, target_tokenizer | |
| def translate( | |
| text: str, | |
| lang_key: str, | |
| config: dict, | |
| device: torch.device, | |
| max_output_length: int = 50, | |
| ) -> str: | |
| model, source_tokenizer, target_tokenizer = load_translator( | |
| lang_key, config, device | |
| ) | |
| cleaned_sentence = preprocess_text(text) | |
| source_ids = source_tokenizer.encode(cleaned_sentence.lower().strip())[:100] | |
| source_tensor = torch.tensor(source_ids, dtype=torch.long).unsqueeze(0).to(device) | |
| source_lengths = torch.tensor([len(source_ids)], dtype=torch.long) | |
| predicted_ids, _ = model.translate( | |
| source_tensor, source_lengths, BOS_IDX, EOS_IDX, max_output_length | |
| ) | |
| return target_tokenizer.decode(predicted_ids, skip_special_tokens=True) | |
| def translate_fil_to_war(text: str, config: dict, device: torch.device) -> str: | |
| return translate(text, "fil_war", config, device) | |
| def translate_war_to_fil(text: str, config: dict, device: torch.device) -> str: | |
| return translate(text, "war_fil", config, device) | |
| if __name__ == "__main__": | |
| config = load_config() | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| tests = { | |
| "fil_war": "Sobrang saya ko na walang pasok sa trabaho bukas", | |
| "war_fil": "Nalipay kaayo ko nga wala koy trabaho ugma", | |
| } | |
| for key, sentence in tests.items(): | |
| info = LANGUAGE_PAIRS[key] | |
| try: | |
| result = translate(sentence, key, config, device) | |
| print(f"{info['name']}: {sentence!r} -> {result!r}") | |
| except FileNotFoundError as e: | |
| print(f"[{info['name']}] Skipped — {e}") | |