{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":121150,"databundleVersionId":15833391,"isSourceIdPinned":false}],"dockerImageVersionId":31286,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport pandas as pd\nimport torch\nfrom torch.utils.data import DataLoader, Dataset\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom tqdm.auto import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-03-02T11:30:19.404669Z","iopub.execute_input":"2026-03-02T11:30:19.405053Z","iopub.status.idle":"2026-03-02T11:30:43.952426Z","shell.execute_reply.started":"2026-03-02T11:30:19.405021Z","shell.execute_reply":"2026-03-02T11:30:43.951312Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#MODEL_PATH = \"/kaggle/input/dpc-starter-train/byt5-akkadian-model/\"\n#MODEL_PATH = \"/kaggle/input/epoch30-seed42/byt5-akkadian-model\"\nMODEL_PATH=\"/kaggle/input/k/qifeihhh666/dpc-starter-train/byt5-akkadian-model/\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-02T11:30:19.390068Z","iopub.execute_input":"2026-03-02T11:30:19.390661Z","iopub.status.idle":"2026-03-02T11:30:19.402632Z","shell.execute_reply.started":"2026-03-02T11:30:19.390578Z","shell.execute_reply":"2026-03-02T11:30:19.40131Z"}},"outputs":[],"execution_count":null},{"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":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def find_optimal_batch_size(self, dataset, start_bs: int = 32):\n    \"\"\"Binary search for optimal batch size\"\"\"\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            input_ids = inputs.input_ids.to(self.config.device)\n            attention_mask = inputs.attention_mask.to(self.config.device)\n\n            with torch.inference_mode():\n                if self.config.use_mixed_precision:\n                    with autocast():\n                        _ = self.model.generate(\n                            input_ids=input_ids,\n                            attention_mask=attention_mask,\n                            num_beams=1,  # 🔑 keep minimal for memory test\n                            max_new_tokens=8,\n                            use_cache=True\n                        )\n                else:\n                    _ = self.model.generate(\n                        input_ids=input_ids,\n                        attention_mask=attention_mask,\n                        num_beams=1,\n                        max_new_tokens=8,\n                        use_cache=True\n                    )\n\n            min_bs = test_bs\n            logger.info(f\"  ✅ Batch size {test_bs} works\")\n\n            del inputs\n            if torch.cuda.is_available():\n                torch.cuda.empty_cache()\n\n        except RuntimeError as e:\n            if \"out of memory\" in str(e).lower():\n                max_bs = test_bs\n                logger.info(f\"  ❌ Batch size {test_bs} OOM\")\n                if torch.cuda.is_available():\n                    torch.cuda.empty_cache()\n            else:\n                raise\n\n    optimal = min_bs\n    logger.info(f\"🎯 Optimal batch size: {optimal}\")\n    return optimal","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"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":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":" Create engine\nengine = UltraInferenceEngine(config)\n\n# Run inference\nresults_df = engine.run_inference(test_df)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Sort results for safety\nresults_df = results_df.sort_values(\"id\").reset_index(drop=True)\n\n# ---------- Atomic Submission Save ----------\noutput_path = Path(config.output_dir) / 'submission.csv'\ntemp_path = output_path.with_suffix(\".tmp\")\nresults_df.to_csv(temp_path, index=False)\ntemp_path.replace(output_path)\n\nlogger.info(f\"\\n✅ Submission saved to {output_path}\")\n\n# ---------- Save FULL Config ----------\nconfig_dict = {\n    k: str(v) if not isinstance(v,(int,float,bool,str,list,dict)) else v\n    for k,v in vars(config).items()\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\n# ---------- Save Run Stats ----------\nstats = {\n    \"num_samples\": len(results_df),\n    \"empty_ratio\": (results_df['translation'].str.strip() == \"\").mean(),\n    \"avg_length\": results_df['translation'].str.len().mean()\n}\n\nstats_path = Path(config.output_dir) / 'run_stats.json'\nwith open(stats_path, 'w') as f:\n    json.dump(stats, f, indent=2)\n\n# ---------- Submission Hash ----------\nimport hashlib\n\ndef file_hash(path):\n    with open(path,'rb') as f:\n        return hashlib.md5(f.read()).hexdigest()\n\nsubmission_hash = file_hash(output_path)\n\n# ---------- Final Report ----------\nprint(\"\\n\" + \"=\"*60)\nprint(\"🎉 ULTRA-OPTIMIZED INFERENCE COMPLETE!\")\nprint(\"=\"*60)\nprint(f\"Submission file : {output_path}\")\nprint(f\"Config file     : {config_path}\")\nprint(f\"Stats file      : {stats_path}\")\nprint(f\"Log file        : {Path(config.output_dir) / 'inference_ultra.log'}\")\nprint(f\"Total samples   : {len(results_df)}\")\nprint(f\"Submission hash : {submission_hash}\")\nprint(\"=\"*60)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"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":{"trusted":true},"outputs":[],"execution_count":null}]}