{"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":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":121150,"databundleVersionId":15833391},{"sourceType":"datasetVersion","sourceId":14340674,"datasetId":9156186,"databundleVersionId":15148873},{"sourceType":"datasetVersion","sourceId":14899351,"datasetId":9366631,"databundleVersionId":15763950},{"sourceType":"modelInstanceVersion","sourceId":755680,"databundleVersionId":15750522,"modelInstanceId":577094,"modelId":589419},{"sourceType":"modelInstanceVersion","sourceId":4251,"databundleVersionId":6198432,"modelInstanceId":3045,"modelId":575},{"sourceType":"modelInstanceVersion","sourceId":82982,"databundleVersionId":9210550,"modelInstanceId":69710,"modelId":94840}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# ==============================================================================\n# AKKADIAN TO ENGLISH - GODKUN CUSTOM ELITE PIPELINE (LB 35.9+ Target)\n# ==============================================================================\nimport os\nos.environ[\"PYTORCH_CUDA_ALLOC_CONF\"] = \"expandable_segments:True\"\n\nimport gc\nimport re\nimport math\nimport random\nimport logging\nfrom dataclasses import dataclass\nfrom pathlib import Path\nfrom typing import List, Dict, Tuple\nfrom contextlib import nullcontext\n\nimport pandas as pd\nimport numpy as np\nimport torch\nfrom tqdm.auto import tqdm\nfrom transformers import AutoModelForSeq2SeqLM, AutoTokenizer\n\n# ==========================================\n# 1. DYNAMIC MODEL LOCATOR\n# ==========================================\ndef find_model_path(keyword1, keyword2=\"\"):\n    \"\"\"Scans Kaggle inputs to automatically find the attached model directories.\"\"\"\n    for root, dirs, files in os.walk(\"/kaggle/input\"):\n        if \"config.json\" in files:\n            root_lower = root.lower()\n            if keyword1 in root_lower and (not keyword2 or keyword2 in root_lower):\n                return root\n    return None\n\nmodel_a = find_model_path(\"final-byt5\") or find_model_path(\"optimized-34x\")\nmodel_b = find_model_path(\"mbr-v2\") or find_model_path(\"mattiaangeli\")\n\nif not model_a or not model_b:\n    raise ValueError(\"❌ ERROR: Could not find ByT5 models! Please ensure 'final-byt5' and 'byt5-akkadian-mbr-v2' are attached to the notebook.\")\n\n# ==========================================\n# 2. CONFIGURATION\n# ==========================================\n@dataclass\nclass GodKunConfig:\n    test_data_path: str = \"/kaggle/input/deep-past-initiative-machine-translation/test.csv\"\n    output_dir: str = \"/kaggle/working/\"\n    \n    model_a_path: str = model_a\n    model_b_path: str = model_b\n    \n    max_input_length: int = 512\n    max_new_tokens: int = 384\n    batch_size: int = 2\n\n    # Elite Candidate Generation Settings\n    num_beam_cands: int = 4\n    num_sample_cands: int = 3\n    num_beams: int = 8\n    mbr_top_p: float = 0.92\n    mbr_temperature: float = 0.75\n    mbr_pool_cap: int = 36\n    agreement_bonus: float = 0.035\n    \n    seed: int = 42\n\n    def __post_init__(self):\n        self.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n        Path(self.output_dir).mkdir(parents=True, exist_ok=True)\n        self.use_bf16_amp = bool(self.device.type == \"cuda\" and getattr(torch.cuda, \"is_bf16_supported\", lambda: False)())\n\n# ==========================================\n# 3. UTILITIES & LOGGING\n# ==========================================\ndef setup_logging():\n    for h in logging.root.handlers[:]:\n        logging.root.removeHandler(h)\n    logging.basicConfig(level=logging.INFO, format=\"%(asctime)s | %(levelname)s | %(message)s\")\n    return logging.getLogger(\"GodKun_Engine\")\n\nlogger = setup_logging()\n\ndef set_seed(seed: int):\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n\ndef bf16_ctx(device, enabled):\n    if enabled and device.type == \"cuda\":\n        return torch.autocast(device_type=\"cuda\", dtype=torch.bfloat16)\n    return nullcontext()\n\n# ==========================================\n# 4. ADVANCED PRE/POST-PROCESSING (35.9 Fixes)\n# ==========================================\nGAP_UNIFIED_RE = re.compile(r\"<\\s*big[\\s_\\-]*gap\\s*>|<\\s*gap\\s*>|\\bbig[\\s_\\-]*gap\\b|\\bx(?:\\s+x)+\\b|\\.{3,}|\\u2026+|\\[\\.+\\]|\\[\\s*x\\s*\\]|\\(\\s*x\\s*\\)|(?<!\\w)x{2,}(?!\\w)|(?<!\\w)x(?!\\w)|\\(\\s*large\\s+break\\s*\\)|\\(\\s*break\\s*\\)|\\(\\s*\\d+\\s+broken\\s+lines?\\s*\\)\", re.I)\n\n# The LB 35.9 Specific Corrections\n_CURLY_DQ_RE = re.compile(\"[\\u201c\\u201d]\") \n_CURLY_SQ_RE = re.compile(\"[\\u2018\\u2019]\") \n_COMMODITY_RE = re.compile(r'(?<=\\s)-(gold|tax|textiles)\\b')\n_COMMODITY_REPL = {\"gold\": \"pašallum gold\", \"tax\": \"šadduātum tax\", \"textiles\": \"kutānum textiles\"}\n_SHEKEL_REPLS = [\n    (re.compile(r'5\\s+11\\s*/\\s*12\\s+shekels?', re.I), '6 shekels less 15 grains'),\n    (re.compile(r'5\\s*/\\s*12\\s+shekels?', re.I), '⅓ shekel 15 grains'),\n    (re.compile(r'7\\s*/\\s*12\\s+shekels?', re.I), '½ shekel 15 grains'),\n    (re.compile(r'1\\s*/\\s*12\\s*(?:\\(shekel\\)|\\bshekel)?', re.I), '15 grains'),\n]\n_HACEK_TRANS = str.maketrans({\"ḫ\": \"h\", \"Ḫ\": \"H\"})\n\nclass GodKunPreprocessor:\n    def preprocess_batch(self, texts: List[str]) -> List[str]:\n        ser = pd.Series(texts).fillna(\"\").astype(str)\n        ser = ser.str.replace(GAP_UNIFIED_RE, \"<gap>\", regex=True)\n        ser = ser.str.replace(r\"\\s+\", \" \", regex=True).str.strip()\n        return ser.tolist()\n\nclass GodKunPostprocessor:\n    def postprocess_batch(self, translations: List[str]) -> List[str]:\n        s = pd.Series(translations).fillna(\"\").astype(str)\n        s = s.str.replace(r\"(?:<gap>\\s*){2,}\", \"<gap>\", regex=True)\n        \n        # Apply 35.9 Bug Fixes\n        s = s.str.replace(_COMMODITY_RE, lambda m: _COMMODITY_REPL[m.group(1)], regex=True)\n        for pat, repl in _SHEKEL_REPLS:\n            s = s.str.replace(pat, repl, regex=True)\n        \n        s = s.str.replace(_CURLY_DQ_RE, '\"', regex=True)\n        s = s.str.replace(_CURLY_SQ_RE, \"'\", regex=True)\n        s = s.str.translate(_HACEK_TRANS)\n        \n        # Fix hallucinated repeating words\n        s = s.str.replace(r\"\\b(\\w+)(?:\\s+\\1\\b)+\", r\"\\1\", regex=True)\n        s = s.str.replace(r\"\\s+\", \" \", regex=True).str.strip()\n        return s.tolist()\n\n# ==========================================\n# 5. MBR CONSENSUS MATH\n# ==========================================\ndef get_ngrams(tokens: List[str], n: int) -> Dict[Tuple[str, ...], int]:\n    counts = {}\n    for i in range(len(tokens) - n + 1):\n        ng = tuple(tokens[i:i + n])\n        counts[ng] = counts.get(ng, 0) + 1\n    return counts\n\ndef sentence_bleu_smoothed(hyp: str, ref: str, max_n: int = 4) -> float:\n    hyp_tok, ref_tok = hyp.strip().split(), ref.strip().split()\n    if not hyp_tok or not ref_tok: return 0.0\n    bp = min(1.0, math.exp(1.0 - len(ref_tok) / max(len(hyp_tok), 1)))\n    log_avg = 0.0\n    for n in range(1, max_n + 1):\n        hyp_ng, ref_ng = get_ngrams(hyp_tok, n), get_ngrams(ref_tok, n)\n        clipped = sum(min(cnt, ref_ng.get(ng, 0)) for ng, cnt in hyp_ng.items())\n        total = sum(hyp_ng.values())\n        if total == 0: return 0.0\n        p_n = (clipped / total) if n == 1 else ((clipped + 1.0) / (total + 1.0))\n        if p_n <= 0: return 0.0\n        log_avg += math.log(p_n)\n    return float(bp * math.exp(log_avg / max_n))\n\ndef char_ngrams(text: str, n: int) -> Dict[str, int]:\n    if len(text) < n: return {}\n    counts = {}\n    for i in range(len(text) - n + 1):\n        ng = text[i:i + n]\n        counts[ng] = counts.get(ng, 0) + 1\n    return counts\n\ndef sentence_chrfpp(hyp: str, ref: str, char_order=6, word_order=2, beta=2.0) -> float:\n    hyp, ref = hyp.strip(), ref.strip()\n    if not hyp or not ref: return 0.0\n    precisions, recalls = [], []\n    for n in range(1, char_order + 1):\n        hyp_ng, ref_ng = char_ngrams(hyp, n), char_ngrams(ref, n)\n        if not hyp_ng or not ref_ng: continue\n        overlap = sum(min(cnt, ref_ng.get(ng, 0)) for ng, cnt in hyp_ng.items())\n        hyp_total, ref_total = sum(hyp_ng.values()), sum(ref_ng.values())\n        if hyp_total > 0: precisions.append(overlap / hyp_total)\n        if ref_total > 0: recalls.append(overlap / ref_total)\n\n    hyp_w, ref_w = hyp.split(), ref.split()\n    for n in range(1, word_order + 1):\n        hyp_ng, ref_ng = get_ngrams(hyp_w, n), get_ngrams(ref_w, n)\n        if not hyp_ng or not ref_ng: continue\n        overlap = sum(min(cnt, ref_ng.get(ng, 0)) for ng, cnt in hyp_ng.items())\n        hyp_total, ref_total = sum(hyp_ng.values()), sum(ref_ng.values())\n        if hyp_total > 0: precisions.append(overlap / hyp_total)\n        if ref_total > 0: recalls.append(overlap / ref_total)\n\n    if not precisions or not recalls: return 0.0\n    p, r = sum(precisions) / len(precisions), sum(recalls) / len(recalls)\n    if p <= 0 or r <= 0: return 0.0\n    beta2 = beta * beta\n    return float((1 + beta2) * p * r / (beta2 * p + r))\n\nclass MBRSelector:\n    def __init__(self, cfg: GodKunConfig):\n        self.cfg = cfg\n\n    def pick(self, candidates: List[str]) -> str:\n        counts, order = {}, []\n        for x in candidates:\n            t = str(x or \"\").strip()\n            if not t: continue\n            if t not in counts:\n                order.append(t)\n                counts[t] = 0\n            counts[t] += 1\n            \n        if self.cfg.mbr_pool_cap > 0: order = order[: self.cfg.mbr_pool_cap]\n        if not order: return \"The tablet is too damaged to translate.\"\n        if len(order) == 1: return order[0]\n\n        best_text, best_score = order[0], -1e9\n        for cand in order:\n            support, denom = 0.0, 0\n            for other in order:\n                if other == cand: continue\n                w = counts.get(other, 1)\n                bleu = sentence_bleu_smoothed(cand, other)\n                chrf = sentence_chrfpp(cand, other)\n                util = float(math.sqrt(bleu * chrf)) if (bleu > 0 and chrf > 0) else 0.0\n                support += util * w\n                denom += w\n            if denom > 0: support /= denom\n            support += self.cfg.agreement_bonus * max(0, counts.get(cand, 1) - 1)\n            \n            if support > best_score:\n                best_score = support\n                best_text = cand\n        return best_text\n\n# ==========================================\n# 6. ENGINE & EXECUTION\n# ==========================================\nclass ModelWrapper:\n    def __init__(self, path: str, cfg: GodKunConfig, label: str):\n        self.cfg = cfg\n        self.label = label\n        logger.info(f\"[{label}] Loading model from memory...\")\n        self.tokenizer = AutoTokenizer.from_pretrained(path, local_files_only=True)\n        self.model = AutoModelForSeq2SeqLM.from_pretrained(path, local_files_only=True).to(cfg.device).eval()\n\n    def generate(self, texts: List[str]) -> List[List[str]]:\n        inputs = self.tokenizer(texts, return_tensors=\"pt\", padding=True, truncation=True, max_length=self.cfg.max_input_length).to(self.cfg.device)\n        \n        with bf16_ctx(self.cfg.device, self.cfg.use_bf16_amp), torch.no_grad():\n            beam_out = self.model.generate(\n                **inputs, do_sample=False, num_beams=self.cfg.num_beams, \n                num_return_sequences=self.cfg.num_beam_cands, max_new_tokens=self.cfg.max_new_tokens\n            )\n            beam_texts = self.tokenizer.batch_decode(beam_out, skip_special_tokens=True)\n            \n            sample_texts = []\n            if self.cfg.num_sample_cands > 0:\n                sample_out = self.model.generate(\n                    **inputs, do_sample=True, num_beams=1, top_p=self.cfg.mbr_top_p, \n                    temperature=self.cfg.mbr_temperature, num_return_sequences=self.cfg.num_sample_cands, \n                    max_new_tokens=self.cfg.max_new_tokens\n                )\n                sample_texts = self.tokenizer.batch_decode(sample_out, skip_special_tokens=True)\n                \n        pools = []\n        rb, rs = self.cfg.num_beam_cands, self.cfg.num_sample_cands\n        for i in range(len(texts)):\n            p = list(beam_texts[i*rb:(i+1)*rb])\n            if rs > 0: p.extend(sample_texts[i*rs:(i+1)*rs])\n            pools.append(p)\n        return pools\n\ndef main():\n    cfg = GodKunConfig()\n    set_seed(cfg.seed)\n    \n    logger.info(\"=\" * 60)\n    logger.info(\"GODKUN PIPELINE | ByT5 Multi-Model Ensemble + 35.9 MBR\")\n    logger.info(f\"Loaded Model A: {cfg.model_a_path.split('/')[-1]}\")\n    logger.info(f\"Loaded Model B: {cfg.model_b_path.split('/')[-1]}\")\n    logger.info(\"=\" * 60)\n    \n    test_df = pd.read_csv(cfg.test_data_path)\n    prep = GodKunPreprocessor()\n    test_texts = [\"translate Akkadian to English: \" + t for t in prep.preprocess_batch(test_df[\"transliteration\"].tolist())]\n    \n    all_pools = {i: [] for i in range(len(test_texts))}\n    model_paths = [(cfg.model_a_path, \"Model-A\"), (cfg.model_b_path, \"Model-B\")]\n    \n    for path, label in model_paths:\n        wrapper = ModelWrapper(path, cfg, label)\n        for i in tqdm(range(0, len(test_texts), cfg.batch_size), desc=f\"{label} Generating\"):\n            batch = test_texts[i:i + cfg.batch_size]\n            pools = wrapper.generate(batch)\n            for j, pool in enumerate(pools):\n                all_pools[i + j].extend(pool)\n                \n        del wrapper.model, wrapper.tokenizer\n        gc.collect()\n        torch.cuda.empty_cache()\n\n    logger.info(\"⚖️ Running MBR Consensus Selector...\")\n    post = GodKunPostprocessor()\n    mbr = MBRSelector(cfg)\n    \n    final_preds = []\n    for i in tqdm(range(len(test_texts)), desc=\"MBR Scoring\"):\n        cleaned_pool = post.postprocess_batch(all_pools[i])\n        best = mbr.pick(cleaned_pool)\n        final_preds.append(best if best.strip() else \"The tablet is too damaged to translate.\")\n\n    submission = pd.DataFrame({'id': test_df['id'], 'translation': final_preds})\n    submission.to_csv(\"submission.csv\", index=False)\n    \n    logger.info(\"=\" * 60)\n    logger.info(\"✅ PIPELINE COMPLETE. Submission saved to submission.csv\")\n    logger.info(\"=\" * 60)\n\nif __name__ == \"__main__\":\n    main()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-15T06:20:43.299695Z","iopub.execute_input":"2026-03-15T06:20:43.300596Z","iopub.status.idle":"2026-03-15T06:22:37.592004Z","shell.execute_reply.started":"2026-03-15T06:20:43.300554Z","shell.execute_reply":"2026-03-15T06:22:37.591472Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}