walidsobhie-code Claude Opus 4.6 commited on
Commit
e31f34c
·
1 Parent(s): e5ae26c

fix: update notebook for Colab T4 GPU training

Browse files

- Configure for CUDA/T4 GPU instead of MPS
- Add base model download step
- Use Google Drive for persistence
- Fix training and merge function calls
- Update workflow for Colab environment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. colab_train_stack29.ipynb +207 -102
colab_train_stack29.ipynb CHANGED
@@ -4,17 +4,25 @@
4
  "cell_type": "markdown",
5
  "metadata": {},
6
  "source": [
7
- "# 🚀 Stack 2.9 - Local Training Notebook\n",
8
  "\n",
9
- "**Training on local Mac with MPS (Apple Silicon GPU)**\n",
10
  "\n",
11
- "This notebook trains a LoRA adapter for Stack 2.9 on **Qwen2.5-Coder-7B** using your local machine.\n",
 
 
 
 
12
  "\n",
13
  "---\n",
14
  "\n",
15
- "**Prerequisites:**\n",
16
- "1. Base model downloaded to `./base_model_qwen7b/`\n",
17
- "2. Run from the stack-2.9 directory\n",
 
 
 
 
18
  "---\n"
19
  ]
20
  },
@@ -24,32 +32,46 @@
24
  "metadata": {},
25
  "outputs": [],
26
  "source": [
27
- "# Check system and GPU\n",
28
- "import platform\n",
29
- "import os\n",
 
 
 
 
 
 
30
  "\n",
31
- "print(\"=\"*60)\n",
32
- "print(\"SYSTEM INFO\")\n",
33
- "print(\"=\"*60)\n",
34
- "print(f\"Platform: {platform.platform()}\")\n",
35
- "print(f\"Python: {platform.python_version()}\")\n",
36
- "print(f\"Working directory: {os.getcwd()}\")\n",
37
  "\n",
38
- "try:\n",
39
- " import torch\n",
40
- " print(f\"PyTorch: {torch.__version__}\")\n",
41
- " print(f\"MPS available: {torch.backends.mps.is_available()}\")\n",
42
- " if torch.backends.mps.is_available():\n",
43
- " print(f\"MPS device: {torch.backends.mps.is_built()}\")\n",
44
- "except ImportError:\n",
45
- " print(\"PyTorch not installed - run: pip install torch\")"
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  ]
47
  },
48
  {
49
  "cell_type": "markdown",
50
  "metadata": {},
51
  "source": [
52
- "## 1️⃣ Set Working Directory"
53
  ]
54
  },
55
  {
@@ -58,35 +80,79 @@
58
  "metadata": {},
59
  "outputs": [],
60
  "source": [
61
- "# Navigate to the stack-2.9 directory\n",
62
- "import os\n",
 
63
  "\n",
64
- "STACK_PATH = \"/Users/walidsobhi/.openclaw/workspace/stack-2.9\"\n",
65
- "os.chdir(STACK_PATH)\n",
 
 
 
 
 
 
 
 
66
  "\n",
67
- "BASE_MODEL_PATH = \"./base_model_qwen7b\"\n",
68
- "DATA_PATH = \"./data/final/train.jsonl\"\n",
69
- "OUTPUT_DIR = \"./training_output\"\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  "\n",
71
- "os.makedirs(OUTPUT_DIR, exist_ok=True)\n",
 
 
 
 
 
 
 
 
 
 
72
  "\n",
73
- "print(f\"✅ Working directory: {os.getcwd()}\")\n",
74
- "print(f\"Base model path: {BASE_MODEL_PATH}\")\n",
75
- "print(f\"Data path: {DATA_PATH}\")\n",
76
- "print(f\"Output dir: {OUTPUT_DIR}\")\n",
77
  "\n",
78
- "# Check paths exist\n",
79
- "print(\"\\n📁 Checking required files:\")\n",
80
- "print(f\" - Data exists: {os.path.exists(DATA_PATH)}\")\n",
81
- "if not os.path.exists(DATA_PATH):\n",
82
- " print(f\" ⚠️ Data not found at {DATA_PATH}\")"
 
 
 
 
 
 
 
83
  ]
84
  },
