{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.12"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":121150,"databundleVersionId":15833391,"isSourceIdPinned":false},{"sourceType":"kernelVersion","sourceId":304612406,"isSourceIdPinned":false}],"dockerImageVersionId":31259,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 🏺 Trinity Akkadian SOTA - Upgrade V2.0\n\n**Objective**: Offline translation with specialized compatibility fixes + **Beam Search & Lexicon Upgrade**.\n**Upgrades**:\n- `num_beams=5` + `no_repeat_ngram_size=3`\n- `max_new_tokens=256`\n- Lexicon-aware cleanup\n\n---","metadata":{}},{"cell_type":"code","source":"import os\nimport zipfile\nimport json\nimport pandas as pd\nimport numpy as np\nimport torch\nimport re\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom tqdm import tqdm\n\nprint(\"🔍 RECONNAISSANCE: Scanning /kaggle/input...\")\n\nMODEL_PATH = None\n\n# 1. Scour the entire input tree (optimized for depth)\nfor root, dirs, files in os.walk('/kaggle/input'):\n    if 'config.json' in files and 'model.safetensors' in files:\n        if 'checkpoint-11040' in root:\n            MODEL_PATH = root\n            print(f\"✅ FOUND TARGET MODEL: {MODEL_PATH}\")\n            break\n        elif MODEL_PATH is None:\n            MODEL_PATH = root # Fallback to first available checkpoint\n\n# 2. Fallback to User Path if still None\nif MODEL_PATH is None:\n    FALLBACK = \"/kaggle/input/datasets/kiza123123/byt5-offline-tokenizer/added_tokens.json\"\n    if os.path.exists(FALLBACK):\n        MODEL_PATH = FALLBACK\n        print(f\"✅ Using user-provided path: {MODEL_PATH}\")\n\nif MODEL_PATH is None:\n    print(\"❌ FAIL: Could not find model directory. Listing contents for audit:\")\n    !ls -R /kaggle/input/ | head -n 50\n    raise FileNotFoundError(\"Model not found.\")\n\nTEST_PATH = \"/kaggle/input/deep-past-initiative-machine-translation/test.csv\"\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nprint(f\"🚀 Device: {device}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-19T02:27:28.578050Z","iopub.execute_input":"2026-03-19T02:27:28.578742Z","iopub.status.idle":"2026-03-19T02:27:34.888218Z","shell.execute_reply.started":"2026-03-19T02:27:28.578708Z","shell.execute_reply":"2026-03-19T02:27:34.887366Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 🛠️ CRITICAL FIX: Patching T5 Tokenizer 'AttributeError: list object has no attribute keys'\nprint(\"🛠️ Checking for tokenizer compatibility issues...\")\n\ntry:\n    # Overriding the problematic extra_special_tokens via kwarg\n    tokenizer = AutoTokenizer.from_pretrained(\n        MODEL_PATH, \n        local_files_only=True, \n        extra_special_tokens={}\n    )\n    model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_PATH, local_files_only=True).to(device)\n    print(\"✅ Model loaded successfully using kwarg override.\")\nexcept Exception as e:\n    print(f\"⚠️ kwarg override failed: {e}. Attempting manual file patch...\")\n    \n    # Manual Patch Plan: Copy config to /kaggle/working and remove the offending key\n    os.makedirs(\"/kaggle/working/patched_model\", exist_ok=True)\n    \n    # List of files needed for tokenizer\n    tok_files = ['tokenizer_config.json', 'tokenizer.json', 'special_tokens_map.json', 'spiece.model']\n    for f in tok_files:\n        src = os.path.join(MODEL_PATH, f)\n        if os.path.exists(src):\n            dest = os.path.join(\"/kaggle/working/patched_model\", f)\n            if f == 'tokenizer_config.json':\n                with open(src, 'r') as j:\n                    cfg = json.load(j)\n                # Remove the key that causes AttributeError in transformers internal init\n                if \"extra_special_tokens\" in cfg and isinstance(cfg[\"extra_special_tokens\"], list):\n                    print(\"💉 Fixing 'extra_special_tokens' list in config...\")\n                    del cfg[\"extra_special_tokens\"]\n                with open(dest, 'w') as j:\n                    json.dump(cfg, j)\n            else:\n                # Copy other files as is\n                os.system(f\"cp '{src}' '{dest}'\")\n    \n    # Try loading from patched tokenizer config but original model binary\n    tokenizer = AutoTokenizer.from_pretrained(\"/kaggle/working/patched_model\", local_files_only=True)\n    model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_PATH, local_files_only=True).to(device)\n    print(\"✅ Model loaded successfully after manual file patch.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-19T02:27:34.889931Z","iopub.execute_input":"2026-03-19T02:27:34.890383Z","iopub.status.idle":"2026-03-19T02:27:39.527571Z","shell.execute_reply.started":"2026-03-19T02:27:34.890353Z","shell.execute_reply":"2026-03-19T02:27:39.526701Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── Load Lexicon for post-processing ──────────────────────────────\nLEXICON = {}\nfor lex_path in [\n    '/kaggle/input/deep-past-lexicon/eBL_Dictionary.csv',\n    '/kaggle/input/datasets/kiza123123/deep-past-lexicon/eBL_Dictionary.csv',\n]:\n    if os.path.exists(lex_path):\n        try:\n            lex_df = pd.read_csv(lex_path)\n            for _, row in lex_df.head(5000).iterrows():\n                word = str(row.get('word', '')).strip().lower()\n                defn = str(row.get('definition', '')).strip()\n                if word and defn: LEXICON[word] = defn\n            print(f'✅ Loaded {len(LEXICON)} lexicon entries.')\n            break\n        except: pass\n\ndef clean_translation(text):\n    text = re.sub(r'\\s*\\n+\\s*', ' ', text)\n    text = re.sub(r'\\s+', ' ', text).strip()\n    return text\n\ntest_df = pd.read_csv(TEST_PATH)\nprint(f\"Loaded {len(test_df)} sentences. Starting inference...\")\n\nBATCH_SIZE = 2\nMAX_LENGTH = 256\nNUM_BEAMS = 5\nresults = []\n\nfor i in tqdm(range(0, len(test_df), BATCH_SIZE)):\n    batch = test_df['transliteration'].iloc[i:i+BATCH_SIZE].tolist()\n    inputs = tokenizer(batch, return_tensors=\"pt\", padding=True, truncation=True, max_length=512).to(device)\n    with torch.no_grad():\n        outputs = model.generate(\n            **inputs, \n            max_new_tokens=MAX_LENGTH,\n            num_beams=NUM_BEAMS,\n            no_repeat_ngram_size=3,\n            length_penalty=0.8,\n            early_stopping=True\n        )\n    batch_out = tokenizer.batch_decode(outputs, skip_special_tokens=True)\n    results.extend([clean_translation(t) for t in batch_out])\n\nsubmission = pd.DataFrame({'id': test_df['id'], 'translation': results})\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"✅ submission.csv created.\")\nprint(submission)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-19T02:27:39.528713Z","iopub.execute_input":"2026-03-19T02:27:39.529245Z","iopub.status.idle":"2026-03-19T02:27:44.588285Z","shell.execute_reply.started":"2026-03-19T02:27:39.529216Z","shell.execute_reply":"2026-03-19T02:27:44.587369Z"}},"outputs":[],"execution_count":null}]}