{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# IncidentCommander RL — Kaggle shard 1 / 3\n", "\n", "**Workload:** every 3rd task starting at index **0** (~127 of 381 scenarios).\n", "Trains a LoRA on **Phi-3.5-mini-instruct** using a local **DeepSeek-R1-0528-Qwen3-8B** critic.\n", "\n", "## REQUIRED — attach these 2 Kaggle Models before running\n", "Right sidebar → `+ Add Input` → `Models` tab:\n", "1. `Microsoft / phi-3` → framework `PyTorch` → variation `phi-3.5-mini-instruct` → version `2`\n", "2. `deepseek-ai / deepseek-r1-0528` → framework `Transformers` → variation `deepseek-r1-0528-qwen3-8b` → version `1`\n", "\n", "## Required notebook settings\n", "- Accelerator: `GPU T4 x2` or `GPU P100`\n", "- Internet: `On`\n", "- Persistence: `Files only`\n", "\n", "**Output:** `/kaggle/working/adapter_kaggle1.zip` — download from the sidebar after the run finishes." ] }, { "cell_type": "code", "execution_count": null, "id": "1c28582e", "metadata": {}, "outputs": [], "source": [ "# === 1. Install deps + unsloth (best-effort) ===\n", "# Qwen3 (in DeepSeek-R1-0528) needs transformers >= 4.51. Unsloth speeds up\n", "# the actor ~2x; if its install fails on this Kaggle image we fall back to\n", "# pure HF transformers automatically (train_lib.py handles both paths).\n", "import subprocess, sys\n", "\n", "def pip(*args):\n", " return subprocess.run([sys.executable, '-m', 'pip', 'install', '-q', *args],\n", " check=False).returncode\n", "\n", "rc = pip('-U', 'unsloth')\n", "print('[install] unsloth rc =', rc, '(non-zero is fine, HF fallback works)')\n", "\n", "pip('-U',\n", " 'transformers>=4.51,<4.55',\n", " 'peft>=0.13,<0.16',\n", " 'accelerate>=1.1,<1.5',\n", " 'bitsandbytes>=0.45.5',\n", " 'huggingface_hub>=0.25,<1.0',\n", " 'pydantic>=2,<3',\n", " 'datasets', 'sentencepiece', 'protobuf', 'safetensors')\n", "print('[install] pinned stack done')" ] }, { "cell_type": "code", "execution_count": null, "id": "37a868c2", "metadata": {}, "outputs": [], "source": [ "# === 2. GPU sanity ===\n", "import subprocess\n", "print('--- GPU ---')\n", "subprocess.run(['nvidia-smi', '-L'], check=False)\n", "import torch\n", "print('CUDA OK?', torch.cuda.is_available(),\n", " '| device:', torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'none')" ] }, { "cell_type": "code", "execution_count": null, "id": "fa14ea90", "metadata": {}, "outputs": [], "source": [ "# === 3. Verify attached Kaggle Models + suppress warning spam ===\n", "import os, pathlib, shutil, warnings, logging\n", "\n", "ACTOR_PATH = '/kaggle/input/models/Microsoft/phi-3/pytorch/phi-3.5-mini-instruct/2'\n", "CRITIC_PATH = '/kaggle/input/models/deepseek-ai/deepseek-r1-0528/transformers/deepseek-r1-0528-qwen3-8b/1'\n", "\n", "def verify(path, label):\n", " p = pathlib.Path(path)\n", " if not p.exists():\n", " raise SystemExit(f'{label} not found at {path}. Attach the matching Kaggle Model.')\n", " if not (any(p.glob('*.safetensors')) or any(p.glob('*.bin'))):\n", " raise SystemExit(f'{label} found at {path} but no weight files inside.')\n", " print(f'{label}: OK -> {path}')\n", "\n", "verify(ACTOR_PATH, 'actor (Phi-3.5-mini-instruct)')\n", "verify(CRITIC_PATH, 'critic (DeepSeek-R1-0528-Qwen3-8B)')\n", "\n", "os.environ['HF_HOME'] = '/tmp/hf-cache'\n", "os.environ['HUGGINGFACE_HUB_CACHE'] = '/tmp/hf-cache'\n", "os.environ['TRANSFORMERS_CACHE'] = '/tmp/hf-cache'\n", "pathlib.Path('/tmp/hf-cache').mkdir(parents=True, exist_ok=True)\n", "\n", "modules_dir = pathlib.Path('/tmp/hf-cache/modules')\n", "if modules_dir.exists():\n", " shutil.rmtree(modules_dir, ignore_errors=True)\n", " print('cleared cached custom modeling code at', modules_dir)\n", "\n", "try:\n", " from kaggle_secrets import UserSecretsClient\n", " os.environ['HF_TOKEN'] = UserSecretsClient().get_secret('HF_TOKEN')\n", " print('HF_TOKEN attached from Kaggle Secrets')\n", "except Exception:\n", " print('No HF_TOKEN -- training runs fully offline (that is fine).')\n", "\n", "for pat in ('.*Caching is incompatible with gradient checkpointing.*',\n", " '.*None of the inputs have requires_grad=True.*',\n", " '.*use_reentrant parameter should be passed explicitly.*',\n", " \".*AccumulateGrad node's stream does not match.*\"):\n", " warnings.filterwarnings('ignore', message=pat)\n", "\n", "class _PhiFilter(logging.Filter):\n", " def filter(self, r):\n", " return 'Caching is incompatible' not in r.getMessage()\n", "for n in ('transformers', 'transformers.models.phi3.modeling_phi3',\n", " 'torch.utils.checkpoint'):\n", " logging.getLogger(n).addFilter(_PhiFilter())\n", "print('warning filters installed')" ] }, { "cell_type": "code", "execution_count": null, "id": "b83c7a39", "metadata": {}, "outputs": [], "source": [ "# === 4. Clone the repo (fresh every run, prints commit hash) ===\n", "import os, subprocess, pathlib, shutil\n", "WORK = '/kaggle/working/incident-commander'\n", "os.chdir('/kaggle/working')\n", "if pathlib.Path(WORK).exists():\n", " shutil.rmtree(WORK, ignore_errors=True)\n", "subprocess.run(['git', 'clone', '--depth', '1',\n", " 'https://github.com/r1cksync/meta-rl-hack.git', WORK],\n", " check=True)\n", "os.chdir(WORK)\n", "subprocess.run(['git', '-C', WORK, 'log', '-1', '--oneline'], check=False)\n", "print('cwd =', os.getcwd())" ] }, { "cell_type": "code", "execution_count": null, "id": "81701d83", "metadata": {}, "outputs": [], "source": [ "# === 5. Configure run (shard 1 / 3) ===\n", "import os\n", "os.environ['INCIDENT_COMMANDER_MOCK'] = 'true'\n", "os.environ['IC_ACTOR_MODEL'] = ACTOR_PATH\n", "os.environ['IC_CRITIC_PROVIDER'] = 'local'\n", "os.environ['IC_CRITIC_MODEL'] = CRITIC_PATH\n", "os.environ['IC_TASK_MODE'] = 'all'\n", "os.environ['IC_TASK_SHARDS'] = '3'\n", "os.environ['IC_TASK_SHARD'] = '0'\n", "os.environ['IC_TOTAL_UPDATES'] = '60'\n", "os.environ['IC_ROLLOUTS'] = '3'\n", "os.environ['IC_MAX_STEPS'] = '12'\n", "os.environ['IC_CKPT_EVERY'] = '15'\n", "os.environ['IC_RUN_NAME'] = 'kaggle1'\n", "print('actor :', os.environ['IC_ACTOR_MODEL'])\n", "print('critic:', os.environ['IC_CRITIC_MODEL'])\n", "print('shard :', os.environ['IC_TASK_SHARD'], '/', os.environ['IC_TASK_SHARDS'])" ] }, { "cell_type": "code", "execution_count": null, "id": "5fecb57e", "metadata": {}, "outputs": [], "source": [ "# === 6. Train ===\n", "import subprocess, sys\n", "result = subprocess.run([sys.executable, 'scripts/run_training.py'], check=False)\n", "print('exit code:', result.returncode)" ] }, { "cell_type": "code", "execution_count": null, "id": "ed71f261", "metadata": {}, "outputs": [], "source": [ "# === 7. Package outputs for download ===\n", "import shutil, glob, pathlib\n", "LOGS = pathlib.Path('colab/logs')\n", "finals = sorted(LOGS.glob('adapter_kaggle1_final'))\n", "ckpts = sorted(LOGS.glob('adapter_kaggle1_u*'))\n", "keep = (finals or ckpts)\n", "assert keep, 'No adapter directories found -- check the training cell output.'\n", "src = keep[-1]\n", "print('packaging', src)\n", "dst = pathlib.Path('/kaggle/working/adapter_kaggle1.zip')\n", "shutil.make_archive(str(dst.with_suffix('')), 'zip', root_dir=src)\n", "print('zipped to', dst, 'size:', dst.stat().st_size, 'bytes')\n", "for j in glob.glob('colab/logs/training_kaggle1*.json'):\n", " shutil.copy(j, '/kaggle/working/')\n", "print('files in /kaggle/working/:')\n", "for f in sorted(pathlib.Path('/kaggle/working/').iterdir()):\n", " if f.name == 'hf-cache':\n", " continue\n", " print(' ', f.name, f.stat().st_size if f.is_file() else '')" ] }, { "cell_type": "markdown", "id": "1be8077f", "metadata": {}, "source": [ "## Done\n", "\n", "Download `adapter_kaggle1.zip` from the **Output** tab on the right.\n", "Run shard 2 and shard 3 in parallel browser tabs, then on your laptop:\n", "\n", "```powershell\n", "python scripts/merge_lora_adapters.py `\n", " --inputs ./adapter_kaggle1 ./adapter_kaggle2 ./adapter_kaggle3 `\n", " --output ./adapter_merged\n", "```\n", "\n", "The merged adapter loads with the standard `peft` API on top of `microsoft/Phi-3.5-mini-instruct`." ] } ], "metadata": { "kaggle": { "accelerator": "nvidiaTeslaT4", "dataSources": [], "isInternetEnabled": true, "language": "python", "sourceType": "notebook" }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.10" } }, "nbformat": 4, "nbformat_minor": 5 }