85
  {
86
  "cell_type": "markdown",
87
  "metadata": {},
88
  "source": [
89
- "## 2️⃣ Install Dependencies"
 
 
90
  ]
91
  },
92
  {
@@ -95,18 +161,26 @@
95
  "metadata": {},
96
  "outputs": [],
97
  "source": [
98
- "# Install required packages\n",
99
- "!pip install torch torchvision torchaudio\n",
100
- "!pip install transformers peft accelerate datasets pyyaml tqdm\n",
101
- "!pip install scipy\n",
102
- "print(\"\\n✅ Dependencies installed\")"
 
 
 
 
 
 
 
 
103
  ]
104
  },
105
  {
106
  "cell_type": "markdown",
107
  "metadata": {},
108
  "source": [
109
- "## 3️⃣ Prepare Training Configuration"
110
  ]
111
  },
112
  {
@@ -115,7 +189,7 @@
115
  "metadata": {},
116
  "outputs": [],
117
  "source": [
118
- "# Use local training config\n",
119
  "import yaml\n",
120
  "\n",
121
  "config_path = \"./stack/training/train_config_local.yaml\"\n",
@@ -123,16 +197,18 @@
123
  "with open(config_path, 'r') as f:\n",
124
  " config = yaml.safe_load(f)\n",
125
  "\n",
126
- "# Update paths to match our setup\n",
127
- "config['model']['name'] = BASE_MODEL_PATH\n",
128
  "config['data']['input_path'] = DATA_PATH\n",
129
- "config['output']['lora_dir'] = f\"{OUTPUT_DIR}/lora\"\n",
130
- "config['output']['merged_dir'] = f\"{OUTPUT_DIR}/merged\"\n",
131
- "config['hardware']['device'] = \"mps\"\n",
 
132
  "\n",
133
  "# Save updated config\n",
134
- "updated_config_path = f\"{OUTPUT_DIR}/train_config.yaml\"\n",
135
  "os.makedirs(OUTPUT_DIR, exist_ok=True)\n",
 
136
  "\n",
137
  "with open(updated_config_path, 'w') as f:\n",
138
  " yaml.dump(config, f)\n",
@@ -149,7 +225,15 @@
149
  "cell_type": "markdown",
150
  "metadata": {},
151
  "source": [
152
- "## 4️⃣ Check Base Model"
 
 
 
 
 
 
 
 
153
  ]
154
  },
155
  {
@@ -158,50 +242,35 @@
158
  "metadata": {},
159
  "outputs": [],
160
  "source": [
161
- "# Check if base model exists\n",
162
  "import os\n",
 
163
  "\n",
164
- "model_path = BASE_MODEL_PATH\n",
165
- "print(f\"Checking base model at: {model_path}\")\n",
166
  "\n",
167
- "if os.path.exists(model_path):\n",
168
- " files = os.listdir(model_path)\n",
169
- " print(f\"✅ Base model found! {len(files)} files:\")\n",
170
- " for f in files[:10]:\n",
171
- " print(f\" - {f}\")\n",
172
- " if len(files) > 10:\n",
173
- " print(f\" ... and {len(files)-10} more\")\n",
174
- "else:\n",
175
- " print(\"❌ Base model NOT found!\")\n",
176
- " print(\"\\nTo download Qwen2.5-Coder-7B:\")\n",
177
- " print(\" huggingface-cli download Qwen/Qwen2.5-Coder-7B --local-dir ./base_model_qwen7b\")\n",
178
- " print(\" OR\")\n",
179
- " print(\" python -c \\\"from transformers import AutoModelForCausalLM; AutoModelForCausalLM.from_pretrained('Qwen/Qwen2.5-Coder-7B', local_dir='./base_model_qwen7b')\\\"\")"
180
- ]
181
- },
182
- {
183
- "cell_type": "markdown",
184
- "metadata": {},
185
- "source": [
186
- "## 5️⃣ Train LoRA Adapter\n",
187
  "\n",
188
- "⚠️ **This will take significant time on MPS.**\n",
189
  "\n",
190
- "MPS is slower than CUDA, so training will take longer. Consider using a smaller dataset for testing."
 
 
191
  ]
192
  },
193
- {
194
- "cell_type": "code",
195
- "execution_count": null,
196
- "metadata": {},
197
- "outputs": [],
198
- "source": "import os\nimport sys\n\n# Add the training module to path\nsys.path.insert(0, './stack/training')\n\nprint(\"=\"*60)\nprint(\"STARTING TRAINING\")\nprint(\"=\"*60)\nprint(f\"Working directory: {os.getcwd()}\")\nprint(f\"Config: {updated_config_path}\")\nprint(f\"Output: {OUTPUT_DIR}/lora\")\nprint(\"=\"*60 + \"\\n\")\n\n# Run training using the correct function\nfrom train_lora import train_lora\n\ntrainer = train_lora(updated_config_path)\n\nprint(\"\\n\" + \"=\"*60)\nprint(\"TRAINING COMPLETED\")\nprint(\"=\"*60)"
199
- },
200
  {
201
  "cell_type": "markdown",
202
  "metadata": {},
203
  "source": [
204
- "## 6️⃣ Verify Training Output"
205
  ]
206
  },
207
  {
@@ -220,14 +289,16 @@
220
  " size = os.path.getsize(os.path.join(lora_dir, f)) / (1024*1024)\n",
221
  " print(f\" - {f}: {size:.1f} MB\")\n",
222
  "else:\n",
223
- " print(\"⚠️ LoRA directory not found\")"
224
  ]
225
  },
