{"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":[{"sourceType":"competition","sourceId":121150,"databundleVersionId":15833391,"isSourceIdPinned":false},{"sourceType":"datasetVersion","sourceId":15270248,"datasetId":9743961,"databundleVersionId":16170166,"isSourceIdPinned":true}],"dockerImageVersionId":31287,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"default_parameters":{},"duration":27.056951,"end_time":"2026-03-18T09:48:35.729189","environment_variables":{},"exception":true,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2026-03-18T09:48:08.672238","version":"2.6.0"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"06a91820b06a442b83a5ee12ae355a61":{"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_98e79a4903d94a68b7f4a007034874f7","placeholder":"​","style":"IPY_MODEL_4918647a18db4ea18c52c01fe47eafb1","tabbable":null,"tooltip":null,"value":" 4/4 [00:25&lt;00:00,  7.17s/it]"}},"0e313a503729477f854541b2d863adb1":{"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":""}},"1c492154309a46d7b1de88e13d1292c1":{"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_22edf20acbb2479fa2c7e1290ee55a94","max":498,"min":0,"orientation":"horizontal","style":"IPY_MODEL_0e313a503729477f854541b2d863adb1","tabbable":null,"tooltip":null,"value":498}},"22edf20acbb2479fa2c7e1290ee55a94":{"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}},"252a46cd68fd4514aac94117b31ebcab":{"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_c6881257f50f4204afc7b10a14df4d57","placeholder":"​","style":"IPY_MODEL_f7f6b0d011f740ec92d2cff53e9093f8","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"275fd5dea3be4f308509cbf1f9c570ea":{"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":""}},"2784333579354a11a4cbff73a76b7898":{"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_252a46cd68fd4514aac94117b31ebcab","IPY_MODEL_1c492154309a46d7b1de88e13d1292c1","IPY_MODEL_592d336642464cd58a16ee92908d4be9"],"layout":"IPY_MODEL_b26e0e9632f44e589e30e66b2c8c92d5","tabbable":null,"tooltip":null}},"2f9f0bf15a1b46b8ab8bb491e82f4044":{"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}},"3819ebeb0e9641da82b369f4d2bd627a":{"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}},"44ed8bccf1e8463886f5b347448af818":{"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}},"4918647a18db4ea18c52c01fe47eafb1":{"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}},"57c62a902c464862a92ed97dd985371b":{"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_6dec1c04b5dd4df685d7b8a94bf61732","IPY_MODEL_8838e57e8cc445fb9022b6d95b6a0904","IPY_MODEL_06a91820b06a442b83a5ee12ae355a61"],"layout":"IPY_MODEL_44ed8bccf1e8463886f5b347448af818","tabbable":null,"tooltip":null}},"592d336642464cd58a16ee92908d4be9":{"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_3819ebeb0e9641da82b369f4d2bd627a","placeholder":"​","style":"IPY_MODEL_5dbce8e1a37349c3bde6e227bb5709e5","tabbable":null,"tooltip":null,"value":" 498/498 [00:07&lt;00:00, 65.04it/s, Materializing param=shared.weight]"}},"5dbce8e1a37349c3bde6e227bb5709e5":{"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}},"65edce3770364abeb56041b6be12e5a8":{"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}},"6dec1c04b5dd4df685d7b8a94bf61732":{"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_2f9f0bf15a1b46b8ab8bb491e82f4044","placeholder":"​","style":"IPY_MODEL_65edce3770364abeb56041b6be12e5a8","tabbable":null,"tooltip":null,"value":"Translating: 100%"}},"8838e57e8cc445fb9022b6d95b6a0904":{"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_e578f01b0e8647cd87d977a92724d8d7","max":4,"min":0,"orientation":"horizontal","style":"IPY_MODEL_275fd5dea3be4f308509cbf1f9c570ea","tabbable":null,"tooltip":null,"value":4}},"98e79a4903d94a68b7f4a007034874f7":{"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}},"b26e0e9632f44e589e30e66b2c8c92d5":{"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}},"c6881257f50f4204afc7b10a14df4d57":{"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}},"e578f01b0e8647cd87d977a92724d8d7":{"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}},"f7f6b0d011f740ec92d2cff53e9093f8":{"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}}},"version_major":2,"version_minor":0}}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## 1️⃣ System-Level Optimization\n\nSet optimal environment variables **before** importing PyTorch.","metadata":{"papermill":{"duration":0.006982,"end_time":"2026-03-18T09:48:11.237784","exception":false,"start_time":"2026-03-18T09:48:11.230802","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import os\n\n# Optimize PyTorch/CUDA performance\nos.environ['OMP_NUM_THREADS'] = '4'\nos.environ['MKL_NUM_THREADS'] = '4'\nos.environ['CUDA_LAUNCH_BLOCKING'] = '0'\nos.environ['TORCH_CUDNN_V8_API_ENABLED'] = '1'\nos.environ['TOKENIZERS_PARALLELISM'] = 'true'\n\nprint(\"Environment variables optimized\")","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:11.250695Z","iopub.status.busy":"2026-03-18T09:48:11.250444Z","iopub.status.idle":"2026-03-18T09:48:11.258733Z","shell.execute_reply":"2026-03-18T09:48:11.258065Z"},"papermill":{"duration":0.016498,"end_time":"2026-03-18T09:48:11.260246","exception":false,"start_time":"2026-03-18T09:48:11.243748","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 2️⃣ Imports & Setup","metadata":{"papermill":{"duration":0.005801,"end_time":"2026-03-18T09:48:11.272208","exception":false,"start_time":"2026-03-18T09:48:11.266407","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import re\nimport logging\nimport warnings\nfrom pathlib import Path\nfrom typing import Dict, List, Tuple, Optional\nfrom dataclasses import dataclass\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\nimport copy\nimport pandas as pd\nimport numpy as np\nimport torch\nfrom torch.utils.data import Dataset, DataLoader, Sampler\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom tqdm.auto import tqdm\nimport json\nimport random\n\nwarnings.filterwarnings('ignore')\n\n# Check GPUs\nprint(f\"PyTorch version: {torch.__version__}\")\nprint(f\"CUDA available: {torch.cuda.is_available()}\")\nprint(f\"bf16 supported: {torch.cuda.is_available() and torch.cuda.is_bf16_supported()}\")\nif torch.cuda.is_available():\n    n_gpus = torch.cuda.device_count()\n    print(f\"GPUs available: {n_gpus}\")\n    for i in range(n_gpus):\n        print(f\"  GPU {i}: {torch.cuda.get_device_name(i)} \"\n              f\"({torch.cuda.get_device_properties(i).total_memory / 1e9:.1f} GB)\")","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:11.284495Z","iopub.status.busy":"2026-03-18T09:48:11.284170Z","iopub.status.idle":"2026-03-18T09:48:32.241085Z","shell.execute_reply":"2026-03-18T09:48:32.240121Z"},"papermill":{"duration":20.964897,"end_time":"2026-03-18T09:48:32.242705","exception":false,"start_time":"2026-03-18T09:48:11.277808","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 3️⃣ Configuration\n\n**📝 EDIT THESE PATHS:**","metadata":{"papermill":{"duration":0.005733,"end_time":"2026-03-18T09:48:32.254587","exception":false,"start_time":"2026-03-18T09:48:32.248854","status":"completed"},"tags":[]}},{"cell_type":"code","source":"@dataclass\nclass UltraConfig:\n    \"\"\"Ultra-optimized configuration\"\"\"\n    \n    # ============ PATHS - EDIT THESE ============\n    test_data_path: str = \"/kaggle/input/competitions/deep-past-initiative-machine-translation/test.csv\"\n    model_path: str = \"/kaggle/input/byt5-large-v18-lora-akkadian\"\n    output_dir: str = \"/kaggle/working/\"\n    \n    # ============ PROCESSING ============\n    max_length: int = 1024       # Must match training max_source_len (byte-level!)\n    batch_size: int = 8          # Per-GPU batch size\n    num_workers: int = 4\n    \n    # ============ GENERATION ============\n    num_beams: int = 8           # More beams for diverse beam candidates\n    num_beam_candidates: int = 4 # Return top-4 from beam search\n    max_new_tokens: int = 1024   # ByT5 byte-level needs 1024 for full translations\n    length_penalty: float = 1.0  # lp=1.0 optimal (validated)\n    repetition_penalty: float = 1.2  # Prevents degenerate repetition loops\n    early_stopping: bool = True\n    no_repeat_ngram_size: int = 0\n    \n    # ============ MBR CONFIG ============\n    use_mbr: bool = True\n    mbr_sample_temperatures: tuple = (0.6, 0.8, 1.05)  # 3 temperatures\n    mbr_samples_per_temp: int = 2                        # 2 samples each = 6 stochastic\n    mbr_sample_top_p: float = 0.92\n    mbr_agreement_bonus: float = 0.035  # Bonus for inter-candidate agreement\n    \n    # ============ OPTIMIZATIONS ============\n    use_mixed_precision: bool = True   # Uses bf16 (mandatory for ByT5!)\n    use_better_transformer: bool = True\n    use_bucket_batching: bool = True\n    use_vectorized_postproc: bool = True\n    use_adaptive_beams: bool = False\n    use_auto_batch_size: bool = True\n    \n    # ============ OTHER ============\n    aggressive_postprocessing: bool = True  # Enable postprocessing fixes\n    checkpoint_freq: int = 100\n    num_buckets: int = 4\n    \n    def __post_init__(self):\n        self.num_gpus = torch.cuda.device_count() if torch.cuda.is_available() else 0\n        self.devices = [torch.device(f\"cuda:{i}\") for i in range(self.num_gpus)] if self.num_gpus > 0 else [torch.device(\"cpu\")]\n        self.device = self.devices[0]  # Primary device\n        Path(self.output_dir).mkdir(exist_ok=True, parents=True)\n        \n        if not torch.cuda.is_available():\n            self.use_mixed_precision = False\n            self.use_better_transformer = False\n        \n        self.total_mbr_candidates = self.num_beam_candidates + len(self.mbr_sample_temperatures) * self.mbr_samples_per_temp\n\nconfig = UltraConfig()\n\nprint(\"\\nConfiguration:\")\nprint(f\"  GPUs: {config.num_gpus} ({', '.join(str(d) for d in config.devices)})\")\nprint(f\"  Batch size: {config.batch_size} per GPU ({config.batch_size * max(1, config.num_gpus)} effective)\")\nprint(f\"  Beams: {config.num_beams} (returning top {config.num_beam_candidates})\")\nprint(f\"  Length penalty: {config.length_penalty}\")\nprint(f\"  Repetition penalty: {config.repetition_penalty}\")\nprint(f\"  Max new tokens: {config.max_new_tokens}\")\nprint(f\"\\nMBR:\")\nprint(f\"  Enabled: {config.use_mbr}\")\nprint(f\"  Beam candidates: {config.num_beam_candidates}\")\nprint(f\"  Sample temps: {config.mbr_sample_temperatures} x {config.mbr_samples_per_temp} = {len(config.mbr_sample_temperatures) * config.mbr_samples_per_temp}\")\nprint(f\"  Total candidates: {config.total_mbr_candidates}\")\nprint(f\"  Agreement bonus: {config.mbr_agreement_bonus}\")\nprint(f\"\\nOptimizations:\")\nprint(f\"  Mixed Precision (bf16): {config.use_mixed_precision}\")\nprint(f\"  BetterTransformer: {config.use_better_transformer}\")\nprint(f\"  Bucket Batching: {config.use_bucket_batching}\")\nprint(f\"  Postprocessing: {config.aggressive_postprocessing}\")","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.267455Z","iopub.status.busy":"2026-03-18T09:48:32.266985Z","iopub.status.idle":"2026-03-18T09:48:32.280837Z","shell.execute_reply":"2026-03-18T09:48:32.279985Z"},"papermill":{"duration":0.021791,"end_time":"2026-03-18T09:48:32.282150","exception":false,"start_time":"2026-03-18T09:48:32.260359","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 4️⃣ Logging Setup","metadata":{"papermill":{"duration":0.005814,"end_time":"2026-03-18T09:48:32.293945","exception":false,"start_time":"2026-03-18T09:48:32.288131","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def setup_logging(output_dir: str = './outputs'):\n    \"\"\"Setup logging\"\"\"\n    Path(output_dir).mkdir(exist_ok=True, parents=True)\n    log_file = Path(output_dir) / 'inference_ultra.log'\n    \n    for handler in logging.root.handlers[:]:\n        logging.root.removeHandler(handler)\n    \n    logging.basicConfig(\n        level=logging.INFO,\n        format='%(asctime)s - %(levelname)s - %(message)s',\n        handlers=[\n            logging.StreamHandler(),\n            logging.FileHandler(log_file)\n        ]\n    )\n    return logging.getLogger(__name__)\n\nlogger = setup_logging(config.output_dir)\nlogger.info(\"Logging initialized\")","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.306618Z","iopub.status.busy":"2026-03-18T09:48:32.306400Z","iopub.status.idle":"2026-03-18T09:48:32.313199Z","shell.execute_reply":"2026-03-18T09:48:32.312249Z"},"papermill":{"duration":0.015091,"end_time":"2026-03-18T09:48:32.314793","exception":false,"start_time":"2026-03-18T09:48:32.299702","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 5️⃣ V9 Normalization Preprocessor\n\n**CRITICAL**: The V9 model was trained on normalized transliterations.\nThe same `normalize_transliteration()` must be applied to test input at inference time.\nThis replaces the old preprocessor that incorrectly converted test format → old training format.","metadata":{"papermill":{"duration":0.005869,"end_time":"2026-03-18T09:48:32.326561","exception":false,"start_time":"2026-03-18T09:48:32.320692","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def normalize_transliteration(text):\n    \"\"\"V9 normalization — MUST match the training preprocessing exactly.\n    Source: /kaggle/working/deep-past-data/create_v9.py\n    \"\"\"\n    if not text or (isinstance(text, float) and pd.isna(text)):\n        return \"\"\n    text = str(text)\n    # Ḫ → H, ḫ → h (test uses H/h, train was normalized to match)\n    text = text.replace('\\u1e2a', 'H').replace('\\u1e2b', 'h')\n    # Subscript digits → plain digits\n    sub_map = str.maketrans(\n        '\\u2080\\u2081\\u2082\\u2083\\u2084\\u2085\\u2086\\u2087\\u2088\\u2089\\u2093',\n        '0123456789x')\n    text = text.translate(sub_map)\n    # {det} → (det) — handle malformed braces like {d)\n    text = re.sub(r'\\{([^})\\]]+)[})\\]]', r'(\\1)', text)\n    text = text.replace('{', '(').replace('}', ')')\n    # Remove ! and ? markers\n    text = text.replace('!', '').replace('?', '')\n    # Remove half-brackets ⸢⸣⸤⸥\n    for ch in '\\u2e22\\u2e23\\u2e24\\u2e25':\n        text = text.replace(ch, '')\n    # Remove square brackets (keep content)\n    text = text.replace('[', '').replace(']', '')\n    # Gap markers\n    text = text.replace('<big_gap>', '\\u2026')\n    text = text.replace('<gap>', 'x')\n    # Remove remaining angle-bracket tags (keep content)\n    text = re.sub(r'<([^>]*)>', r'\\1', text)\n    # Normalize whitespace\n    text = re.sub(r'\\s+', ' ', text).strip()\n    return text\n\n\nclass OptimizedPreprocessor:\n    \"\"\"Preprocessor using V9 normalization\"\"\"\n    \n    def preprocess_input_text(self, text: str) -> str:\n        return normalize_transliteration(text)\n    \n    def preprocess_batch(self, texts: List[str]) -> List[str]:\n        return [normalize_transliteration(t) for t in texts]\n\n# Test with actual test data format\npreprocessor = OptimizedPreprocessor()\ntest_cases = [\n    \"um-ma kà-ru-um kà-ni-ia-ma a-na aa-qí-il… da-tí-a\",\n    \"i-na mup-pì-im aa a-lim(ki) ia-tù u„-mì-im\",\n    \"KIŠIB {d}EN.LÍL ša₂ KÙ.BABBAR\",\n    \"lugal ... xxx [mu].2.kam\",\n]\nprint(\"V9 Normalization test:\")\nfor t in test_cases:\n    print(f\"  {t}\")\n    print(f\"  → {preprocessor.preprocess_input_text(t)}\")\n    print()","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.339889Z","iopub.status.busy":"2026-03-18T09:48:32.339673Z","iopub.status.idle":"2026-03-18T09:48:32.347506Z","shell.execute_reply":"2026-03-18T09:48:32.346808Z"},"papermill":{"duration":0.016115,"end_time":"2026-03-18T09:48:32.349110","exception":false,"start_time":"2026-03-18T09:48:32.332995","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 6️⃣ Postprocessor\n\nRegex-based corrections from top LB notebooks:\n- Fraction normalization (0.3333 → ⅓, shekel fractions)\n- Commodity expansion (-gold → pašallum gold)\n- Gap/PN handling\n- Repetition removal (word and phrase level)\n- Grammar marker removal\n- Month normalization\n- ḫ/Ḫ → h/H in output","metadata":{"papermill":{"duration":0.005919,"end_time":"2026-03-18T09:48:32.361453","exception":false,"start_time":"2026-03-18T09:48:32.355534","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import math\n\n# ── Gap unification ──\n_GAP_UNIFIED_RE = re.compile(\n    r\"<\\s*big[\\s_\\-]*gap\\s*>\"\n    r\"|<\\s*gap\\s*>\"\n    r\"|\\bbig[\\s_\\-]*gap\\b\"\n    r\"|\\bx(?:\\s+x)+\\b\"\n    r\"|\\.{3,}|…+|\\[\\.+\\]\"\n    r\"|\\[\\s*x\\s*\\]|\\(\\s*x\\s*\\)\"\n    r\"|(?<!\\w)x{2,}(?!\\w)\"\n    r\"|(?<!\\w)x(?!\\w)\"\n    r\"|\\(\\s*large\\s+break\\s*\\)\"\n    r\"|\\(\\s*break\\s*\\)\"\n    r\"|\\(\\s*\\d+\\s+broken\\s+lines?\\s*\\)\",\n    re.I\n)\n\ndef _normalize_gaps_vec(ser: pd.Series) -> pd.Series:\n    return ser.str.replace(_GAP_UNIFIED_RE, \"<gap>\", regex=True)\n\n# ── Fraction normalization ──\n_EXACT_FRAC_RE = re.compile(r\"0\\.8333|0\\.6666|0\\.3333|0\\.1666|0\\.625|0\\.75|0\\.25|0\\.5\")\n_EXACT_FRAC_MAP = {\n    \"0.8333\": \"\\u215a\", \"0.6666\": \"\\u2154\", \"0.3333\": \"\\u2153\", \"0.1666\": \"\\u2159\",\n    \"0.625\": \"\\u215d\", \"0.75\": \"\\u00be\", \"0.25\": \"\\u00bc\", \"0.5\": \"\\u00bd\",\n}\n\ndef _frac_repl(m: re.Match) -> str:\n    return _EXACT_FRAC_MAP[m.group(0)]\n\n_ALLOWED_FRACS = [\n    (1/6, \"0.16666\"), (1/4, \"0.25\"), (1/3, \"0.33333\"),\n    (1/2, \"0.5\"), (2/3, \"0.66666\"), (3/4, \"0.75\"), (5/6, \"0.83333\"),\n]\n_FRAC_TOL = 2e-3\n_FLOAT_RE = re.compile(r\"(?<![\\w/])(\\d+\\.\\d{4,})(?![\\w/])\")\n\ndef _canon_decimal(x: float) -> str:\n    ip = int(math.floor(x + 1e-12))\n    frac = x - ip\n    best = min(_ALLOWED_FRACS, key=lambda t: abs(frac - t[0]))\n    if abs(frac - best[0]) <= _FRAC_TOL:\n        dec = best[1]\n        if ip == 0:\n            return dec\n        return f\"{ip}{dec[1:]}\" if dec.startswith(\"0.\") else f\"{ip}+{dec}\"\n    return f\"{x:.5f}\".rstrip(\"0\").rstrip(\".\")\n\n# ── Shekel fractions ──\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), '\\u2153 shekel 15 grains'),\n    (re.compile(r'7\\s*/\\s*12\\s+shekels?', re.I), '\\u00bd shekel 15 grains'),\n    (re.compile(r'1\\s*/\\s*12\\s*(?:\\(shekel\\)|\\bshekel)?', re.I), '15 grains'),\n]\n\n# ── Commodity expansion (only space-prefixed hyphens) ──\n_COMMODITY_RE = re.compile(r'(?<=\\s)-(gold|tax|textiles)\\b')\n_COMMODITY_REPL = {\"gold\": \"pasallum gold\", \"tax\": \"sadduatum tax\", \"textiles\": \"kutanum textiles\"}\n\ndef _commodity_repl(m: re.Match) -> str:\n    return _COMMODITY_REPL[m.group(1)]\n\n# ── Grammar markers ──\n_SOFT_GRAM_RE = re.compile(\n    r\"\\(\\s*(?:fem|plur|pl|sing|singular|plural|\\?|\\!)\"\n    r\"(?:\\.\\s*(?:plur|plural|sing|singular))?\"\n    r\"\\.?\\s*[^)]*\\)\", re.I\n)\n_BARE_GRAM_RE = re.compile(r\"(?<!\\w)(?:fem|sing|pl|plural)\\.?(?!\\w)\\s*\", re.I)\n_UNCERTAIN_RE = re.compile(r\"\\(\\?\\)\")\n\n# ── Month normalization ──\n_MONTH_RE = re.compile(r\"\\bMonth\\s+(XII|XI|X|IX|VIII|VII|VI|V|IV|III|II|I)\\b\", re.I)\n_ROMAN2INT = {\"I\":1,\"II\":2,\"III\":3,\"IV\":4,\"V\":5,\"VI\":6,\"VII\":7,\"VIII\":8,\"IX\":9,\"X\":10,\"XI\":11,\"XII\":12}\n\ndef _month_repl(m: re.Match) -> str:\n    return f\"Month {_ROMAN2INT.get(m.group(1).upper(), m.group(1))}\"\n\n# ── Quotes ──\n_CURLY_DQ_RE = re.compile(\"[\\u201c\\u201d]\")\n_CURLY_SQ_RE = re.compile(\"[\\u2018\\u2019]\")\n\n# ── Repetition removal ──\n_REPEAT_WORD_RE = re.compile(r\"\\b(\\w+)(?:\\s+\\1\\b)+\")\n_REPEAT_PUNCT_RE = re.compile(r\"([.,])\\1+\")\n_PUNCT_SPACE_RE = re.compile(r\"\\s+([.,:])\")\n\n# ── PN handling ──\n_PN_RE = re.compile(r\"\\bPN\\b\")\n\n# ── Stray marks ──\n_STRAY_MARKS_RE = re.compile(r'<<[^>]*>>|<(?!gap\\b)[^>]*>')\n_EXTRA_STRAY_RE = re.compile(r'(?<!\\w)(?:\\.\\.+|xx+)(?!\\w)')\n_MULTI_GAP_RE = re.compile(r'(?:<gap>\\s*){2,}')\n\n# ── Slash alternatives (protect fractions) ──\n_SLASH_ALT_RE = re.compile(r'(?<![0-9/])\\s+/\\s+(?![0-9])\\S+')\n\n# ── Forbidden chars (preserve parentheses per host) ──\n_FORBIDDEN_TRANS = str.maketrans(\"\", \"\", '\\u2014\\u2014<>\\u2308\\u230b\\u230a[]+\\u02be;')\n\n# ── h/H normalization ──\n_HACEK_TRANS = str.maketrans({\"\\u1e2b\": \"h\", \"\\u1e2a\": \"H\"})\n\n_WS_RE = re.compile(r\"\\s+\")\n\n\nclass VectorizedPostprocessor:\n    \"\"\"Full postprocessor with regex corrections from top LB notebooks\"\"\"\n    \n    def __init__(self, aggressive: bool = False):\n        self.aggressive = aggressive\n    \n    def postprocess_batch(self, translations: List[str]) -> List[str]:\n        s = pd.Series(translations).fillna(\"\").astype(str)\n        \n        if self.aggressive:\n            # Gap unification\n            s = _normalize_gaps_vec(s)\n            s = s.str.replace(_PN_RE, \"<gap>\", regex=True)\n            \n            # Commodity expansion\n            s = s.str.replace(_COMMODITY_RE, _commodity_repl, regex=True)\n            \n            # Shekel fractions\n            for pat, repl in _SHEKEL_REPLS:\n                s = s.str.replace(pat, repl, regex=True)\n            \n            # Fraction normalization\n            s = s.str.replace(_EXACT_FRAC_RE, _frac_repl, regex=True)\n            s = s.str.replace(_FLOAT_RE, lambda m: _canon_decimal(float(m.group(1))), regex=True)\n            \n            # Grammar markers\n            s = s.str.replace(_SOFT_GRAM_RE, \" \", regex=True)\n            s = s.str.replace(_BARE_GRAM_RE, \" \", regex=True)\n            s = s.str.replace(_UNCERTAIN_RE, \"\", regex=True)\n            \n            # Stray marks\n            s = s.str.replace(_STRAY_MARKS_RE, \"\", regex=True)\n            s = s.str.replace(_EXTRA_STRAY_RE, \"\", regex=True)\n            s = s.str.replace(_SLASH_ALT_RE, \"\", regex=True)\n            \n            # Curly quotes -> straight\n            s = s.str.replace(_CURLY_DQ_RE, '\"', regex=True)\n            s = s.str.replace(_CURLY_SQ_RE, \"'\", regex=True)\n            \n            # Month normalization\n            s = s.str.replace(_MONTH_RE, _month_repl, regex=True)\n            s = s.str.replace(_MULTI_GAP_RE, \"<gap>\", regex=True)\n            \n            # Protect <gap> markers before stripping forbidden chars\n            s = s.str.replace(\"<gap>\", \"\\x00GAP\\x00\", regex=False)\n            s = s.str.translate(_FORBIDDEN_TRANS)\n            s = s.str.replace(\"\\x00GAP\\x00\", \" <gap> \", regex=False)\n            \n            # h/H normalization\n            s = s.str.translate(_HACEK_TRANS)\n            \n            # Repetition removal (word level)\n            s = s.str.replace(_REPEAT_WORD_RE, r\"\\1\", regex=True)\n            # Repetition removal (phrase level, 4-gram down to 2-gram)\n            for n in range(4, 1, -1):\n                pat = r\"\\b((?:\\w+\\s+){\" + str(n-1) + r\"}\\w+)(?:\\s+\\1\\b)+\"\n                s = s.str.replace(pat, r\"\\1\", regex=True)\n            \n            # Punctuation cleanup\n            s = s.str.replace(_PUNCT_SPACE_RE, r\"\\1\", regex=True)\n            s = s.str.replace(_REPEAT_PUNCT_RE, r\"\\1\", regex=True)\n        \n        # Always: normalize whitespace\n        s = s.str.replace(_WS_RE, \" \", regex=True).str.strip()\n        \n        return s.tolist()\n\n# Test\npostprocessor = VectorizedPostprocessor(aggressive=config.aggressive_postprocessing)\ntest_outputs = [\n    \"The king king king took the city.\",\n    \"He paid 0.3333 minas of silver.\",\n    \"5/12 shekel of gold.\",\n    \"Month IV of the year.\",\n    \"The tablet of \\u1e2babrum son of PN.\",\n    \"  Multiple   spaces   here  \",\n]\ncleaned = postprocessor.postprocess_batch(test_outputs)\nprint(\"Postprocessing test:\")\nfor orig, clean in zip(test_outputs, cleaned):\n    print(f\"  {repr(orig)}\")\n    print(f\"  -> {repr(clean)}\")\n    print()","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.374609Z","iopub.status.busy":"2026-03-18T09:48:32.374363Z","iopub.status.idle":"2026-03-18T09:48:32.403980Z","shell.execute_reply":"2026-03-18T09:48:32.403022Z"},"papermill":{"duration":0.038252,"end_time":"2026-03-18T09:48:32.405462","exception":false,"start_time":"2026-03-18T09:48:32.367210","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 6b. MBR (Minimum Bayes Risk) Reranking\n\nGenerate multiple candidates per sample (beam + stochastic sampling), then select the one\nwith highest consensus score using the competition metric `sqrt(BLEU * chrF++)`.","metadata":{"papermill":{"duration":0.005966,"end_time":"2026-03-18T09:48:32.417715","exception":false,"start_time":"2026-03-18T09:48:32.411749","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import sacrebleu\n\ndef mbr_score_pair(hypothesis: str, reference: str) -> float:\n    \"\"\"Compute competition metric between two candidates: sqrt(BLEU * chrF++)\"\"\"\n    # sentence-level BLEU and chrF++\n    bleu = sacrebleu.sentence_bleu(hypothesis, [reference]).score\n    chrf = sacrebleu.sentence_chrf(hypothesis, [reference], word_order=2).score\n    return math.sqrt(max(bleu, 0) * max(chrf, 0))\n\n\ndef mbr_select(candidates: List[str], agreement_bonus: float = 0.035) -> Tuple[str, float, List[float]]:\n    \"\"\"Select best candidate via MBR with agreement bonus.\n    \n    For each candidate, compute average score against all OTHER candidates.\n    The candidate with highest average score is the MBR winner — it's the\n    translation that all other candidates \"agree with\" most.\n    \n    agreement_bonus: extra weight for candidates that appear multiple times\n    (exact or near-exact duplicates get a boost).\n    \"\"\"\n    n = len(candidates)\n    if n == 0:\n        return \"\", 0.0, []\n    if n == 1:\n        return candidates[0], 0.0, [0.0]\n    \n    # Deduplicate and count for agreement bonus\n    from collections import Counter\n    norm_candidates = [c.strip().lower() for c in candidates]\n    counts = Counter(norm_candidates)\n    \n    # Pairwise score matrix (only upper triangle needed)\n    scores = np.zeros((n, n))\n    for i in range(n):\n        for j in range(i + 1, n):\n            s = mbr_score_pair(candidates[i], candidates[j])\n            scores[i][j] = s\n            scores[j][i] = s\n    \n    # Average score for each candidate (against all others)\n    mbr_scores = []\n    for i in range(n):\n        avg = scores[i].sum() / (n - 1)\n        # Agreement bonus: if this candidate's normalized form appears multiple times\n        dup_count = counts[norm_candidates[i]]\n        bonus = agreement_bonus * (dup_count - 1) if dup_count > 1 else 0\n        mbr_scores.append(avg + bonus)\n    \n    best_idx = int(np.argmax(mbr_scores))\n    return candidates[best_idx], mbr_scores[best_idx], mbr_scores\n\n\n# Test MBR\ntest_candidates = [\n    \"Thus says the colony of Kanesh to our envoys.\",\n    \"Thus says the Kanesh colony to our envoys.\",\n    \"Thus speaks the colony of Kanesh to our envoys.\",\n    \"Thus says the Kanesh colony to our envoys.\",  # duplicate\n    \"The colony of Kanesh says thus to our messengers.\",\n]\nwinner, score, all_scores = mbr_select(test_candidates, agreement_bonus=0.035)\nprint(\"MBR test:\")\nfor i, (c, s) in enumerate(zip(test_candidates, all_scores)):\n    marker = \" <-- WINNER\" if c == winner else \"\"\n    print(f\"  [{s:.2f}] {c}{marker}\")\nprint(f\"\\nBest: {winner} (score={score:.2f})\")","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.430945Z","iopub.status.busy":"2026-03-18T09:48:32.430480Z","iopub.status.idle":"2026-03-18T09:48:32.526154Z","shell.execute_reply":"2026-03-18T09:48:32.525163Z"},"papermill":{"duration":0.10438,"end_time":"2026-03-18T09:48:32.527916","exception":false,"start_time":"2026-03-18T09:48:32.423536","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 7️⃣ Bucket Batch Sampler\n\nGroups samples by length to minimize padding → **20-40% faster**.","metadata":{"papermill":{"duration":0.006053,"end_time":"2026-03-18T09:48:32.540533","exception":false,"start_time":"2026-03-18T09:48:32.534480","status":"completed"},"tags":[]}},{"cell_type":"code","source":"class BucketBatchSampler(Sampler):\n    \"\"\"Batch samples by similar length to minimize padding\"\"\"\n    \n    def __init__(self, dataset, batch_size: int, num_buckets: int = 4, shuffle: bool = False):\n        self.dataset = dataset\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        \n        # Calculate lengths\n        lengths = [len(text.split()) for _, text in dataset]\n        \n        # Sort indices by length\n        sorted_indices = sorted(range(len(lengths)), key=lambda i: lengths[i])\n        \n        # Create buckets\n        bucket_size = len(sorted_indices) // num_buckets\n        self.buckets = []\n        for i in range(num_buckets):\n            start = i * bucket_size\n            end = None if i == num_buckets - 1 else (i + 1) * bucket_size\n            self.buckets.append(sorted_indices[start:end])\n        \n        # Log bucket info\n        logger.info(f\"Created {num_buckets} buckets:\")\n        for i, bucket in enumerate(self.buckets):\n            bucket_lengths = [lengths[idx] for idx in bucket]\n            logger.info(f\"  Bucket {i}: {len(bucket)} samples, \"\n                       f\"length range [{min(bucket_lengths)}, {max(bucket_lengths)}]\")\n    \n    def __iter__(self):\n        for bucket in self.buckets:\n            if self.shuffle:\n                random.shuffle(bucket)\n            \n            for i in range(0, len(bucket), self.batch_size):\n                yield bucket[i:i+self.batch_size]\n    \n    def __len__(self):\n        return sum((len(b) + self.batch_size - 1) // self.batch_size for b in self.buckets)","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.554604Z","iopub.status.busy":"2026-03-18T09:48:32.553574Z","iopub.status.idle":"2026-03-18T09:48:32.561654Z","shell.execute_reply":"2026-03-18T09:48:32.560855Z"},"papermill":{"duration":0.016609,"end_time":"2026-03-18T09:48:32.563160","exception":false,"start_time":"2026-03-18T09:48:32.546551","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 8️⃣ Dataset Class","metadata":{"papermill":{"duration":0.005885,"end_time":"2026-03-18T09:48:32.575265","exception":false,"start_time":"2026-03-18T09:48:32.569380","status":"completed"},"tags":[]}},{"cell_type":"code","source":"class AkkadianDataset(Dataset):\n    \"\"\"Optimized dataset with batch preprocessing\"\"\"\n    \n    def __init__(self, dataframe: pd.DataFrame, preprocessor: OptimizedPreprocessor):\n        self.sample_ids = dataframe['id'].tolist()\n        \n        # Batch preprocess (faster than loop)\n        raw_texts = dataframe['transliteration'].tolist()\n        preprocessed = preprocessor.preprocess_batch(raw_texts)\n        \n        # Add task prefix\n        self.input_texts = [\n            \"translate Akkadian to English: \" + text\n            for text in preprocessed\n        ]\n        \n        logger.info(f\"Dataset created with {len(self.sample_ids)} samples\")\n    \n    def __len__(self):\n        return len(self.sample_ids)\n    \n    def __getitem__(self, index: int):\n        return self.sample_ids[index], self.input_texts[index]","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.588183Z","iopub.status.busy":"2026-03-18T09:48:32.587972Z","iopub.status.idle":"2026-03-18T09:48:32.593695Z","shell.execute_reply":"2026-03-18T09:48:32.592911Z"},"papermill":{"duration":0.014025,"end_time":"2026-03-18T09:48:32.595145","exception":false,"start_time":"2026-03-18T09:48:32.581120","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 9️⃣ Ultra-Optimized Inference Engine\n\nMain inference engine with all optimizations.","metadata":{"papermill":{"duration":0.005884,"end_time":"2026-03-18T09:48:32.607311","exception":false,"start_time":"2026-03-18T09:48:32.601427","status":"completed"},"tags":[]}},{"cell_type":"code","source":"class UltraInferenceEngine:\n    \"\"\"Ultra-optimized inference engine with multi-GPU support and MBR reranking\"\"\"\n    \n    def __init__(self, config: UltraConfig):\n        self.config = config\n        self.preprocessor = OptimizedPreprocessor()\n        self.postprocessor = VectorizedPostprocessor(aggressive=config.aggressive_postprocessing)\n        self.results = []\n        \n        # Load model(s) — one per GPU\n        self._load_models()\n    \n    def _resolve_model_path(self, path):\n        \"\"\"Resolve model path for newer transformers that reject local paths with many slashes.\n        Returns (resolved_path, load_kwargs) where load_kwargs forces local loading if needed.\"\"\"\n        p = Path(path)\n        # Check if it's clearly a local path (starts with / or ./)\n        if not path.startswith((\"/\", \"./\", \"../\")):\n            return path, {}\n        \n        # It's a local path — resolve it and check for config.json\n        resolved = str(p.resolve())\n        if p.exists() and p.is_dir():\n            # Path exists as directory — use resolved absolute path\n            return resolved, {\"local_files_only\": True}\n        \n        # Path doesn't exist yet or isn't a dir — might be Kaggle mount timing issue\n        # Try to find config.json to verify\n        config_file = p / \"config.json\"\n        if config_file.exists():\n            return resolved, {\"local_files_only\": True}\n        \n        # Last resort: still pass local_files_only to prevent hub validation\n        logger.warning(f\"Path {path} does not appear to exist as directory, attempting anyway\")\n        return resolved, {\"local_files_only\": True}\n    \n    def _load_models(self):\n        \"\"\"Load model on each available GPU in bf16\"\"\"\n        logger.info(f\"Loading model from {self.config.model_path}\")\n        \n        model_path, load_kwargs = self._resolve_model_path(self.config.model_path)\n        is_local = bool(load_kwargs)\n        logger.info(f\"Resolved path: {model_path} (local={is_local})\")\n        \n        self.tokenizer = AutoTokenizer.from_pretrained(model_path, **load_kwargs)\n        \n        # Load in bf16 — ByT5 REQUIRES bf16 (fp16 causes NaN overflow!)\n        model = AutoModelForSeq2SeqLM.from_pretrained(\n            model_path,\n            torch_dtype=torch.bfloat16,\n            **load_kwargs\n        )\n        num_params = sum(p.numel() for p in model.parameters())\n        logger.info(f\"Model loaded: {num_params:,} parameters (bf16)\")\n        \n        self.models = []\n        for i, device in enumerate(self.config.devices):\n            if i == 0:\n                m = model.to(device).eval()\n            else:\n                logger.info(f\"Copying model to {device}...\")\n                m = copy.deepcopy(model).to(device).eval()\n            \n            if self.config.use_better_transformer and device.type == \"cuda\":\n                try:\n                    from optimum.bettertransformer import BetterTransformer\n                    m = BetterTransformer.transform(m)\n                    logger.info(f\"  BetterTransformer applied on {device}\")\n                except (ImportError, Exception) as e:\n                    logger.warning(f\"  BetterTransformer failed on {device}: {e}\")\n            \n            self.models.append(m)\n        \n        logger.info(f\"Models ready on {len(self.models)} device(s): \"\n                    f\"{[str(d) for d in self.config.devices]}\")\n        \n        if len(self.models) > 1:\n            del model\n            torch.cuda.empty_cache()\n    \n    def _collate_fn(self, batch_samples):\n        \"\"\"Collate function\"\"\"\n        batch_ids = [s[0] for s in batch_samples]\n        batch_texts = [s[1] for s in batch_samples]\n        \n        tokenized = self.tokenizer(\n            batch_texts,\n            max_length=self.config.max_length,\n            padding=True,\n            truncation=True,\n            return_tensors=\"pt\"\n        )\n        \n        return batch_ids, tokenized\n    \n    def find_optimal_batch_size(self, dataset, start_bs: int = 32):\n        \"\"\"Binary search for optimal batch size (on primary GPU)\"\"\"\n        logger.info(\"Finding optimal batch size...\")\n        \n        max_bs = start_bs\n        min_bs = 1\n        \n        while max_bs - min_bs > 1:\n            test_bs = (max_bs + min_bs) // 2\n            \n            try:\n                test_batch = [dataset[i] for i in range(min(test_bs, len(dataset)))]\n                ids, inputs = self._collate_fn(test_batch)\n                \n                with torch.inference_mode():\n                    with torch.amp.autocast(\"cuda\", dtype=torch.bfloat16):\n                        outputs = self.models[0].generate(\n                            input_ids=inputs.input_ids.to(self.config.device),\n                            attention_mask=inputs.attention_mask.to(self.config.device),\n                            num_beams=self.config.num_beams,\n                            max_new_tokens=64,\n                            use_cache=True\n                        )\n                \n                min_bs = test_bs\n                logger.info(f\"  Batch size {test_bs} works\")\n                \n                del outputs, inputs\n                torch.cuda.empty_cache()\n                \n            except RuntimeError as e:\n                if \"out of memory\" in str(e):\n                    max_bs = test_bs\n                    logger.info(f\"  Batch size {test_bs} OOM\")\n                    torch.cuda.empty_cache()\n                else:\n                    raise\n        \n        optimal = min_bs\n        logger.info(f\"Optimal batch size per GPU: {optimal}\")\n        return optimal\n    \n    def _generate_on_device(self, gpu_idx, input_ids, attention_mask, gen_config):\n        \"\"\"Run generation on a specific GPU. Returns list of strings.\"\"\"\n        device = self.config.devices[gpu_idx]\n        model = self.models[gpu_idx]\n        \n        ids_dev = input_ids.to(device)\n        mask_dev = attention_mask.to(device)\n        \n        with torch.inference_mode():\n            with torch.amp.autocast(\"cuda\", dtype=torch.bfloat16):\n                outputs = model.generate(\n                    input_ids=ids_dev,\n                    attention_mask=mask_dev,\n                    **gen_config\n                )\n        \n        return self.tokenizer.batch_decode(outputs.cpu(), skip_special_tokens=True)\n    \n    def _generate_beam_candidates(self, gpu_idx, input_ids, attention_mask):\n        \"\"\"Generate beam search candidates. Returns num_beam_candidates per input.\"\"\"\n        gen_config = {\n            \"max_new_tokens\": self.config.max_new_tokens,\n            \"num_beams\": self.config.num_beams,\n            \"num_return_sequences\": self.config.num_beam_candidates,\n            \"length_penalty\": self.config.length_penalty,\n            \"early_stopping\": self.config.early_stopping,\n            \"use_cache\": True,\n        }\n        if self.config.repetition_penalty != 1.0:\n            gen_config[\"repetition_penalty\"] = self.config.repetition_penalty\n        \n        return self._generate_on_device(gpu_idx, input_ids, attention_mask, gen_config)\n    \n    def _generate_sample_candidates(self, gpu_idx, input_ids, attention_mask, temperature, num_samples):\n        \"\"\"Generate stochastic sample candidates at given temperature.\"\"\"\n        gen_config = {\n            \"max_new_tokens\": self.config.max_new_tokens,\n            \"do_sample\": True,\n            \"temperature\": temperature,\n            \"top_p\": self.config.mbr_sample_top_p,\n            \"num_return_sequences\": num_samples,\n            \"use_cache\": True,\n        }\n        if self.config.repetition_penalty != 1.0:\n            gen_config[\"repetition_penalty\"] = self.config.repetition_penalty\n        \n        return self._generate_on_device(gpu_idx, input_ids, attention_mask, gen_config)\n    \n    def _save_checkpoint(self):\n        \"\"\"Save checkpoint\"\"\"\n        if len(self.results) > 0 and len(self.results) % self.config.checkpoint_freq == 0:\n            path = Path(self.config.output_dir) / f\"checkpoint_{len(self.results)}.csv\"\n            df = pd.DataFrame(self.results, columns=['id', 'translation'])\n            df.to_csv(path, index=False)\n            logger.info(f\"Checkpoint: {len(self.results)} translations\")\n    \n    def run_inference(self, test_df: pd.DataFrame) -> pd.DataFrame:\n        \"\"\"Run inference with MBR reranking across all GPUs\"\"\"\n        n_gpus = len(self.models)\n        use_mbr = self.config.use_mbr\n        logger.info(f\"Starting inference on {n_gpus} GPU(s), MBR={'ON' if use_mbr else 'OFF'}\")\n        \n        dataset = AkkadianDataset(test_df, self.preprocessor)\n        \n        if self.config.use_auto_batch_size:\n            optimal_bs = self.find_optimal_batch_size(dataset)\n            if use_mbr:\n                mbr_factor = max(1, self.config.num_beam_candidates)\n                adjusted_bs = max(1, optimal_bs // mbr_factor)\n                logger.info(f\"  MBR adjusted batch size: {optimal_bs} -> {adjusted_bs} \"\n                           f\"(x{mbr_factor} return sequences)\")\n                optimal_bs = adjusted_bs\n            self.config.batch_size = optimal_bs\n        \n        effective_batch_size = self.config.batch_size * n_gpus\n        \n        if self.config.use_bucket_batching:\n            batch_sampler = BucketBatchSampler(\n                dataset, effective_batch_size,\n                num_buckets=self.config.num_buckets\n            )\n            dataloader = DataLoader(\n                dataset,\n                batch_sampler=batch_sampler,\n                num_workers=self.config.num_workers,\n                collate_fn=self._collate_fn,\n                pin_memory=True,\n                prefetch_factor=2,\n                persistent_workers=True if self.config.num_workers > 0 else False\n            )\n        else:\n            dataloader = DataLoader(\n                dataset,\n                batch_size=effective_batch_size,\n                shuffle=False,\n                num_workers=self.config.num_workers,\n                collate_fn=self._collate_fn,\n                pin_memory=True,\n                prefetch_factor=2,\n                persistent_workers=True if self.config.num_workers > 0 else False\n            )\n        \n        logger.info(f\"DataLoader: {len(dataloader)} batches, \"\n                    f\"batch_size={effective_batch_size} ({self.config.batch_size}/GPU x {n_gpus} GPUs)\")\n        \n        self.results = []\n        all_candidates_log = {}\n        \n        with torch.inference_mode():\n            for batch_idx, (batch_ids, tokenized) in enumerate(tqdm(dataloader, desc=\"Translating\")):\n                try:\n                    input_ids = tokenized.input_ids\n                    attention_mask = tokenized.attention_mask\n                    bs = input_ids.size(0)\n                    \n                    if not use_mbr:\n                        gen_config = {\n                            \"max_new_tokens\": self.config.max_new_tokens,\n                            \"num_beams\": self.config.num_beams,\n                            \"length_penalty\": self.config.length_penalty,\n                            \"early_stopping\": self.config.early_stopping,\n                            \"use_cache\": True,\n                        }\n                        if self.config.repetition_penalty != 1.0:\n                            gen_config[\"repetition_penalty\"] = self.config.repetition_penalty\n                        \n                        if n_gpus > 1:\n                            chunk_size = (bs + n_gpus - 1) // n_gpus\n                            id_chunks = [batch_ids[i:i+chunk_size] for i in range(0, bs, chunk_size)]\n                            input_chunks = list(input_ids.split(chunk_size))\n                            mask_chunks = list(attention_mask.split(chunk_size))\n                            \n                            all_translations = [None] * len(input_chunks)\n                            all_ids_out = [None] * len(input_chunks)\n                            \n                            with ThreadPoolExecutor(max_workers=n_gpus) as executor:\n                                futures = {}\n                                for gpu_idx, (id_chunk, inp_chunk, mask_chunk) in enumerate(\n                                    zip(id_chunks, input_chunks, mask_chunks)\n                                ):\n                                    future = executor.submit(\n                                        self._generate_on_device,\n                                        gpu_idx, inp_chunk, mask_chunk, gen_config\n                                    )\n                                    futures[future] = gpu_idx\n                                \n                                for future in as_completed(futures):\n                                    gpu_idx = futures[future]\n                                    all_translations[gpu_idx] = future.result()\n                                    all_ids_out[gpu_idx] = id_chunks[gpu_idx]\n                            \n                            flat_ids = [i for chunk in all_ids_out if chunk for i in chunk]\n                            flat_trans = [t for chunk in all_translations if chunk for t in chunk]\n                        else:\n                            flat_trans = self._generate_on_device(\n                                0, input_ids, attention_mask, gen_config\n                            )\n                            flat_ids = batch_ids\n                        \n                        cleaned = self.postprocessor.postprocess_batch(flat_trans)\n                        self.results.extend(zip(flat_ids, cleaned))\n                    \n                    else:\n                        for sample_idx in range(bs):\n                            sample_id = batch_ids[sample_idx]\n                            sample_input = input_ids[sample_idx:sample_idx+1]\n                            sample_mask = attention_mask[sample_idx:sample_idx+1]\n                            \n                            gpu_idx = 0\n                            candidates = []\n                            \n                            beam_outputs = self._generate_beam_candidates(\n                                gpu_idx, sample_input, sample_mask\n                            )\n                            candidates.extend(beam_outputs)\n                            \n                            for temp in self.config.mbr_sample_temperatures:\n                                sample_outputs = self._generate_sample_candidates(\n                                    gpu_idx, sample_input, sample_mask,\n                                    temperature=temp,\n                                    num_samples=self.config.mbr_samples_per_temp\n                                )\n                                candidates.extend(sample_outputs)\n                            \n                            candidates = self.postprocessor.postprocess_batch(candidates)\n                            candidates = [c for c in candidates if c.strip()]\n                            if not candidates:\n                                candidates = [\"\"]\n                            \n                            winner, score, all_scores = mbr_select(\n                                candidates,\n                                agreement_bonus=self.config.mbr_agreement_bonus\n                            )\n                            \n                            self.results.append((sample_id, winner))\n                            all_candidates_log[sample_id] = {\n                                \"candidates\": candidates,\n                                \"scores\": [float(s) for s in all_scores],\n                                \"winner\": winner,\n                                \"winner_score\": float(score),\n                            }\n                            \n                            logger.info(f\"  Sample {sample_id}: {len(candidates)} candidates, \"\n                                       f\"MBR score={score:.2f}\")\n                    \n                    self._save_checkpoint()\n                    \n                    if torch.cuda.is_available() and batch_idx % 10 == 0:\n                        for i in range(n_gpus):\n                            torch.cuda.empty_cache()\n                    \n                except Exception as e:\n                    logger.error(f\"Batch {batch_idx} error: {e}\")\n                    import traceback\n                    traceback.print_exc()\n                    self.results.extend([(bid, \"\") for bid in batch_ids])\n                    continue\n        \n        logger.info(\"Inference completed\")\n        \n        if use_mbr and all_candidates_log:\n            log_path = Path(self.config.output_dir) / \"mbr_candidates.json\"\n            with open(log_path, \"w\") as f:\n                json.dump(all_candidates_log, f, indent=2, ensure_ascii=False)\n            logger.info(f\"MBR candidates log saved to {log_path}\")\n        \n        results_df = pd.DataFrame(self.results, columns=['id', 'translation'])\n        self._validate_results(results_df)\n        \n        return results_df\n    \n    def _validate_results(self, df: pd.DataFrame):\n        \"\"\"Validation report\"\"\"\n        print(\"\\n\" + \"=\"*60)\n        print(\"VALIDATION REPORT\")\n        print(\"=\"*60)\n        \n        empty = df['translation'].str.strip().eq('').sum()\n        print(f\"\\nEmpty: {empty} ({empty/len(df)*100:.2f}%)\")\n        \n        lengths = df['translation'].str.len()\n        print(f\"\\nLength stats:\")\n        print(f\"   Mean: {lengths.mean():.1f}, Median: {lengths.median():.1f}\")\n        print(f\"   Min: {lengths.min()}, Max: {lengths.max()}\")\n        \n        short = ((lengths < 5) & (lengths > 0)).sum()\n        if short > 0:\n            print(f\"   {short} very short translations\")\n        \n        print(f\"\\nSample translations:\")\n        for idx in [0, len(df)//2, -1]:\n            s = df.iloc[idx]\n            preview = s['translation'][:70] + \"...\" if len(s['translation']) > 70 else s['translation']\n            print(f\"   ID {s['id']:4d}: {preview}\")\n        \n        print(\"\\n\" + \"=\"*60 + \"\\n\")\n\nprint(\"Inference engine defined (with MBR)\")","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.620885Z","iopub.status.busy":"2026-03-18T09:48:32.620667Z","iopub.status.idle":"2026-03-18T09:48:32.657046Z","shell.execute_reply":"2026-03-18T09:48:32.656328Z"},"papermill":{"duration":0.045316,"end_time":"2026-03-18T09:48:32.658522","exception":false,"start_time":"2026-03-18T09:48:32.613206","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 🔟 Load Test Data","metadata":{"papermill":{"duration":0.006203,"end_time":"2026-03-18T09:48:32.670904","exception":false,"start_time":"2026-03-18T09:48:32.664701","status":"completed"},"tags":[]}},{"cell_type":"code","source":"logger.info(f\"Loading test data from {config.test_data_path}\")\n\ntest_df = pd.read_csv(config.test_data_path, encoding='utf-8')\nlogger.info(f\"✅ Loaded {len(test_df)} test samples\")\n\nprint(\"\\nFirst 5 samples:\")\nprint(test_df.head())","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.684434Z","iopub.status.busy":"2026-03-18T09:48:32.684157Z","iopub.status.idle":"2026-03-18T09:48:32.710618Z","shell.execute_reply":"2026-03-18T09:48:32.709579Z"},"papermill":{"duration":0.035145,"end_time":"2026-03-18T09:48:32.712537","exception":false,"start_time":"2026-03-18T09:48:32.677392","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 1️⃣1️⃣ Run Ultra-Optimized Inference\n\n**This is the main cell - all optimizations are active!**","metadata":{"papermill":{"duration":0.007265,"end_time":"2026-03-18T09:48:32.726969","exception":false,"start_time":"2026-03-18T09:48:32.719704","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Create engine\nengine = UltraInferenceEngine(config)\n\n# Run inference\nresults_df = engine.run_inference(test_df)","metadata":{"execution":{"iopub.execute_input":"2026-03-18T09:48:32.742024Z","iopub.status.busy":"2026-03-18T09:48:32.741550Z","iopub.status.idle":"2026-03-18T09:48:32.761573Z","shell.execute_reply":"2026-03-18T09:48:32.760156Z"},"papermill":{"duration":0.029,"end_time":"2026-03-18T09:48:32.762913","exception":true,"start_time":"2026-03-18T09:48:32.733913","status":"failed"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 1️⃣2️⃣ Save Results","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[]}},{"cell_type":"code","source":"# Save submission\noutput_path = Path(config.output_dir) / 'submission.csv'\nresults_df.to_csv(output_path, index=False)\nlogger.info(f\"\\nSubmission saved to {output_path}\")\n\n# Save config\nconfig_dict = {\n    \"batch_size\": config.batch_size,\n    \"num_beams\": config.num_beams,\n    \"num_beam_candidates\": config.num_beam_candidates,\n    \"length_penalty\": config.length_penalty,\n    \"repetition_penalty\": config.repetition_penalty,\n    \"max_new_tokens\": config.max_new_tokens,\n    \"no_repeat_ngram_size\": config.no_repeat_ngram_size,\n    \"postprocessing\": config.aggressive_postprocessing,\n    \"mbr\": {\n        \"enabled\": config.use_mbr,\n        \"sample_temperatures\": list(config.mbr_sample_temperatures),\n        \"samples_per_temp\": config.mbr_samples_per_temp,\n        \"sample_top_p\": config.mbr_sample_top_p,\n        \"agreement_bonus\": config.mbr_agreement_bonus,\n        \"total_candidates\": config.total_mbr_candidates,\n    },\n    \"optimizations\": {\n        \"mixed_precision\": config.use_mixed_precision,\n        \"better_transformer\": config.use_better_transformer,\n        \"bucket_batching\": config.use_bucket_batching,\n    }\n}\n\nconfig_path = Path(config.output_dir) / 'ultra_config.json'\nwith open(config_path, 'w') as f:\n    json.dump(config_dict, f, indent=2)\n\nprint(\"\\n\" + \"=\"*60)\nprint(\"INFERENCE COMPLETE\")\nprint(\"=\"*60)\nprint(f\"Submission file: {output_path}\")\nprint(f\"Config file: {config_path}\")\nprint(f\"Total translations: {len(results_df)}\")\nprint(f\"Beams: {config.num_beams} -> {config.num_beam_candidates} candidates, LP: {config.length_penalty}, RepPen: {config.repetition_penalty}\")\nprint(f\"MBR: {'ON' if config.use_mbr else 'OFF'} ({config.total_mbr_candidates} candidates/sample)\")\nprint(f\"Postprocessing: {config.aggressive_postprocessing}\")\nprint(\"=\"*60)","metadata":{"execution":{"iopub.execute_input":"2026-03-18T07:55:14.945555Z","iopub.status.busy":"2026-03-18T07:55:14.945094Z","iopub.status.idle":"2026-03-18T07:55:14.962545Z","shell.execute_reply":"2026-03-18T07:55:14.961693Z"},"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 1️⃣3️⃣ [Optional] Inspect Results","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[]}},{"cell_type":"code","source":"# Load submission\nsubmission = pd.read_csv(output_path)\n\nprint(f\"Submission shape: {submission.shape}\")\nprint(f\"\\nFirst 10 translations:\")\nprint(submission.head(10))\n\nprint(f\"\\nLast 10 translations:\")\nprint(submission.tail(10))\n\n# Statistics\nlengths = submission['translation'].str.len()\nprint(f\"\\nLength distribution:\")\nprint(lengths.describe())\n\n# Check for issues\nempty = submission['translation'].str.strip().eq('').sum()\nprint(f\"\\nEmpty translations: {empty}\")\n\nif empty > 0:\n    print(\"\\nEmpty translation IDs:\")\n    print(submission[submission['translation'].str.strip().eq('')]['id'].tolist())","metadata":{"execution":{"iopub.execute_input":"2026-03-18T07:55:14.995371Z","iopub.status.busy":"2026-03-18T07:55:14.994824Z","iopub.status.idle":"2026-03-18T07:55:15.012531Z","shell.execute_reply":"2026-03-18T07:55:15.011213Z"},"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[]},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[]},"outputs":[],"execution_count":null}]}