{"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":14387266,"sourceType":"datasetVersion","datasetId":9188227},{"sourceId":258034511,"sourceType":"kernelVersion"},{"sourceId":289595309,"sourceType":"kernelVersion"},{"sourceId":289693199,"sourceType":"kernelVersion"}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip --version","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:00:14.801197Z","iopub.execute_input":"2026-01-02T16:00:14.801428Z","iopub.status.idle":"2026-01-02T16:00:15.358960Z","shell.execute_reply.started":"2026-01-02T16:00:14.801403Z","shell.execute_reply":"2026-01-02T16:00:15.358126Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"try:\n    import unsloth\nexcept Exception as e:\n    !pip uninstall -y torchvision\n    !pip uninstall -y torch\n    !pip install --no-index --find-links=/kaggle/input/unsloth-pip-python12/unsloth-wheels unsloth\n    !pip uninstall -y tensorflow","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:03:02.978087Z","iopub.execute_input":"2026-01-02T16:03:02.978658Z","iopub.status.idle":"2026-01-02T16:04:57.903150Z","shell.execute_reply.started":"2026-01-02T16:03:02.978624Z","shell.execute_reply":"2026-01-02T16:04:57.902456Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport torch\nimport json\nimport wandb\nimport pickle as pkl\nfrom datasets import Dataset, load_dataset, DatasetDict\nfrom sklearn.model_selection import train_test_split\nfrom unsloth import FastLanguageModel, PatchFastRL, is_bfloat16_supported\nimport re\nfrom tqdm.auto import tqdm\nfrom unsloth.chat_templates import get_chat_template","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:05:27.304220Z","iopub.execute_input":"2026-01-02T16:05:27.304736Z","iopub.status.idle":"2026-01-02T16:05:50.732031Z","shell.execute_reply.started":"2026-01-02T16:05:27.304691Z","shell.execute_reply":"2026-01-02T16:05:50.731284Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# In[2] Config\nBASE_MODEL_PATH = \"/kaggle/input/gemma-3-4b-it-bnb-4bit/gemma-3-4b-it-bnb-4bit\"\n# LORA_PATH = '/kaggle/input/deep-past-sft-gemma3-training/deep_past_gm3'  \nLORA_PATH = '/kaggle/input/dp25-gm3-lora'\n\nDATA_DIR = \"/kaggle/input/deep-past-initiative-machine-translation\"\nTRAIN_CSV = f\"{DATA_DIR}/train.csv\"\nTEST_CSV = f\"{DATA_DIR}/test.csv\"\n\nMAX_LENGTH = 1024\nLORA_RANK = 16\nGPU_MEM_UTIL = 0.7\n\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:13:21.213861Z","iopub.execute_input":"2026-01-02T16:13:21.214625Z","iopub.status.idle":"2026-01-02T16:13:21.218710Z","shell.execute_reply.started":"2026-01-02T16:13:21.214582Z","shell.execute_reply":"2026-01-02T16:13:21.218100Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# In[3] Load model + tokenizer\nmodel, tokenizer = FastLanguageModel.from_pretrained(\n    model_name=BASE_MODEL_PATH,\n    load_in_4bit=True,\n    max_lora_rank=LORA_RANK,\n    max_seq_length=MAX_LENGTH,\n    gpu_memory_utilization=GPU_MEM_UTIL,\n)\n\ntokenizer.padding_side = \"left\"\n\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Apply Gemma-3 chat template\ntokenizer = get_chat_template(tokenizer, chat_template=\"gemma-3\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:10:01.617913Z","iopub.execute_input":"2026-01-02T16:10:01.618578Z","iopub.status.idle":"2026-01-02T16:10:01.622881Z","shell.execute_reply.started":"2026-01-02T16:10:01.618544Z","shell.execute_reply":"2026-01-02T16:10:01.622236Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.load_adapter(LORA_PATH)\n\nFastLanguageModel.for_inference(model)\nmodel.config.use_cache = True\n# model.to(DEVICE)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:11:33.169153Z","iopub.execute_input":"2026-01-02T16:11:33.169961Z","iopub.status.idle":"2026-01-02T16:11:35.497286Z","shell.execute_reply.started":"2026-01-02T16:11:33.169927Z","shell.execute_reply":"2026-01-02T16:11:35.496706Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\n# In[4] Load train.csv and split (seed=42)\ntest_df = pd.read_csv(TEST_CSV)\n\nprint(f\"Test size : {len(test_df)}\")\n\n# test_df = test_df.sample(10)\ntest_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:13:34.901139Z","iopub.execute_input":"2026-01-02T16:13:34.901880Z","iopub.status.idle":"2026-01-02T16:13:34.916613Z","shell.execute_reply.started":"2026-01-02T16:13:34.901838Z","shell.execute_reply":"2026-01-02T16:13:34.915759Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# In[5] Prompt builder\ndef build_messages(source_text: str):\n    prompt = f\"\"\"\nAs an Akkadian translation expert, please translate the following text into English following functional equivalence principles:\n\nTranslation requirements:\n1. Accurately convey the semantic content of the original text\n2. Consider cultural adaptation (convert unfamiliar concepts to target-culture understandable concepts)\n3. Maintain natural and fluent language\n\nOriginal text: \"{source_text}\"\n\nPlease only provide the translation:\n\"\"\".strip()\n\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You are a professional Akkadian translation expert skilled in functional equivalence translation.\",\n        },\n        {\"role\": \"user\", \"content\": prompt},\n    ]\n\n# In[6] Decode helper\ndef extract_model_answer(decoded: str) -> str:\n    parts = decoded.split(\"<start_of_turn>model\")\n    if len(parts) >= 2:\n        ans = parts[-1]\n        ans = ans.replace(\"<end_of_turn>\", \"\").strip()\n        return ans\n    return decoded.strip()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:20:09.936809Z","iopub.execute_input":"2026-01-02T16:20:09.937401Z","iopub.status.idle":"2026-01-02T16:20:09.944146Z","shell.execute_reply.started":"2026-01-02T16:20:09.937360Z","shell.execute_reply":"2026-01-02T16:20:09.943390Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_tok = tokenizer.tokenizer\n\n@torch.inference_mode()\ndef translate_batch(\n    texts,\n    max_new_tokens=512,\n    temperature=0.7,\n    top_p=0.95,\n    top_k=64,\n    do_sample=False,\n):\n    chats = [\n        tokenizer.apply_chat_template(\n            build_messages(str(t)),\n            tokenize=False,\n            add_generation_prompt=True,\n        )\n        for t in texts\n    ]\n\n    inputs = base_tok(\n        chats,\n        return_tensors=\"pt\",\n        padding=True,\n        truncation=True,\n    ).to(DEVICE)\n\n    outputs = model.generate(\n        **inputs,\n        max_new_tokens=max_new_tokens,\n        temperature=temperature,\n        top_p=top_p,\n        top_k=top_k,\n        do_sample=do_sample,\n\n        # ✅ 正统 EOS\n        eos_token_id=base_tok.eos_token_id,\n        pad_token_id=base_tok.pad_token_id,\n    )\n\n    decoded = base_tok.batch_decode(outputs, skip_special_tokens=False)\n    return [\n        extract_model_answer(x).replace(\"\\n\", \" \").strip()\n        for x in decoded\n    ]\n\n# In[8] Run batch inference on split test set (fast)\nfrom tqdm.auto import tqdm\n\ndef run_inference_on_df(\n    df: pd.DataFrame,\n    text_col: str = \"transliteration\",\n    batch_size: int = 16,\n    **gen_kwargs,\n):\n    texts = df[text_col].astype(str).tolist()\n    preds = []\n\n    for i in tqdm(range(0, len(texts), batch_size)):\n        batch_texts = texts[i : i + batch_size]\n        batch_preds = translate_batch(batch_texts, **gen_kwargs)\n        preds.extend(batch_preds)\n\n    return preds\n\n\ntest_df[\"translation\"] = run_inference_on_df(\n    test_df,\n    batch_size=4,\n    max_new_tokens=512,\n    do_sample=False,\n)\n\ntest_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:24:05.985132Z","iopub.execute_input":"2026-01-02T16:24:05.985501Z","iopub.status.idle":"2026-01-02T16:24:20.267524Z","shell.execute_reply.started":"2026-01-02T16:24:05.985472Z","shell.execute_reply":"2026-01-02T16:24:20.266785Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df['translation'] = test_df['translation'].apply(lambda x: x.replace('<pad>', ''))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sub = test_df[['id', 'translation']]\nsub.to_csv(\"submission.csv\", index=False)\nsub","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T16:25:39.995761Z","iopub.execute_input":"2026-01-02T16:25:39.996396Z","iopub.status.idle":"2026-01-02T16:25:40.011926Z","shell.execute_reply.started":"2026-01-02T16:25:39.996367Z","shell.execute_reply":"2026-01-02T16:25:40.011354Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}