226
  {
227
  "cell_type": "markdown",
228
  "metadata": {},
229
  "source": [
230
- "## 7️⃣ Merge LoRA Adapter (Optional)"
 
 
231
  ]
232
  },
233
  {
@@ -235,13 +306,46 @@
235
  "execution_count": null,
236
  "metadata": {},
237
  "outputs": [],
238
- "source": "# Merge LoRA with base model\nmerged_dir = f\"{OUTPUT_DIR}/merged\"\n\nprint(\"=\"*60)\nprint(\"MERGING LORA ADAPTER\")\nprint(\"=\"*60)\n\nsys.path.insert(0, './stack/training')\nfrom merge_adapter import merge_adapter\n\n# Create a minimal config for merging\nimport yaml\n\nmerge_config = {\n 'model': {'name': BASE_MODEL_PATH, 'trust_remote_code': True},\n 'output': {'lora_dir': f'{OUTPUT_DIR}/lora', 'merged_dir': merged_dir},\n 'quantization': {'enabled': False}\n}\n\n# Save config for merge\nmerge_config_path = f\"{OUTPUT_DIR}/merge_config.yaml\"\nwith open(merge_config_path, 'w') as f:\n yaml.dump(merge_config, f)\n\n# Run merge\nmerge_adapter(\n config_path=merge_config_path,\n lora_path=f\"{OUTPUT_DIR}/lora\",\n output_path=merged_dir\n)\n\nprint(f\"\\n✅ Merged model saved to: {merged_dir}\")\nif os.path.exists(merged_dir):\n print(\"Files:\", os.listdir(merged_dir)[:5])"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  },
240
  {
241
  "cell_type": "markdown",
242
  "metadata": {},
243
  "source": [
244
- "## 8️⃣ Test Inference"
245
  ]
246
  },
