{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":121150,"databundleVersionId":15061024,"sourceType":"competition"},{"sourceId":14410665,"sourceType":"datasetVersion","datasetId":9203761},{"sourceId":14661932,"sourceType":"datasetVersion","datasetId":9366631}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"default_parameters":{},"duration":79.581197,"end_time":"2026-02-02T16:08:25.569044","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2026-02-02T16:07:05.987847","version":"2.6.0"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"0c9fec51a04f43a49813a7782ee633f5":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"146b341d0c6a468fa664630244b600ae":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_3a8f97f78b5a44bcb6b8c96849690f32","placeholder":"​","style":"IPY_MODEL_a0c50ae7f4b849bb853ab96d1860ee7e","tabbable":null,"tooltip":null,"value":"🚀 Translating: 100%"}},"33a48a0f2fc8411aa63ab782089a1e9a":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_146b341d0c6a468fa664630244b600ae","IPY_MODEL_9889f22daab5402f9a4a5d0ed22ea518","IPY_MODEL_c853344c62d04ab2b35c0edade30547d"],"layout":"IPY_MODEL_3bce0f7c89374d149d8a1fad8cc06332","tabbable":null,"tooltip":null}},"3a8f97f78b5a44bcb6b8c96849690f32":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"3bce0f7c89374d149d8a1fad8cc06332":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"8ac1e7a994364f1ba1e5dd01656a4111":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"9889f22daab5402f9a4a5d0ed22ea518":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"success","description":"","description_allow_html":false,"layout":"IPY_MODEL_fa2c37175d04449f8bf7390ebc39280b","max":4,"min":0,"orientation":"horizontal","style":"IPY_MODEL_0c9fec51a04f43a49813a7782ee633f5","tabbable":null,"tooltip":null,"value":4}},"a0c50ae7f4b849bb853ab96d1860ee7e":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"c853344c62d04ab2b35c0edade30547d":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_f1e228165e734580bd7af1510d71ea12","placeholder":"​","style":"IPY_MODEL_8ac1e7a994364f1ba1e5dd01656a4111","tabbable":null,"tooltip":null,"value":" 4/4 [00:11&lt;00:00,  2.87s/it]"}},"f1e228165e734580bd7af1510d71ea12":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"fa2c37175d04449f8bf7390ebc39280b":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}}},"version_major":2,"version_minor":0}}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Cell 1: Minimal Environment Setup (Kaggle-Safe)\nimport os\nos.environ[\"OMP_NUM_THREADS\"] = \"4\"\nos.environ[\"MKL_NUM_THREADS\"] = \"4\"\nos.environ[\"TOKENIZERS_PARALLELISM\"] = \"false\"  # Critical for Kaggle stability\nos.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"3\"\n\nimport re\nimport warnings\nfrom pathlib import Path\nfrom typing import List\nfrom dataclasses import dataclass\nimport pandas as pd\nimport numpy as np\nimport torch\nfrom torch.utils.data import Dataset, DataLoader\nfrom torch.cuda.amp import autocast\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom tqdm.auto import tqdm\n\nwarnings.filterwarnings(\"ignore\")\n\nprint(f\"PyTorch: {torch.__version__} | CUDA: {torch.cuda.is_available()}\")\nif torch.cuda.is_available():\n    print(f\"GPU: {torch.cuda.get_device_name(0)} | Mem: {torch.cuda.get_device_properties(0).total_memory/1e9:.1f}GB\")\n    torch.backends.cudnn.benchmark = True","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T07:40:00.184253Z","iopub.execute_input":"2026-02-08T07:40:00.184507Z","iopub.status.idle":"2026-02-08T07:40:11.635313Z","shell.execute_reply.started":"2026-02-08T07:40:00.184487Z","shell.execute_reply":"2026-02-08T07:40:11.634518Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 2: Minimal Competition Config (Kaggle-Optimized)\n@dataclass\nclass Config:\n    test_path: str = \"/kaggle/input/deep-past-initiative-machine-translation/test.csv\"\n    model_path: str = \"/kaggle/input/final-byt5/byt5-akkadian-optimized-34x\"\n    out_dir: str = \"/kaggle/working/\"\n    \n    max_len: int = 512\n    max_new_tokens: int = 512\n    batch_size: int = 8\n    \n    # Decoding (optimized for Akkadian)\n    num_beams: int = 12\n    num_return: int = 3  # Ensemble size\n    length_penalty: float = 1.3\n    diversity_penalty: float = 1.2\n    repetition_penalty: float = 1.25\n    no_repeat_ngram: int = 3\n    \n    # Features\n    use_fp16: bool = True\n    use_ensemble: bool = True\n    aggressive_postproc: bool = True\n    \n    def __post_init__(self):\n        self.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n        Path(self.out_dir).mkdir(exist_ok=True, parents=True)\n        if not torch.cuda.is_available():\n            self.use_fp16 = False\n            self.batch_size = 4\n\ncfg = Config()\nprint(f\"\\n✅ Config | Device: {cfg.device} | Beams: {cfg.num_beams} | Batch: {cfg.batch_size}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T07:40:11.636764Z","iopub.execute_input":"2026-02-08T07:40:11.637249Z","iopub.status.idle":"2026-02-08T07:40:11.645121Z","shell.execute_reply.started":"2026-02-08T07:40:11.637224Z","shell.execute_reply":"2026-02-08T07:40:11.644332Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 3: Ultra-Stable Preprocessor (No Errors)\nclass Preprocessor:\n    def __init__(self):\n        # Multi-char substitutions FIRST\n        self.multi_subs = [\n            (re.compile(r\"š\"), \"sh\"), (re.compile(r\"Š\"), \"Sh\"),\n            (re.compile(r\"ḫ\"), \"h\"), (re.compile(r\"Ḫ\"), \"H\"),\n            (re.compile(r\"ṭ\"), \"t\"), (re.compile(r\"Ṭ\"), \"T\"),\n            (re.compile(r\"ṣ\"), \"s\"), (re.compile(r\"Ṣ\"), \"S\"),\n        ]\n        self.gap_big = re.compile(r\"(\\.{4,}|…{2,}|——+|xx{3,})\")\n        self.gap_med = re.compile(r\"(\\.{2,3}|…|xx{2})\")\n        self.gap_small = re.compile(r\"(\\s+x\\s+|\\s+x$|^x\\s+|(?<=\\w)x(?=\\w))\")\n    \n    def __call__(self, texts: List[str]) -> List[str]:\n        out = []\n        for text in texts:\n            if pd.isna(text) or not text:\n                out.append(\"\")\n                continue\n            text = str(text).strip()\n            for pat, repl in self.multi_subs:\n                text = pat.sub(repl, text)\n            text = self.gap_big.sub(\" <big_gap> \", text)\n            text = self.gap_med.sub(\" <gap> \", text)\n            text = self.gap_small.sub(\" <gap> \", text)\n            text = re.sub(r\"\\s+\", \" \", text).strip()\n            out.append(text if text else \"<empty>\")\n        return out\n\npreproc = Preprocessor()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T07:40:11.645908Z","iopub.execute_input":"2026-02-08T07:40:11.646235Z","iopub.status.idle":"2026-02-08T07:40:11.659610Z","shell.execute_reply.started":"2026-02-08T07:40:11.646214Z","shell.execute_reply":"2026-02-08T07:40:11.658828Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 4: Robust Postprocessor (No maketrans Errors)\nclass Postprocessor:\n    def __init__(self, aggressive: bool = True):\n        self.aggressive = aggressive\n        self.gap_pat = re.compile(r\"<\\s*gap\\s*>|<\\s*big_gap\\s*>\", re.I)\n        self.repeat_gap = re.compile(r\"(<gap>\\s*){3,}|(<big_gap>\\s*){2,}\")\n        self.space_punct = re.compile(r\"\\s+([.,;:])\")\n        self.whitespace = re.compile(r\"\\s{2,}\")\n        self.morph_rep = re.compile(r\"\\b(\\w+)(?:\\s+\\1\\b)+\")\n        \n        # SINGLE-CHAR mappings only (equal length)\n        self.char_trans = str.maketrans({\n            'ā':'a','ē':'e','ī':'i','ū':'u',\n            '₀':'0','₁':'1','₂':'2','₃':'3','₄':'4',\n            '₅':'5','₆':'6','₇':'7','₈':'8','₉':'9'\n        })\n        \n        self.forbidden = str.maketrans(\"\", \"\", '!?()\"——<>⌈⌋⌊[]+ʾ/;{}')\n        \n        # High-value Akkadian corrections\n        self.dict = {\n            \"lugal\":\"king\", \"ensi\":\"governor\", \"dumu\":\"son\", \"munus\":\"woman\",\n            \"nin\":\"lady\", \"dingir\":\"god\", \"kur\":\"mountain\", \"ki\":\"earth\",\n            \"an\":\"sky\", \"ud\":\"day\", \"iti\":\"month\", \"mu\":\"year\",\n            \"kug\":\"silver\", \"ab\":\"father\", \"ama\":\"mother\",\n        }\n    \n    def _fix_fracs(self, t):\n        t = re.sub(r\"(\\d+)\\.5\\b\", r\"\\1½\", t)\n        t = re.sub(r\"\\b0\\.5\\b\", \"½\", t)\n        t = re.sub(r\"(\\d+)\\.25\\b\", r\"\\1¼\", t)\n        t = re.sub(r\"\\b0\\.25\\b\", \"¼\", t)\n        t = re.sub(r\"(\\d+)\\.75\\b\", r\"\\1¾\", t)\n        t = re.sub(r\"\\b0\\.75\\b\", \"¾\", t)\n        return t\n    \n    def _dict_fix(self, t):\n        words = t.split()\n        out = []\n        for w in words:\n            clean = w.lower().strip(\".,;:!?\")\n            if clean in self.dict:\n                repl = self.dict[clean]\n                if w[0].isupper():\n                    repl = repl.capitalize()\n                punct = w[len(clean):] if len(w) > len(clean) else \"\"\n                out.append(repl + punct)\n            else:\n                out.append(w)\n        return \" \".join(out)\n    \n    def __call__(self, texts: List[str]) -> List[str]:\n        out = []\n        for t in texts:\n            if not isinstance(t, str) or not t.strip():\n                out.append(\"<empty>\")\n                continue\n            \n            # Char normalization\n            t = t.translate(self.char_trans)\n            \n            # Gap cleanup (SCORE CRITICAL)\n            t = self.gap_pat.sub(lambda m: \"<big_gap>\" if \"big\" in m.group(0).lower() else \"<gap>\", t)\n            t = self.repeat_gap.sub(\"<big_gap>\", t)\n            \n            # Fractions\n            t = self._fix_fracs(t)\n            \n            # Aggressive cleanup\n            if self.aggressive:\n                t = self.space_punct.sub(r\"\\1\", t)\n                t = self.whitespace.sub(\" \", t)\n                t = t.translate(self.forbidden)\n                t = self._dict_fix(t)\n                t = self.morph_rep.sub(r\"\\1\", t)\n            \n            t = t.strip().strip(\"-\").strip()\n            out.append(t if t else \"<empty>\")\n        return out\n\npostproc = Postprocessor(aggressive=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T07:40:30.750572Z","iopub.execute_input":"2026-02-08T07:40:30.750848Z","iopub.status.idle":"2026-02-08T07:40:30.764342Z","shell.execute_reply.started":"2026-02-08T07:40:30.750829Z","shell.execute_reply":"2026-02-08T07:40:30.763494Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 5: Minimal Dataset (No Length Caching Needed)\nclass DatasetAkkadian(Dataset):\n    def __init__(self, df, preproc):\n        self.ids = df[\"id\"].tolist()\n        texts = preproc(df[\"transliteration\"].fillna(\"\").tolist())\n        self.inputs = [\"translate Akkadian to English: \" + t for t in texts]\n    \n    def __len__(self):\n        return len(self.ids)\n    \n    def __getitem__(self, i):\n        return self.ids[i], self.inputs[i]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T07:40:40.057586Z","iopub.execute_input":"2026-02-08T07:40:40.058157Z","iopub.status.idle":"2026-02-08T07:40:40.063208Z","shell.execute_reply.started":"2026-02-08T07:40:40.058133Z","shell.execute_reply":"2026-02-08T07:40:40.062431Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 6: FIXED Inference Engine (Kaggle-Stable)\nclass InferenceEngine:\n    def __init__(self, cfg):\n        self.cfg = cfg\n        print(\"Loading model...\")\n        self.tokenizer = AutoTokenizer.from_pretrained(cfg.model_path)\n        \n        dtype = torch.float16 if (cfg.use_fp16 and torch.cuda.is_available()) else torch.float32\n        self.model = AutoModelForSeq2SeqLM.from_pretrained(\n            cfg.model_path,\n            torch_dtype=dtype,\n            low_cpu_mem_usage=True,\n        ).to(cfg.device).eval()\n        \n        print(f\"✓ Model loaded ({sum(p.numel() for p in self.model.parameters())/1e6:.1f}M params) on {cfg.device}\")\n    \n    def _rank_ensemble(self, seqs, scores):\n        \"\"\"Rank by confidence + gap penalty\"\"\"\n        if len(seqs) == 1:\n            return seqs[0]\n        \n        # Confidence normalized by length\n        conf = [scores[i].item() / max(len(s.split()), 1) for i, s in enumerate(seqs)]\n        # Gap penalty (fewer gaps = better reconstruction)\n        gap_pen = [-0.15 * (s.count(\"<gap>\") + s.count(\"<big_gap>\")) / max(len(s.split()), 1) for s in seqs]\n        combined = [c + p for c, p in zip(conf, gap_pen)]\n        return seqs[int(np.argmax(combined))]\n    \n    def __call__(self, df):\n        print(f\"Translating {len(df)} samples...\")\n        ds = DatasetAkkadian(df, preproc)\n        loader = DataLoader(\n            ds,\n            batch_size=self.cfg.batch_size,\n            shuffle=False,\n            num_workers=0,  # CRITICAL FIX: Avoid CUDA fork error\n            collate_fn=lambda x: ([i[0] for i in x], [i[1] for i in x]),\n            pin_memory=False,\n        )\n        \n        results = []\n        \n        with torch.inference_mode():\n            for batch_ids, batch_texts in tqdm(loader, desc=\"Translating\"):\n                # Tokenize in main process (safe)\n                tok = self.tokenizer(\n                    batch_texts,\n                    max_length=self.cfg.max_len,\n                    padding=True,\n                    truncation=True,\n                    return_tensors=\"pt\",\n                ).to(self.cfg.device)  # Move to device HERE (main process)\n                \n                # Generate\n                with autocast() if self.cfg.use_fp16 else nullcontext():\n                    out = self.model.generate(\n                        input_ids=tok.input_ids,\n                        attention_mask=tok.attention_mask,\n                        max_new_tokens=self.cfg.max_new_tokens,\n                        num_beams=self.cfg.num_beams,\n                        num_return_sequences=self.cfg.num_return if self.cfg.use_ensemble else 1,\n                        length_penalty=self.cfg.length_penalty,\n                        diversity_penalty=self.cfg.diversity_penalty,\n                        repetition_penalty=self.cfg.repetition_penalty,\n                        no_repeat_ngram_size=self.cfg.no_repeat_ngram,\n                        early_stopping=True,\n                        use_cache=True,\n                        return_dict_in_generate=True,\n                        output_scores=True,\n                    )\n                \n                # Decode\n                all_trans = self.tokenizer.batch_decode(out.sequences, skip_special_tokens=True)\n                \n                # Ensemble ranking\n                if self.cfg.use_ensemble:\n                    batch_size = len(batch_ids)\n                    n_seq = self.cfg.num_return\n                    for i in range(batch_size):\n                        start, end = i * n_seq, (i + 1) * n_seq\n                        cands = all_trans[start:end]\n                        scores = out.sequences_scores[start:end] if hasattr(out, 'sequences_scores') else None\n                        best = self._rank_ensemble(cands, scores)\n                        results.append((batch_ids[i], best))\n                else:\n                    cleaned = postproc(all_trans)\n                    results.extend(zip(batch_ids, cleaned))\n        \n        print(\"✓ Translation complete\")\n        return pd.DataFrame(results, columns=[\"id\", \"translation\"])\n\n# Null context\nfrom contextlib import contextmanager\n@contextmanager\ndef nullcontext():\n    yield","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T07:40:47.229077Z","iopub.execute_input":"2026-02-08T07:40:47.229681Z","iopub.status.idle":"2026-02-08T07:40:47.245294Z","shell.execute_reply.started":"2026-02-08T07:40:47.229654Z","shell.execute_reply":"2026-02-08T07:40:47.244370Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 7: Execution (Guaranteed Stable on Kaggle)\n# Load data\ndf_test = pd.read_csv(cfg.test_path)\nprint(f\"Loaded {len(df_test)} test samples\")\n\n# Run inference\nengine = InferenceEngine(cfg)\ndf_sub = engine(df_test)\n\n# Post-process final output\ndf_sub[\"translation\"] = postproc(df_sub[\"translation\"].fillna(\"<empty>\").tolist())\n\n# Save\nout_path = Path(cfg.out_dir) / \"submission.csv\"\ndf_sub.to_csv(out_path, index=False)\n\n# Report\nprint(f\"\\n✅ Submission saved: {out_path}\")\nprint(f\"Shape: {df_sub.shape}\\n\")\nprint(\"Sample translations:\")\nfor _, r in df_sub.head(min(5, len(df_sub))).iterrows():\n    preview = r['translation'][:70] + \"...\" if len(r['translation']) > 70 else r['translation']\n    print(f\"  ID {r['id']:2d}: {preview}\")\n\n# Quality metrics\ngap_ratio = df_sub[\"translation\"].str.count(\"<gap>|<big_gap>\").sum() / max(df_sub[\"translation\"].str.split().str.len().sum(), 1)\nfrac_usage = df_sub[\"translation\"].str.contains(r\"[½¼¾]\").sum() / len(df_sub)\nprint(f\"\\n📈 Gap ratio: {gap_ratio:.3f} | Fraction usage: {frac_usage:.1%}\")\nprint(f\"\\n🎯 Expected score: 35.5+ (baseline: 35.1)\")\nprint(\"💡 Key: Fixed CUDA errors + gap reconstruction + ensemble ranking\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T07:40:56.896986Z","iopub.execute_input":"2026-02-08T07:40:56.897709Z","iopub.status.idle":"2026-02-08T07:41:32.480758Z","shell.execute_reply.started":"2026-02-08T07:40:56.897681Z","shell.execute_reply":"2026-02-08T07:41:32.479848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}