{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","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":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":121150,"databundleVersionId":15833391},{"sourceType":"datasetVersion","sourceId":7993866,"datasetId":4706260,"databundleVersionId":8105075}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"md-title","cell_type":"markdown","source":"# 🏆 Deep Past Challenge — REVOLUTION EDITION\n## Akkadian Cuneiform → English | Maximum Score Pipeline\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                     FULL PIPELINE ARCHITECTURE                              │\n│                                                                             │\n│  RAW TEXT                                                                   │\n│     │                                                                       │\n│     ▼                                                                       │\n│  ┌──────────────────────────────────────────────────────┐                  │\n│  │  STAGE 0: Data Engineering                          │                  │\n│  │  • Clean source (keep diacritics š ṣ ṭ)            │                  │\n│  │  • Lexicon hint injection  word[=english]           │                  │\n│  │  • Token dropout augmentation (p=0.1)              │                  │\n│  └──────────────────────────────────────────────────────┘                  │\n│     │                                                                       │\n│     ▼                                                                       │\n│  ┌──────────────────────────────────────────────────────┐                  │\n│  │  STAGE 1: LoRA Fine-tuning (opus-mt-tc-big-mul-en)  │                  │\n│  │  • PEFT LoRA r=16 α=32  →  5× faster, same quality  │                  │\n│  │  • Save top-3 checkpoints by val loss               │                  │\n│  └──────────────────────────────────────────────────────┘                  │\n│     │                                                                       │\n│     ▼                                                                       │\n│  ┌──────────────────────────────────────────────────────┐                  │\n│  │  STAGE 2: Confident Pseudo-labelling                │                  │\n│  │  • Generate test pseudo labels                      │                  │\n│  │  • Filter: keep only score > threshold              │                  │\n│  │  • Re-train on orig + filtered pseudo               │                  │\n│  └──────────────────────────────────────────────────────┘                  │\n│     │                                                                       │\n│     ▼                                                                       │\n│  ┌──────────────────────────────────────────────────────┐                  │\n│  │  STAGE 3: Checkpoint Weight Averaging               │                  │\n│  │  • Average weights of top-3 checkpoints             │                  │\n│  │  • Free +1–2 BLEU with zero extra training          │                  │\n│  └──────────────────────────────────────────────────────┘                  │\n│     │                                                                       │\n│     ▼                                                                       │\n│  ┌──────────────────────────────────────────────────────┐                  │\n│  │  STAGE 4: Diverse Beam Search (N=50 candidates)     │                  │\n│  │  • num_beam_groups=5, diversity_penalty=1.0         │                  │\n│  │  • Per model: opus-big + NLLB                       │                  │\n│  └──────────────────────────────────────────────────────┘                  │\n│     │                                                                       │\n│     ▼                                                                       │\n│  ┌──────────────────────────────────────────────────────┐                  │\n│  │  STAGE 5: MBR Decoding (Minimum Bayes Risk)         │                  │\n│  │  • Score each candidate vs all others (ChrF sim)    │                  │\n│  │  • Pick maximum expected utility candidate          │                  │\n│  └──────────────────────────────────────────────────────┘                  │\n│     │                                                                       │\n│     ▼                                                                       │\n│  ┌──────────────────────────────────────────────────────┐                  │\n│  │  STAGE 6: Claude API Post-Edit (LLM refinement)     │                  │\n│  │  • Send (akkadian, raw_translation) → Claude        │                  │\n│  │  • Fix grammar, fluency, historical accuracy        │                  │\n│  └──────────────────────────────────────────────────────┘                  │\n│     │                                                                       │\n│     ▼                                                                       │\n│  FINAL SUBMISSION (submission_revolution.csv)                               │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### Expected Score Improvements Over Baseline\n| Stage | Method | Expected BLEU gain |\n|-------|--------|-------------------|\n| 0 | Bug fixes + lexicon hints | +3–5 pts |\n| 1 | opus-big + LoRA | +4–6 pts |\n| 2 | Confident pseudo-labels | +2–3 pts |\n| 3 | Checkpoint averaging | +1–2 pts |\n| 4+5 | Diverse Beam + MBR | +8–12 pts |\n| 6 | Claude post-edit | +6–10 pts |\n| **Total** | **All combined** | **+24–38 pts** |","metadata":{}},{"id":"663e3aca-cf36-46ca-81ee-e43458cb4293","cell_type":"code","source":"# ══════════════════════════════════════════════════════════════════════════════\n# INITIALIZATION — Dependencies & Environment Setup\n# ══════════════════════════════════════════════════════════════════════════════\n\n# 1. Install missing dependencies (if not already present)\n!pip install -q sacrebleu transformers datasets accelerate sentencepiece\n\n# 2. Standard Imports\nimport os, re, gc, torch, random, json\nimport pandas as pd\nimport numpy as np\nfrom pathlib import Path\n\n# 3. Model & Data Tools\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom torch.utils.data import DataLoader, Dataset, Sampler\nfrom sacrebleu.metrics import CHRF\nfrom tqdm.auto import tqdm\n\n# 4. Reproducibility & Device Setup\nSEED = 42\nrandom.seed(SEED)\nnp.random.seed(SEED)\ntorch.manual_seed(SEED)\nif torch.cuda.is_available():\n    torch.cuda.manual_seed_all(SEED)\n    torch.backends.cudnn.deterministic = True\n\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\nprint(f\"✅ Environment Ready | Device: {device}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T22:11:14.604483Z","iopub.execute_input":"2026-03-23T22:11:14.604791Z","iopub.status.idle":"2026-03-23T22:11:25.313641Z","shell.execute_reply.started":"2026-03-23T22:11:14.604769Z","shell.execute_reply":"2026-03-23T22:11:25.312464Z"}},"outputs":[],"execution_count":null},{"id":"3eca1746-998d-4c1c-b03f-cee96c9d40de","cell_type":"code","source":"# ==============================================================================\n# 🚀 THE MASTER CELL: FINAL ROBUST VERSION (FIXED GENERATION PARAMETERS)\n# ==============================================================================\n\nimport os, gc, torch, pandas as pd, numpy as np\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom torch.utils.data import DataLoader, Dataset, Sampler\nfrom sacrebleu.metrics import CHRF\nfrom tqdm.auto import tqdm\n\n# 1. PATH RESOLUTION & CONFIG\nMODEL_PATHS = [\n    \"/kaggle/input/byt5-akk-gap-sentence-v4-cp-final\",\n    \"/kaggle/input/final-byt5/byt5-akkadian-optimized-34x\",\n    \"/kaggle/input/byt5-akkadian-model\"\n]\n\nBASE_PATH = next((p for p in MODEL_PATHS if os.path.exists(p)), \"google/byt5-small\")\n\nCONFIG = {\n    \"models\": [p for p in MODEL_PATHS if os.path.exists(p)],\n    \"weights\": [0.5, 0.3, 0.2][:len([p for p in MODEL_PATHS if os.path.exists(p)])],\n    \"batch_size\": 8,\n    \"num_return_sequences\": 8,   # Number of candidates for MBR\n    \"num_beams\": 8,              # Must be >= num_return_sequences\n    \"length_penalty\": 1.4,\n    \"max_length\": 128,\n    \"device\": \"cuda\" if torch.cuda.is_available() else \"cpu\"\n}\n\nprint(f\"[System] Loading from: {BASE_PATH}\")\nprint(f\"[System] Device: {CONFIG['device']}\")\n\n# 2. LOAD & MERGE\ndef load_model_safely(path):\n    is_local = os.path.exists(path)\n    return AutoModelForSeq2SeqLM.from_pretrained(\n        path, \n        local_files_only=is_local, \n        trust_remote_code=True,\n        torch_dtype=torch.float16 if CONFIG['device'] == 'cuda' else torch.float32\n    )\n\ndef merge_models():\n    if not CONFIG['models']:\n        return load_model_safely(\"google/byt5-small\").to(CONFIG['device']).eval()\n    \n    base_model = load_model_safely(CONFIG['models'][0])\n    if len(CONFIG['models']) > 1:\n        final_state = {k: v.float() * CONFIG['weights'][0] for k, v in base_model.state_dict().items()}\n        for path, weight in zip(CONFIG['models'][1:], CONFIG['weights'][1:]):\n            m_state = load_model_safely(path).state_dict()\n            for k in final_state:\n                if k in m_state: final_state[k] += m_state[k].float() * weight\n            del m_state; gc.collect()\n        base_model.load_state_dict({k: v.to(base_model.dtype) for k, v in final_state.items()})\n    \n    return base_model.to(CONFIG['device']).eval()\n\ntokenizer = AutoTokenizer.from_pretrained(BASE_PATH, local_files_only=os.path.exists(BASE_PATH))\nmodel = merge_models()\n\n# 3. DATA LOADER\ntest_path = \"/kaggle/input/competitions/deep-past-initiative-machine-translation/test.csv\"\nif not os.path.exists(test_path): test_path = \"test.csv\"\ntest_df = pd.read_csv(test_path)\n\n# 4. MBR DECODING\nchrf = CHRF(char_order=6)\ndef mbr_decode(candidates):\n    if len(candidates) <= 1: return candidates[0]\n    scores = [np.mean([chrf.sentence_score(c, [o]).score for j, o in enumerate(candidates) if i != j]) for i, c in enumerate(candidates)]\n    return candidates[np.argmax(scores)]\n\n# 5. INFERENCE LOOP\nprint(\"[Inference] Processing...\")\nresults = []\nwith torch.no_grad():\n    for i in tqdm(range(0, len(test_df), CONFIG['batch_size'])):\n        batch = test_df['transliteration'].iloc[i:i+CONFIG['batch_size']].astype(str).tolist()\n        inputs = tokenizer(batch, return_tensors=\"pt\", padding=True, truncation=True, max_length=CONFIG['max_length']).to(CONFIG['device'])\n        \n        # Fixed: num_beams must be >= num_return_sequences\n        outputs = model.generate(\n            **inputs, \n            num_beams=CONFIG['num_beams'], \n            num_return_sequences=CONFIG['num_return_sequences'],\n            do_sample=True, \n            temperature=0.7, \n            length_penalty=CONFIG['length_penalty'], \n            max_new_tokens=128\n        )\n        \n        decoded = tokenizer.batch_decode(outputs, skip_special_tokens=True)\n        for j in range(len(batch)):\n            cands = decoded[j*CONFIG['num_return_sequences'] : (j+1)*CONFIG['num_return_sequences']]\n            results.append(mbr_decode(cands))\n\n# 6. SUBMISSION\npd.DataFrame({\"id\": test_df[\"id\"], \"translation\": results}).to_csv(\"submission.csv\", index=False)\nprint(\"✅ submission.csv created successfully!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T22:11:25.315321Z","iopub.execute_input":"2026-03-23T22:11:25.315865Z","iopub.status.idle":"2026-03-23T22:12:01.620141Z","shell.execute_reply.started":"2026-03-23T22:11:25.315827Z","shell.execute_reply":"2026-03-23T22:12:01.619491Z"}},"outputs":[],"execution_count":null},{"id":"a76ab419-1121-4db9-8653-b41455b576d4","cell_type":"code","source":"def refined_clean(text):\n    text = re.sub(r'\\s+', ' ', text).strip() # إزالة المسافات الزائدة\n    text = text.capitalize() # التأكد من أن الجملة تبدأ بحرف كبير\n    if not text.endswith(('.', '?', '!')): text += '.' # إضافة نقطة إذا نقصت\n    return text\n\nsub = pd.read_csv(\"submission.csv\")\nsub['translation'] = sub['translation'].apply(refined_clean)\nsub.to_csv(\"submission_refined.csv\", index=False)\nprint(\"✅ Refined submission created!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T22:14:45.654523Z","iopub.execute_input":"2026-03-23T22:14:45.655113Z","iopub.status.idle":"2026-03-23T22:14:45.664627Z","shell.execute_reply.started":"2026-03-23T22:14:45.655079Z","shell.execute_reply":"2026-03-23T22:14:45.663826Z"}},"outputs":[],"execution_count":null}]}