247
  {
@@ -261,12 +365,12 @@
261
  " model = AutoModelForCausalLM.from_pretrained(\n",
262
  " model_path,\n",
263
  " torch_dtype=torch.float16,\n",
264
- " device_map=\"mps\",\n",
265
  " trust_remote_code=True\n",
266
  " )\n",
267
  " \n",
268
  " prompt = \"Write a Python function to reverse a string:\\n\\n```python\\n\"\n",
269
- " inputs = tokenizer(prompt, return_tensors=\"pt\").to(\"mps\")\n",
270
  " \n",
271
  " print(\"Generating...\")\n",
272
  " with torch.no_grad():\n",
@@ -294,21 +398,22 @@
294
  "source": [
295
  "## 🔚 Training Complete!\n",
296
  "\n",
297
- "Your model is ready in:\n",
298
- "- LoRA adapter: `{OUTPUT_DIR}/lora/`\n",
299
- "- Merged model: `{OUTPUT_DIR}/merged/`\n",
300
  "\n",
301
  "**Next steps:**\n",
302
- "1. Run evaluation on HumanEval/MBPP benchmarks\n",
303
- "2. Upload to Hugging Face Hub\n",
304
- "3. Apply to Together AI\n"
 
 
 
305
  ]
306
  }
307
  ],
308
  "metadata": {
309
  "accelerator": "GPU",
310
  "colab": {
311
- "name": "Stack 2.9 Local Training (Fixed)",
312
  "provenance": []
313
  },
314
  "kernelspec": {
 
4
  "cell_type": "markdown",
5
  "metadata": {},
6
  "source": [
7
+ "# 🚀 Stack 2.9 - Colab Training Notebook\n",
8
  "\n",
9
+ "**Zero-cost training on Google Colab free tier with T4 GPU**\n",
10
  "\n",
11
+ "This notebook trains a LoRA adapter for Stack 2.9 on **Qwen2.5-Coder-7B** using a free T4 GPU.\n",
12
+ "\n",
13
+ "⏱️ **Expected runtime:** 3-5 hours\n",
14
+ "💾 **VRAM needed:** ~12GB (fits in T4's 15GB)\n",
15
+ "📦 **Output:** `./training_output/` (on Google Drive)\n",
16
  "\n",
17
  "---\n",
18
  "\n",
19
+ "**CRITICAL:** All data saved to **Google Drive** to persist through disconnects.\n",
20
+ "\n",
21
+ "**Instructions:**\n",
22
+ "1. Runtime → Change runtime type → **GPU (T4)**\n",
23
+ "2. Run all cells in order\n",
24
+ "3. **Allow** Drive access when prompted\n",
25
+ "\n",
26
  "---\n"
27
  ]
28
  },
 
32
  "metadata": {},
33
  "outputs": [],
34
  "source": [
35
+ "# Check GPU\n",
36
+ "!nvidia-smi"
37
+ ]
38
+ },
39
+ {
40
+ "cell_type": "markdown",
41
+ "metadata": {},
42
+ "source": [
43
+ "## 1️⃣ Mount Google Drive (REQUIRED for persistence)\n",
44
  "\n",
45
+ "Click the link, allow access, copy the auth code, paste it, and press Enter.\n",
 
 
 
 
 
46
  "\n",
47
+ "**Without Drive mounting, training will be lost if Colab disconnects!**"
48
+ ]
49
+ },
50
+ {
51
+ "cell_type": "code",
52
+ "execution_count": null,
53
+ "metadata": {},
54
+ "outputs": [],
55
+ "source": [
56
+ "from google.colab import drive\n",
57
+ "drive.mount('/content/drive')\n",
58
+ "\n",
59
+ "# Set up paths on Drive - ALL OUTPUT GOES HERE\n",
60
+ "import os\n",
61
+ "BASE_PATH = \"/content/drive/MyDrive/stack-2.9\"\n",
62
+ "os.makedirs(BASE_PATH, exist_ok=True)\n",
63
+ "os.chdir(BASE_PATH)\n",
64
+ "print(f\"\\n✅ Working directory: {os.getcwd()}\")\n",
65
+ "print(f\"All outputs will be saved to: {BASE_PATH}\")\n",
66
+ "print(\"\\nCurrent folder contents:\")\n",
67
+ "!ls -la"
68
  ]
69
  },
70
  {
71
  "cell_type": "markdown",
72
  "metadata": {},
73
  "source": [
74
+ "## 2️⃣ Clone Stack 2.9 Repository"
75
  ]
76
  },
