MSGEncrypted commited on
Commit
97e8808
·
1 Parent(s): 543077a

notebook wip

Browse files
Files changed (1) hide show
  1. notebook/gemma-finetune.ipynb +466 -0
notebook/gemma-finetune.ipynb ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {
7
+ "colab_type": "code",
8
+ "execution": {
9
+ "iopub.execute_input": "2026-06-07T13:53:33.681800Z",
10
+ "iopub.status.busy": "2026-06-07T13:53:33.681410Z",
11
+ "iopub.status.idle": "2026-06-07T13:53:47.949186Z",
12
+ "shell.execute_reply": "2026-06-07T13:53:47.948138Z",
13
+ "shell.execute_reply.started": "2026-06-07T13:53:33.681762Z"
14
+ },
15
+ "trusted": true
16
+ },
17
+ "outputs": [],
18
+ "source": [
19
+ "!pip install -U transformers"
20
+ ]
21
+ },
22
+ {
23
+ "cell_type": "markdown",
24
+ "metadata": {
25
+ "colab_type": "text"
26
+ },
27
+ "source": [
28
+ "## Local Inference on GPU \n",
29
+ "Model page: https://huggingface.co/google/gemma-4-E2B-it-qat-mobile-transformers\n",
30
+ "\n",
31
+ "⚠️ If the generated code snippets do not work, please open an issue on either the [model repo](https://huggingface.co/google/gemma-4-E2B-it-qat-mobile-transformers)\n",
32
+ "\t\t\tand/or on [huggingface.js](https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/src/model-libraries-snippets.ts) 🙏"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": null,
38
+ "metadata": {},
39
+ "outputs": [],
40
+ "source": []
41
+ },
42
+ {
43
+ "cell_type": "code",
44
+ "execution_count": null,
45
+ "metadata": {
46
+ "execution": {
47
+ "iopub.execute_input": "2026-06-07T14:00:05.743785Z",
48
+ "iopub.status.busy": "2026-06-07T14:00:05.742974Z",
49
+ "iopub.status.idle": "2026-06-07T14:00:05.748408Z",
50
+ "shell.execute_reply": "2026-06-07T14:00:05.747778Z",
51
+ "shell.execute_reply.started": "2026-06-07T14:00:05.743756Z"
52
+ },
53
+ "trusted": true
54
+ },
55
+ "outputs": [],
56
+ "source": [
57
+ "# Load model directly\n",
58
+ "from transformers import AutoModel\n",
59
+ "import torch\n",
60
+ "\n",
61
+ "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
62
+ "\n",
63
+ "model_name_gemma=\"google/gemma-4-E2B-it-qat-mobile-transformers\"\n",
64
+ "model_name=\"openbmb/MiniCPM5-1B\"\n",
65
+ "model_openbmb=\"openbmb/MiniCPM5-1B\""
66
+ ]
67
+ },
68
+ {
69
+ "cell_type": "code",
70
+ "execution_count": null,
71
+ "metadata": {
72
+ "colab_type": "code",
73
+ "execution": {
74
+ "iopub.execute_input": "2026-06-07T13:58:21.771701Z",
75
+ "iopub.status.busy": "2026-06-07T13:58:21.770950Z",
76
+ "iopub.status.idle": "2026-06-07T13:58:42.868203Z",
77
+ "shell.execute_reply": "2026-06-07T13:58:42.867564Z",
78
+ "shell.execute_reply.started": "2026-06-07T13:58:21.771669Z"
79
+ },
80
+ "trusted": true
81
+ },
82
+ "outputs": [],
83
+ "source": [
84
+ "\n",
85
+ "model = AutoModel.from_pretrained(model_name, dtype=\"auto\").to(device)"
86
+ ]
87
+ },
88
+ {
89
+ "cell_type": "code",
90
+ "execution_count": null,
91
+ "metadata": {
92
+ "execution": {
93
+ "iopub.execute_input": "2026-06-07T14:00:17.480009Z",
94
+ "iopub.status.busy": "2026-06-07T14:00:17.479002Z",
95
+ "iopub.status.idle": "2026-06-07T14:00:28.838734Z",
96
+ "shell.execute_reply": "2026-06-07T14:00:28.837707Z",
97
+ "shell.execute_reply.started": "2026-06-07T14:00:17.479974Z"
98
+ },
99
+ "trusted": true
100
+ },
101
+ "outputs": [],
102
+ "source": [
103
+ "\n",
104
+ "from transformers import AutoTokenizer, AutoModelForCausalLM\n",
105
+ "\n",
106
+ "tokenizer = AutoTokenizer.from_pretrained(\"openbmb/MiniCPM5-1B\")\n",
107
+ "model = AutoModelForCausalLM.from_pretrained(\"openbmb/MiniCPM5-1B\")\n"
108
+ ]
109
+ },
110
+ {
111
+ "cell_type": "code",
112
+ "execution_count": null,
113
+ "metadata": {
114
+ "execution": {
115
+ "iopub.execute_input": "2026-06-07T14:00:51.808940Z",
116
+ "iopub.status.busy": "2026-06-07T14:00:51.808046Z",
117
+ "iopub.status.idle": "2026-06-07T14:00:59.481653Z",
118
+ "shell.execute_reply": "2026-06-07T14:00:59.480980Z",
119
+ "shell.execute_reply.started": "2026-06-07T14:00:51.808892Z"
120
+ },
121
+ "trusted": true
122
+ },
123
+ "outputs": [],
124
+ "source": [
125
+ "messages = [\n",
126
+ " {\"role\": \"user\", \"content\": \"Who are you?\"},\n",
127
+ "]\n",
128
+ "inputs = tokenizer.apply_chat_template(\n",
129
+ "\tmessages,\n",
130
+ "\tadd_generation_prompt=True,\n",
131
+ "\ttokenize=True,\n",
132
+ "\treturn_dict=True,\n",
133
+ "\treturn_tensors=\"pt\",\n",
134
+ ").to(model.device)\n",
135
+ "\n",
136
+ "outputs = model.generate(**inputs, max_new_tokens=120)\n",
137
+ "print(tokenizer.decode(outputs[0][inputs[\"input_ids\"].shape[-1]:]))"
138
+ ]
139
+ },
140
+ {
141
+ "cell_type": "code",
142
+ "execution_count": null,
143
+ "metadata": {
144
+ "execution": {
145
+ "iopub.execute_input": "2026-06-07T13:59:02.169453Z",
146
+ "iopub.status.busy": "2026-06-07T13:59:02.168479Z",
147
+ "iopub.status.idle": "2026-06-07T13:59:04.394628Z",
148
+ "shell.execute_reply": "2026-06-07T13:59:04.393301Z",
149
+ "shell.execute_reply.started": "2026-06-07T13:59:02.169418Z"
150
+ },
151
+ "trusted": true
152
+ },
153
+ "outputs": [],
154
+ "source": [
155
+ "# from transformers import AutoTokenizer, pipeline\n",
156
+ "\n",
157
+ "# tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
158
+ "\n",
159
+ "# pipeline = pipeline(\n",
160
+ "# \"text-generation\",\n",
161
+ "# model=model,\n",
162
+ "# tokenizer=tokenizer,\n",
163
+ "# model_kwargs={\"torch_dtype\": \"auto\"},\n",
164
+ "# )\n",
165
+ "\n",
166
+ "# # Example of generating chat/text\n",
167
+ "# messages = [\n",
168
+ "# {\"role\": \"user\", \"content\": \"What is your favorite color?\"},\n",
169
+ "# ]\n",
170
+ "\n",
171
+ "# prompt = pipeline.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)\n",
172
+ "# outputs = pipeline(prompt, max_new_tokens=256, do_sample=True, temperature=0.7, top_k=50, top_p=0.95)\n",
173
+ "# print(outputs[0][\"generated_text\"])"
174
+ ]
175
+ },
176
+ {
177
+ "cell_type": "markdown",
178
+ "metadata": {},
179
+ "source": [
180
+ "# Finetuning"
181
+ ]
182
+ },
183
+ {
184
+ "cell_type": "code",
185
+ "execution_count": null,
186
+ "metadata": {
187
+ "execution": {
188
+ "iopub.execute_input": "2026-06-07T14:01:09.304174Z",
189
+ "iopub.status.busy": "2026-06-07T14:01:09.303286Z",
190
+ "iopub.status.idle": "2026-06-07T14:01:32.898893Z",
191
+ "shell.execute_reply": "2026-06-07T14:01:32.897942Z",
192
+ "shell.execute_reply.started": "2026-06-07T14:01:09.304140Z"
193
+ },
194
+ "trusted": true
195
+ },
196
+ "outputs": [],
197
+ "source": [
198
+ "# Install necessary libraries for finetuning (if not already installed)\n",
199
+ "!pip install -q -U accelerate peft bitsandbytes transformers trl datasets\n",
200
+ "\n",
201
+ "import torch\n",
202
+ "from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig\n",
203
+ "from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training\n",
204
+ "from trl import SFTTrainer\n",
205
+ "from datasets import Dataset\n",
206
+ "\n",
207
+ "# --- 1. Load Model and Tokenizer for Finetuning with QLoRA ---\n",
208
+ "# The `model` variable from a previous cell is AutoModel, for finetuning\n",
209
+ "# we typically need AutoModelForCausalLM with BitsAndBytesConfig.\n",
210
+ "# Let's reload it for clarity in this finetuning example.\n",
211
+ "\n",
212
+ "# model_id = \"google/gemma-4-E2B-it-qat-mobile-transformers\"\n",
213
+ "model_id = model_openbmb\n",
214
+ "\n",
215
+ "# Configure 4-bit quantization\n",
216
+ "bnb_config = BitsAndBytesConfig(\n",
217
+ " load_in_4bit=True,\n",
218
+ " bnb_4bit_quant_type=\"nf4\",\n",
219
+ " bnb_4bit_compute_dtype=torch.bfloat16,\n",
220
+ " bnb_4bit_use_double_quant=False,\n",
221
+ ")\n",
222
+ "\n",
223
+ "# Load the model with 4-bit quantization\n",
224
+ "# Assuming 'model' from earlier cell is a suitable base for this if not reloaded\n",
225
+ "# If you've already loaded it as `AutoModel`, you might need to ensure it's `AutoModelForCausalLM`\n",
226
+ "# and can be quantizied. For a robust finetuning example, it's safer to load it here again.\n",
227
+ "\n",
228
+ "tuned_model = AutoModelForCausalLM.from_pretrained(\n",
229
+ " model_id,\n",
230
+ " quantization_config=bnb_config,\n",
231
+ " device_map=\"auto\",\n",
232
+ ")\n",
233
+ "\n",
234
+ "tuned_model.config.use_cache = False\n",
235
+ "tuned_model.config.pretraining_tp = 1\n",
236
+ "\n",
237
+ "tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)\n",
238
+ "tokenizer.pad_token = tokenizer.eos_token\n"
239
+ ]
240
+ },
241
+ {
242
+ "cell_type": "code",
243
+ "execution_count": null,
244
+ "metadata": {
245
+ "execution": {
246
+ "iopub.execute_input": "2026-06-07T14:02:33.440153Z",
247
+ "iopub.status.busy": "2026-06-07T14:02:33.439372Z",
248
+ "iopub.status.idle": "2026-06-07T14:02:36.463743Z",
249
+ "shell.execute_reply": "2026-06-07T14:02:36.462765Z",
250
+ "shell.execute_reply.started": "2026-06-07T14:02:33.440118Z"
251
+ },
252
+ "trusted": true
253
+ },
254
+ "outputs": [],
255
+ "source": [
256
+ "\n",
257
+ "# Prepare model for k-bit training\n",
258
+ "tuned_model = prepare_model_for_kbit_training(tuned_model)\n",
259
+ "\n",
260
+ "# --- 2. Configure LoRA ---\n",
261
+ "lora_config = LoraConfig(\n",
262
+ " r=16, # LoRA attention dimension\n",
263
+ " lora_alpha=16, # Alpha parameter for LoRA scaling\n",
264
+ " target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\", \"gate_proj\", \"up_proj\", \"down_proj\"], # Target all linear layers\n",
265
+ " lora_dropout=0.05, # Dropout probability for LoRA layers\n",
266
+ " bias=\"none\", # Only add bias to the LoRA layers\n",
267
+ " task_type=\"CAUSAL_LM\", # Task type for causal language modeling\n",
268
+ ")\n",
269
+ "\n",
270
+ "tuned_model = get_peft_model(tuned_model, lora_config)\n",
271
+ "\n",
272
+ "# --- 3. Prepare a Sample Dataset ---\n",
273
+ "# For a real-world scenario, you would load your own dataset using `load_dataset`\n",
274
+ "# from the `datasets` library and format it appropriately.\n",
275
+ "# This is a simple dummy dataset for demonstration.\n",
276
+ "\n",
277
+ "# Example instruction tuning dataset format\n",
278
+ "data = {\n",
279
+ " \"text\": [\n",
280
+ " \"<start_of_turn>user\\nWhat is the capital of France?<end_of_turn>\\n<start_of_turn>model\\nParis is the capital of France.<end_of_turn>\",\n",
281
+ " \"<start_of_turn>user\\nSuggest a healthy snack.\\n<end_of_turn>\\n<start_of_turn>model\\nAlmonds or a piece of fruit like an apple are great healthy snack options.<end_of_turn>\",\n",
282
+ " \"<start_of_turn>user\\nExplain the concept of photosynthesis.\\n<end_of_turn>\\n<start_of_turn>model\\nPhotosynthesis is the process by which green plants and some other organisms convert light energy into chemical energy.<end_of_turn>\"\n",
283
+ " ]\n",
284
+ "}\n",
285
+ "\n",
286
+ "dataset = Dataset.from_dict(data)\n",
287
+ "\n",
288
+ "# --- 4. Define Training Arguments ---\n",
289
+ "from transformers import TrainingArguments\n",
290
+ "\n",
291
+ "training_args = TrainingArguments(\n",
292
+ " output_dir=\"./gemma_finetuned\", # Output directory for checkpoints and logs\n",
293
+ " num_train_epochs=1, # Number of training epochs\n",
294
+ " per_device_train_batch_size=2, # Batch size per GPU/CPU for training\n",
295
+ " gradient_accumulation_steps=2, # Number of updates steps to accumulate before performing a backward/update pass\n",
296
+ " optim=\"paged_adamw_8bit\", # Optimizer to use\n",
297
+ " save_steps=100, # Save checkpoint every X updates steps\n",
298
+ " logging_steps=10, # Log every X updates steps\n",
299
+ " learning_rate=2e-4, # Initial learning rate for AdamW optimizer\n",
300
+ " weight_decay=0.001, # Weight decay for AdamW\n",
301
+ " fp16=True, # Enable mixed precision training\n",
302
+ " bf16=False, # Disable BF16 if using FP16\n",
303
+ " max_grad_norm=0.3, # Max gradient norm\n",
304
+ " max_steps=-1, # Don't limit training by steps, use epochs\n",
305
+ " warmup_ratio=0.03, # Ratio of total steps for a linear warmup from 0 to learning_rate\n",
306
+ " # group_by_length=True, # Group sequences of roughly the same length together to speed up training\n",
307
+ " lr_scheduler_type=\"constant\", # Learning rate scheduler type\n",
308
+ " report_to=\"none\" # Disable reporting to any tracking service\n",
309
+ ")\n",
310
+ "\n",
311
+ "# --- 5. Initialize and Run SFTTrainer ---\n",
312
+ "\n",
313
+ "trainer = SFTTrainer(\n",
314
+ " model=tuned_model,\n",
315
+ " train_dataset=dataset,\n",
316
+ " peft_config=lora_config,\n",
317
+ " # dataset_text_field=\"text\", # Name of the column containing the text data\n",
318
+ " # tokenizer=tokenizer,\n",
319
+ " args=training_args,\n",
320
+ " # packing=False, # Whether to pack multiple short examples into one longer sequence to improve efficiency\n",
321
+ " # max_seq_length=512, # Max sequence length to use for training\n",
322
+ ")\n",
323
+ "\n",
324
+ "print(\"Starting finetuning...\")\n",
325
+ "trainer.train()\n",
326
+ "print(\"Finetuning complete!\")\n",
327
+ "\n",
328
+ "# --- 6. (Optional) Save the finetuned model ---\n",
329
+ "# trainer.save_model(\"./gemma_finetuned_model\")\n",
330
+ "\n",
331
+ "# --- 7. (Optional) Merge LoRA adapters with the base model for inference ---\n",
332
+ "# from peft import AutoPeftModelForCausalLM\n",
333
+ "# merged_model = AutoPeftModelForCausalLM.from_pretrained(\n",
334
+ "# \"./gemma_finetuned_model\",\n",
335
+ "# device_map=\"auto\",\n",
336
+ "# torch_dtype=torch.bfloat16 # or torch.float16 depending on your hardware\n",
337
+ "# )\n",
338
+ "# merged_model.save_pretrained(\"gemma_merged_model\", safe_serialization=True)\n",
339
+ "# tokenizer.save_pretrained(\"gemma_merged_model\")\n"
340
+ ]
341
+ },
342
+ {
343
+ "cell_type": "code",
344
+ "execution_count": null,
345
+ "metadata": {
346
+ "trusted": true
347
+ },
348
+ "outputs": [],
349
+ "source": [
350
+ "\n",
351
+ "# Prepare model for k-bit training\n",
352
+ "tuned_model = prepare_model_for_kbit_training(tuned_model)\n",
353
+ "\n",
354
+ "# --- 2. Configure LoRA ---\n",
355
+ "lora_config = LoraConfig(\n",
356
+ " r=16, # LoRA attention dimension\n",
357
+ " lora_alpha=16, # Alpha parameter for LoRA scaling\n",
358
+ " target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\", \"gate_proj\", \"up_proj\", \"down_proj\"], # Target all linear layers\n",
359
+ " lora_dropout=0.05, # Dropout probability for LoRA layers\n",
360
+ " bias=\"none\", # Only add bias to the LoRA layers\n",
361
+ " task_type=\"CAUSAL_LM\", # Task type for causal language modeling\n",
362
+ ")\n",
363
+ "\n",
364
+ "tuned_model = get_peft_model(tuned_model, lora_config)\n",
365
+ "\n",
366
+ "# --- 3. Prepare a Sample Dataset ---\n",
367
+ "# For a real-world scenario, you would load your own dataset using `load_dataset`\n",
368
+ "# from the `datasets` library and format it appropriately.\n",
369
+ "# This is a simple dummy dataset for demonstration.\n",
370
+ "\n",
371
+ "# Example instruction tuning dataset format\n",
372
+ "data = {\n",
373
+ " \"text\": [\n",
374
+ " \"<start_of_turn>user\\nWhat is the capital of France?<end_of_turn>\\n<start_of_turn>model\\nParis is the capital of France.<end_of_turn>\",\n",
375
+ " \"<start_of_turn>user\\nSuggest a healthy snack.\\n<end_of_turn>\\n<start_of_turn>model\\nAlmonds or a piece of fruit like an apple are great healthy snack options.<end_of_turn>\",\n",
376
+ " \"<start_of_turn>user\\nExplain the concept of photosynthesis.\\n<end_of_turn>\\n<start_of_turn>model\\nPhotosynthesis is the process by which green plants and some other organisms convert light energy into chemical energy.<end_of_turn>\"\n",
377
+ " ]\n",
378
+ "}\n",
379
+ "\n",
380
+ "dataset = Dataset.from_dict(data)\n",
381
+ "\n",
382
+ "# --- 4. Define Training Arguments ---\n",
383
+ "from transformers import TrainingArguments\n",
384
+ "\n",
385
+ "training_args = TrainingArguments(\n",
386
+ " output_dir=\"./gemma_finetuned\", # Output directory for checkpoints and logs\n",
387
+ " num_train_epochs=1, # Number of training epochs\n",
388
+ " per_device_train_batch_size=2, # Batch size per GPU/CPU for training\n",
389
+ " gradient_accumulation_steps=2, # Number of updates steps to accumulate before performing a backward/update pass\n",
390
+ " optim=\"paged_adamw_8bit\", # Optimizer to use\n",
391
+ " save_steps=100, # Save checkpoint every X updates steps\n",
392
+ " logging_steps=10, # Log every X updates steps\n",
393
+ " learning_rate=2e-4, # Initial learning rate for AdamW optimizer\n",
394
+ " weight_decay=0.001, # Weight decay for AdamW\n",
395
+ " fp16=True, # Enable mixed precision training\n",
396
+ " bf16=False, # Disable BF16 if using FP16\n",
397
+ " max_grad_norm=0.3, # Max gradient norm\n",
398
+ " max_steps=-1, # Don't limit training by steps, use epochs\n",
399
+ " warmup_ratio=0.03, # Ratio of total steps for a linear warmup from 0 to learning_rate\n",
400
+ " # group_by_length=True, # Group sequences of roughly the same length together to speed up training\n",
401
+ " lr_scheduler_type=\"constant\", # Learning rate scheduler type\n",
402
+ " report_to=\"none\" # Disable reporting to any tracking service\n",
403
+ ")\n",
404
+ "\n",
405
+ "# --- 5. Initialize and Run SFTTrainer ---\n",
406
+ "\n",
407
+ "trainer = SFTTrainer(\n",
408
+ " model=tuned_model,\n",
409
+ " train_dataset=dataset,\n",
410
+ " peft_config=lora_config,\n",
411
+ " # dataset_text_field=\"text\", # Name of the column containing the text data\n",
412
+ " # tokenizer=tokenizer,\n",
413
+ " args=training_args,\n",
414
+ " # packing=False, # Whether to pack multiple short examples into one longer sequence to improve efficiency\n",
415
+ " # max_seq_length=512, # Max sequence length to use for training\n",
416
+ ")\n",
417
+ "\n",
418
+ "print(\"Starting finetuning...\")\n",
419
+ "trainer.train()\n",
420
+ "print(\"Finetuning complete!\")\n",
421
+ "\n",
422
+ "# --- 6. (Optional) Save the finetuned model ---\n",
423
+ "# trainer.save_model(\"./gemma_finetuned_model\")\n",
424
+ "\n",
425
+ "# --- 7. (Optional) Merge LoRA adapters with the base model for inference ---\n",
426
+ "# from peft import AutoPeftModelForCausalLM\n",
427
+ "# merged_model = AutoPeftModelForCausalLM.from_pretrained(\n",
428
+ "# \"./gemma_finetuned_model\",\n",
429
+ "# device_map=\"auto\",\n",
430
+ "# torch_dtype=torch.bfloat16 # or torch.float16 depending on your hardware\n",
431
+ "# )\n",
432
+ "# merged_model.save_pretrained(\"gemma_merged_model\", safe_serialization=True)\n",
433
+ "# tokenizer.save_pretrained(\"gemma_merged_model\")\n"
434
+ ]
435
+ }
436
+ ],
437
+ "metadata": {
438
+ "accelerator": "GPU",
439
+ "colab": {
440
+ "gpuType": "T4",
441
+ "machine_shape": "hm"
442
+ },
443
+ "kaggle": {
444
+ "accelerator": "gpu"
445
+ },
446
+ "kernelspec": {
447
+ "display_name": "Python 3",
448
+ "language": "python",
449
+ "name": "python3"
450
+ },
451
+ "language_info": {
452
+ "codemirror_mode": {
453
+ "name": "ipython",
454
+ "version": 3
455
+ },
456
+ "file_extension": ".py",
457
+ "mimetype": "text/x-python",
458
+ "name": "python",
459
+ "nbconvert_exporter": "python",
460
+ "pygments_lexer": "ipython3",
461
+ "version": "3.12.13"
462
+ }
463
+ },
464
+ "nbformat": 4,
465
+ "nbformat_minor": 4
466
+ }