{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":121150,"databundleVersionId":15061024,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":14328947,"sourceType":"datasetVersion","datasetId":9147887},{"sourceId":287169617,"sourceType":"kernelVersion"},{"sourceId":287306416,"sourceType":"kernelVersion"},{"sourceId":288398539,"sourceType":"kernelVersion"},{"sourceId":288715334,"sourceType":"kernelVersion"},{"sourceId":694614,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":526756,"modelId":540799}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"\n# 🏛️ Deep Past Initiative: Akkadian to English Translation Inference\n\n## Overview\nThis script executes the inference pipeline for translating transliterated Akkadian text \ninto English. It utilizes a fine-tuned **ByT5-based Seq2Seq model** optimized for \nhandling fragmented cuneiform texts (gap filling).\n\n## Key Pipeline Steps\n1. **Data Preprocessing**: Normalizes gap markers (e.g., `[...]` -> `<gap>`) using regex to match the training token distribution.\n2. **Model Loading**: Initializes the tokenizer and model weights on the available accelerator (CUDA/CPU).\n3. **Batch Inference**: Uses a custom PyTorch `InferenceDataset` and `DataLoader` to generate translations efficiently using Beam Search (num_beams=4).\n4. **Post-Processing & Submission**: Decodes the output tensors and formats the final CSV for evaluation.\n\n## Dependencies\n- `transformers`: For model architecture and tokenization.\n- `torch`: For tensor operations and hardware acceleration.\n- `pandas`: For data manipulation and I/O.\n","metadata":{}},{"cell_type":"code","source":"# Thanks to 耶✌ \nimport os\nimport pandas as pd\nimport torch\nfrom torch.utils.data import DataLoader, Dataset\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom tqdm.auto import tqdm\nimport re","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-29T10:40:30.803820Z","iopub.execute_input":"2025-12-29T10:40:30.804030Z","iopub.status.idle":"2025-12-29T10:40:44.895744Z","shell.execute_reply.started":"2025-12-29T10:40:30.804008Z","shell.execute_reply":"2025-12-29T10:40:44.894981Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==========================================\n# Text Preprocessing Utility Functions\n# ==========================================\ndef replace_gaps(text):\n    if pd.isna(text): \n        return text\n# Replace variations of triple dots or bracketed dots with <big_gap>\n    text = re.sub(r'\\[\\.{3}(?:\\s+\\.{3})+\\]\\s+\\.{3}(?:\\s+\\.{3})+', '<big_gap>', text)\n    text = re.sub(r'\\[\\.{3}(?:\\s+\\.{3})+\\]', '<big_gap>', text)\n    text = re.sub(r'\\.{3}(?:\\s+\\.{3})+', '<big_gap>', text)\n# Standardize single missing characters 'x' to <gap>\n    text = re.sub(r'\\[x\\]', '<gap>', text)\n    text = re.sub(r' x ', ' <gap> ', text)\n# Handle ellipsis characters and bracketed ellipsis\n    text = re.sub(r'\\[…\\]', '<big_gap>', text)\n    text = re.sub(r'\\[\\.\\.\\.\\]', '<big_gap>', text)\n    text = re.sub(r'…', '<big_gap>', text)\n    text = re.sub(r'\\.\\.\\.', '<big_gap>', text)\n\n    return text\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-29T10:40:44.897223Z","iopub.execute_input":"2025-12-29T10:40:44.897616Z","iopub.status.idle":"2025-12-29T10:40:44.902679Z","shell.execute_reply.started":"2025-12-29T10:40:44.897589Z","shell.execute_reply":"2025-12-29T10:40:44.902014Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def replace_gaps_back(text):\n    if pd.isna(text):  \n        return text\n    \n    text = re.sub(r'<gap>', 'x', text)\n    text = re.sub(r'<big_gap>', '...', text)\n\n    return text","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-29T10:40:44.904090Z","iopub.execute_input":"2025-12-29T10:40:44.904441Z","iopub.status.idle":"2025-12-29T10:40:44.924872Z","shell.execute_reply.started":"2025-12-29T10:40:44.904406Z","shell.execute_reply":"2025-12-29T10:40:44.924159Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==========================================\n# Configuration and Model Setup\n# ==========================================\n\n# Path to the fine-tuned model directory\nMODEL_PATH = \"/kaggle/input/train-gap-all-2/byt5-base-akkadian_gap4/\"\nTEST_DATA_PATH = \"/kaggle/input/deep-past-initiative-machine-translation/test.csv\"\n# Hyperparameters for inference\nBATCH_SIZE = 16\nMAX_LENGTH = 512\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\n# Load the tokenizer and the model architecture\ntokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(MODEL_PATH).to(DEVICE)\n# Set the model to evaluation mode (disables dropout, etc.)\nmodel.eval()\n\ntest_df = pd.read_csv(TEST_DATA_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-29T10:40:44.939833Z","iopub.execute_input":"2025-12-29T10:40:44.940041Z","iopub.status.idle":"2025-12-29T10:41:16.638837Z","shell.execute_reply.started":"2025-12-29T10:40:44.940020Z","shell.execute_reply":"2025-12-29T10:41:16.638255Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"PREFIX = \"translate Akkadian to English: \"\n\n# ==========================================\n# Dataset Class Definition\n# ==========================================\n\nclass InferenceDataset(Dataset):\n    def __init__(self, df, tokenizer):\n        self.texts = df['transliteration'].astype(str).tolist()\n        self.texts = [PREFIX + i for i in self.texts]\n        self.tokenizer = tokenizer\n        \n    def __len__(self):\n        return len(self.texts)\n    \n    def __getitem__(self, idx):\n        text = self.texts[idx]\n        # Tokenize the input text with padding and truncation\n        inputs = self.tokenizer(\n            text, \n            max_length=MAX_LENGTH, \n            padding=\"max_length\", \n            truncation=True, \n            return_tensors=\"pt\"\n        )\n        return {\n            \"input_ids\": inputs[\"input_ids\"].squeeze(0),\n            \"attention_mask\": inputs[\"attention_mask\"].squeeze(0)\n        }\n\ntest_dataset = InferenceDataset(test_df, tokenizer)\ntest_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False)\n\nprint(\"Starting Inference...\")\nall_predictions = []","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-29T10:41:16.639648Z","iopub.execute_input":"2025-12-29T10:41:16.639936Z","iopub.status.idle":"2025-12-29T10:41:16.649469Z","shell.execute_reply.started":"2025-12-29T10:41:16.639900Z","shell.execute_reply":"2025-12-29T10:41:16.648823Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with torch.no_grad():\n    for batch in tqdm(test_loader):\n        input_ids = batch[\"input_ids\"].to(DEVICE)\n        attention_mask = batch[\"attention_mask\"].to(DEVICE)\n  \n        outputs = model.generate(\n            input_ids=input_ids,\n            attention_mask=attention_mask,\n            max_length=MAX_LENGTH,\n            num_beams=4,\n            early_stopping=True\n        )\n        \n\n        decoded = tokenizer.batch_decode(outputs, skip_special_tokens=True)\n        all_predictions.extend([d.strip() for d in decoded])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-29T10:41:16.651527Z","iopub.execute_input":"2025-12-29T10:41:16.651942Z","iopub.status.idle":"2025-12-29T10:41:21.900876Z","shell.execute_reply.started":"2025-12-29T10:41:16.651903Z","shell.execute_reply":"2025-12-29T10:41:21.900041Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"id\": test_df[\"id\"],\n    \"translation\": all_predictions\n})\nsubmission[\"translation\"] = submission[\"translation\"].apply(lambda x: x if len(x) > 0 else \"broken text\")\n\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"Submission file saved successfully!\")\nsubmission.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-29T10:41:21.901985Z","iopub.execute_input":"2025-12-29T10:41:21.902510Z","iopub.status.idle":"2025-12-29T10:41:21.925493Z","shell.execute_reply.started":"2025-12-29T10:41:21.902485Z","shell.execute_reply":"2025-12-29T10:41:21.924840Z"}},"outputs":[],"execution_count":null}]}