77
  {
 
80
  "metadata": {},
81
  "outputs": [],
82
  "source": [
83
+ "# Clone into Drive if not already there\n",
84
+ "if not os.path.exists('stack-2.9'):\n",
85
+ " !git clone https://github.com/my-ai-stack/stack-2.9.git\n",
86
  "\n",
87
+ "os.chdir('stack-2.9')\n",
88
+ "print(f\"Now in: {os.getcwd()}\")\n",
89
+ "!ls -la"
90
+ ]
91
+ },
92
+ {
93
+ "cell_type": "markdown",
94
+ "metadata": {},
95
+ "source": [
96
+ "## 3️⃣ Install Dependencies\n",
97
  "\n",
98
+ "Takes 5-10 minutes."
99
+ ]
100
+ },
101
+ {
102
+ "cell_type": "code",
103
+ "execution_count": null,
104
+ "metadata": {},
105
+ "outputs": [],
106
+ "source": [
107
+ "!pip install --upgrade pip\n",
108
+ "!pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118\n",
109
+ "!pip install transformers==4.40.0 peft==0.10.0 accelerate bitsandbytes==0.43.0 datasets pyyaml tqdm\n",
110
+ "!pip install scipy\n",
111
+ "print(\"\\n✅ Dependencies installed\")"
112
+ ]
113
+ },
114
+ {
115
+ "cell_type": "markdown",
116
+ "metadata": {},
117
+ "source": [
118
+ "## 4️⃣ Download Base Model (Qwen2.5-Coder-7B)\n",
119
  "\n",
120
+ "This takes ~15-20 minutes. The model is ~14GB."
121
+ ]
122
+ },
123
+ {
124
+ "cell_type": "code",
125
+ "execution_count": null,
126
+ "metadata": {},
127
+ "outputs": [],
128
+ "source": [
129
+ "MODEL_NAME = \"Qwen/Qwen2.5-Coder-7B\"\n",
130
+ "MODEL_DIR = \"./base_model_qwen7b\"\n",
131
  "\n",
132
+ "from transformers import AutoModelForCausalLM, AutoTokenizer\n",
133
+ "import os\n",
 
 
134
  "\n",
135
+ "if not os.path.exists(MODEL_DIR):\n",
136
+ " print(f\"Downloading {MODEL_NAME} to {MODEL_DIR}...\")\n",
137
+ " print(\"This will take 15-20 minutes...\")\n",
138
+ " tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)\n",
139
+ " tokenizer.save_pretrained(MODEL_DIR)\n",
140
+ " model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True)\n",
141
+ " model.save_pretrained(MODEL_DIR)\n",
142
+ " print(f\"✅ Model saved to {MODEL_DIR}\")\n",
143
+ "else:\n",
144
+ " print(f\"✅ Model already exists at {MODEL_DIR}\")\n",
145
+ "\n",
146
+ "!ls -lh {MODEL_DIR} | head -10"
147
  ]
148
  },
149
  {
150
  "cell_type": "markdown",
151
  "metadata": {},
152
  "source": [
153
+ "## 5️⃣ Prepare Training Data\n",
154
+ "\n",
155
+ "Using the bundled mini dataset (5K examples) for quick prototyping."
156
  ]
157
  },
158
  {
 
161
  "metadata": {},
162
  "outputs": [],
163
  "source": [
164
+ "# Check if data exists in the repo, if not create mini dataset\n",
165
+ "import os\n",
166
+ "\n",
167
+ "DATA_PATH = \"./data/final/train.jsonl\"\n",
168
+ "\n",
169
+ "if os.path.exists(DATA_PATH):\n",
170
+ " print(f\"✅ Training data found at {DATA_PATH}\")\n",
171
+ " !wc -l {DATA_PATH}\n",
172
+ "else:\n",
173
+ " print(\"Creating mini dataset (5K examples)...\")\n",
174
+ " !python scripts/create_mini_dataset.py --size 5000 --output data_mini/train_mini.jsonl\n",
175
+ " DATA_PATH = \"./data_mini/train_mini.jsonl\"\n",
176
+ " !ls -lh {DATA_PATH}"
177
  ]
178
  },
