{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":121150,"databundleVersionId":15061024,"sourceType":"competition"},{"sourceId":14271477,"sourceType":"datasetVersion","datasetId":9107673}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport torch\nfrom transformers import AutoModelForCausalLM, AutoTokenizer\nfrom tqdm import tqdm\nimport re\nimport os\n\n# ตั้งค่า GPU\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\nMODEL_PATH = \"/kaggle/input/qwen-akkadian-translator-sft/qwen_akkadian_translator_sft_merged\"\nTEST_DATA_PATH = \"/kaggle/input/deep-past-initiative-machine-translation/test.csv\"\nOUTPUT_CSV_PATH = \"submission.csv\"\n\nINPUT_COL_NAME = \"transliteration\"\nID_COL_NAME = \"id\"\n\ndef clean_akkadian(text):\n    if not isinstance(text, str): return \"\"\n    subscript_map = {\n        \"₀\": \"0\", \"₁\": \"1\", \"₂\": \"2\", \"₃\": \"3\", \"₄\": \"4\",\n        \"₅\": \"5\", \"₆\": \"6\", \"₇\": \"7\", \"₈\": \"8\", \"₉\": \"9\",\n        \"ₓ\": \"x\"\n    }\n    translation_table = str.maketrans(subscript_map)\n    text = text.translate(translation_table)\n    text = re.sub(r'\\[x\\]', '<gap>', text)\n    text = re.sub(r'\\[?\\.{3,}\\]?', '<big_gap>', text)\n    text = re.sub(r'\\[\\s*\\.\\.\\.\\s*\\]', '<big_gap>', text)\n    text = re.sub(r'\\[([^\\]]+)\\]', r'\\1', text)\n    for char in ['!', '?', '/', ':', '˹', '˺']:\n        text = text.replace(char, '')\n    text = text.replace('<<', '').replace('>>', '')\n    text = re.sub(r'\\s+', ' ', text).strip()\n    return text\n\nalpaca_prompt = \"\"\"Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.\n\n### Instruction:\nTranslate the following Akkadian text into English.\n\n### Input:\n{}\n\n### Response:\n\"\"\"\n\nprint(f\"📂 Loading Test Data from {TEST_DATA_PATH}...\")\ndf_test = pd.read_csv(TEST_DATA_PATH)\n\nif INPUT_COL_NAME not in df_test.columns:\n    raise ValueError(f\"❌ Column '{INPUT_COL_NAME}' not found in csv! Found: {df_test.columns}\")\n\nprint(\"🧹 Cleaning Inputs...\")\ninputs = df_test[INPUT_COL_NAME].apply(clean_akkadian).tolist()\n\nprompts = [alpaca_prompt.format(text) for text in inputs]\n\nprint(f\"⏳ Loading Hugging Face Model from {MODEL_PATH}...\")\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)\ntokenizer.padding_side = \"left\"\nif tokenizer.pad_token is None:\n    tokenizer.pad_token = tokenizer.eos_token\n\nmodel = AutoModelForCausalLM.from_pretrained(\n    MODEL_PATH,\n    device_map=\"auto\",\n    torch_dtype=torch.float16,\n    trust_remote_code=True\n)\nmodel.eval()\n\nprint(f\"🚀 Running Inference on {len(inputs)} samples...\")\n\nBATCH_SIZE = 8\ngenerated_translations = []\n\nfor i in tqdm(range(0, len(prompts), BATCH_SIZE)):\n    batch_prompts = prompts[i:i + BATCH_SIZE]\n    \n    model_inputs = tokenizer(batch_prompts, return_tensors=\"pt\", padding=True, truncation=True, max_length=2048).to(device)\n    \n    with torch.no_grad():\n        generated_ids = model.generate(\n            **model_inputs,\n            max_new_tokens=1024,\n            do_sample=False,\n            pad_token_id=tokenizer.pad_token_id,\n            eos_token_id=tokenizer.eos_token_id\n        )\n    \n    input_length = model_inputs.input_ids.shape[1]\n    new_tokens = generated_ids[:, input_length:]\n    \n    batch_outputs = tokenizer.batch_decode(new_tokens, skip_special_tokens=True)\n    batch_outputs = [out.strip() for out in batch_outputs]\n    generated_translations.extend(batch_outputs)\n\nprint(\"💾 Saving Results...\")\n\n# สร้าง DataFrame สำหรับ submission\nsubmission_df = pd.DataFrame({\n    ID_COL_NAME: df_test[ID_COL_NAME],\n    'translation': generated_translations\n})\n\n# เลือกเฉพาะคอลัมน์ที่ต้องการ (กันพลาด)\nsubmission_df = submission_df[[ID_COL_NAME, 'translation']]\n\nsubmission_df.to_csv(OUTPUT_CSV_PATH, index=False)\nprint(f\"✅ Saved to '{OUTPUT_CSV_PATH}' with columns: {list(submission_df.columns)}\")\n\nprint(\"\\n👀 Preview:\")\nprint(submission_df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T17:40:53.403106Z","iopub.execute_input":"2025-12-24T17:40:53.403722Z","iopub.status.idle":"2025-12-24T17:43:20.159216Z","shell.execute_reply.started":"2025-12-24T17:40:53.403691Z","shell.execute_reply":"2025-12-24T17:43:20.158556Z"}},"outputs":[],"execution_count":null}]}