179
  {
180
  "cell_type": "markdown",
181
  "metadata": {},
182
  "source": [
183
+ "## 6️⃣ Prepare Training Configuration"
184
  ]
185
  },
186
  {
 
189
  "metadata": {},
190
  "outputs": [],
191
  "source": [
192
+ "# Use Colab config and update paths\n",
193
  "import yaml\n",
194
  "\n",
195
  "config_path = \"./stack/training/train_config_local.yaml\"\n",
 
197
  "with open(config_path, 'r') as f:\n",
198
  " config = yaml.safe_load(f)\n",
199
  "\n",
200
+ "# Update for Colab/T4 GPU\n",
201
+ "config['model']['name'] = MODEL_DIR\n",
202
  "config['data']['input_path'] = DATA_PATH\n",
203
+ "config['output']['lora_dir'] = \"./training_output/lora\"\n",
204
+ "config['output']['merged_dir'] = \"./training_output/merged\"\n",
205
+ "config['hardware']['device'] = \"cuda\" # Use T4 GPU\n",
206
+ "config['hardware']['num_gpus'] = 1\n",
207
  "\n",
208
  "# Save updated config\n",
209
+ "OUTPUT_DIR = \"./training_output\"\n",
210
  "os.makedirs(OUTPUT_DIR, exist_ok=True)\n",
211
+ "updated_config_path = f\"{OUTPUT_DIR}/train_config.yaml\"\n",
212
  "\n",
213
  "with open(updated_config_path, 'w') as f:\n",
214
  " yaml.dump(config, f)\n",
 
225
  "cell_type": "markdown",
226
  "metadata": {},
227
  "source": [
228
+ "## 7️⃣ Train LoRA Adapter\n",
229
+ "\n",
230
+ "⚠️ **This takes 3-5 hours. DO NOT INTERRUPT.**\n",
231
+ "\n",
232
+ "If Colab disconnects, reconnect and training will resume from checkpoint automatically.\n",
233
+ "\n",
234
+ "Watch for `Train loss:` decreasing. It should start ~2.0-3.0 and trend downward.\n",
235
+ "\n",
236
+ "Checkpoints saved every 200 steps to `./training_output/lora/` (on Drive)."
237
  ]
238
  },
239
  {
 
242
  "metadata": {},
243
  "outputs": [],
244
  "source": [
 
245
  "import os\n",
246
+ "import sys\n",
247
  "\n",
248
+ "# Add training module to path\n",
249
+ "sys.path.insert(0, './stack/training')\n",
250
  "\n",
251
+ "print(\"=\"*60)\n",
252
+ "print(\"STARTING TRAINING\")\n",
253
+ "=\"*60)\n",
254
+ "print(f\"Working directory: {os.getcwd()}\")\n",
255
+ "print(f\"Config: {updated_config_path}\")\n",
256
+ "print(f\"Output: {OUTPUT_DIR}/lora\")\n",
257
+ "print(\"=\"*60 + \"\\n\")\n",
258
+ "\n",
259
+ "# Run training\n",
260
+ "from train_lora import train_lora\n",
 
 
 
 
 
 
 
 
 
 
261
  "\n",
262
+ "trainer = train_lora(updated_config_path)\n",
263
  "\n",
264
+ "print(\"\\n\" + \"=\"*60)\n",
265
+ "print(\"TRAINING FINISHED OR STOPPED\")\n",
266
+ "print(\"=\"*60)"
267
  ]
268
  },
 
 
 
 
 
 
 
269
  {
270
  "cell_type": "markdown",
271
  "metadata": {},
272
  "source": [
273
+ "## 8️⃣ Verify Training Output"
274
  ]
275
  },
276
  {
 
289
  " size = os.path.getsize(os.path.join(lora_dir, f)) / (1024*1024)\n",
290
  " print(f\" - {f}: {size:.1f} MB\")\n",
291
  "else:\n",
292
+ " print(\"⚠️ LoRA directory not found - training may have failed\")"
293
  ]
294
  },
295
  {
296
  "cell_type": "markdown",
297
  "metadata": {},
298
  "source": [
299
+ "## 9️⃣ Merge LoRA Adapter with Base Model\n",
300
+ "\n",
301
+ "Combines the trained adapter with the base model to produce a standalone fine-tuned model."
302
  ]
303
  },
304
  {
 
306
  "execution_count": null,
307
  "metadata": {},
308
  "outputs": [],
309
+ "source": [
310
+ "import yaml\n",
311
+ "import sys\n",
312
+ "\n",
313
+ "sys.path.insert(0, './stack/training')\n",
314
+ "from merge_adapter import merge_adapter\n",
315
+ "\n",
316
+ "merged_dir = f\"{OUTPUT_DIR}/merged\"\n",
317
+ "\n",
318
+ "print(\"=\"*60)\n",
319
+ "print(\"MERGING LORA ADAPTER\")\n",
320
+ "=\"*60)\n",
321
+ "\n",
322
+ "# Create merge config\n",
323
+ "merge_config = {\n",
324
+ " 'model': {'name': MODEL_DIR, 'trust_remote_code': True},\n",
325
+ " 'output': {'lora_dir': f'{OUTPUT_DIR}/lora', 'merged_dir': merged_dir},\n",
326
+ " 'quantization': {'enabled': False}\n",
327
+ "}\n",
328
+ "\n",
329
+ "merge_config_path = f\"{OUTPUT_DIR}/merge_config.yaml\"\n",
330
+ "with open(merge_config_path, 'w') as f:\n",
331
+ " yaml.dump(merge_config, f)\n",
332
+ "\n",
333
+ "# Run merge\n",
334
+ "merge_adapter(\n",
335
+ " config_path=merge_config_path,\n",
336
+ " lora_path=f\"{OUTPUT_DIR}/lora\",\n",
337
+ " output_path=merged_dir\n",
338
+ ")\n",
339
+ "\n",
340
+ "print(f\"\\n✅ Merged model saved to: {merged_dir}\")\n",
341
+ "!ls -lh {merged_dir}/"
342
+ ]
343
  },
344
  {
345
  "cell_type": "markdown",
346
  "metadata": {},
347
  "source": [
348
+ "## 🔟 Test Inference (Quick Check)"
349
  ]
350
  },
351
  {
 
365
  " model = AutoModelForCausalLM.from_pretrained(\n",
366
  " model_path,\n",
367
  " torch_dtype=torch.float16,\n",
368
+ " device_map=\"cuda\",\n",
369
  " trust_remote_code=True\n",
370
  " )\n",
371
  " \n",
372
  " prompt = \"Write a Python function to reverse a string:\\n\\n```python\\n\"\n",
373
+ " inputs = tokenizer(prompt, return_tensors=\"pt\").to(\"cuda\")\n",
374
  " \n",
375
  " print(\"Generating...\")\n",
376
  " with torch.no_grad():\n",
 
398
  "source": [
399
  "## 🔚 Training Complete!\n",
400
  "\n",
401
+ "Your model is ready in `./training_output/merged/` and saved to Google Drive.\n",
 
 
402
  "\n",
403
  "**Next steps:**\n",
404
+ "1. **Download** `training_output/merged/` from Drive to your local machine\n",
405
+ "2. **Run evaluation**: Evaluate on HumanEval/MBPP benchmarks\n",
406
+ "3. **Upload model** to Hugging Face Hub\n",
407
+ "4. **Apply to Together AI**\n",
408
+ "\n",
409
+ "**Note:** This model was trained on the full/mini dataset. For better performance, consider training on more data or more epochs.\n"
410
  ]
411
  }
412
  ],
413
  "metadata": {
414
  "accelerator": "GPU",
415
  "colab": {
416
+ "name": "Stack 2.9 Colab Training (T4 GPU)",
417
  "provenance": []
418
  },
419
  "kernelspec": {