fivetech commited on
Commit
72098dc
·
verified ·
1 Parent(s): 0c0218c

Upload train_unsloth.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. train_unsloth.py +171 -0
train_unsloth.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Harbour Fine-tuning Script for Qwen3.6-35B-A3B (MoE)
4
+ Uses Unsloth + LoRA with GGUF quantized model
5
+ Optimized for CPU with 121GB RAM
6
+ """
7
+
8
+ import json
9
+ import torch
10
+ from pathlib import Path
11
+ from datasets import Dataset
12
+ from unsloth import FastLanguageModel
13
+ from trl import SFTTrainer
14
+ from transformers import TrainingArguments
15
+
16
+ # Configuration
17
+ MODEL_NAME = "unsloth/Qwen3.6-35B-A3B-GGUF"
18
+ MODEL_FILE = "Qwen3.6-35B-A3B-UD-Q4_K_M.gguf"
19
+ TRAIN_FILE = Path("/home/fivetech/finetune/harbour_train.jsonl")
20
+ VAL_FILE = Path("/home/fivetech/finetune/harbour_val.jsonl")
21
+ OUTPUT_DIR = Path("/home/fivetech/finetune/output")
22
+ MAX_SEQ_LENGTH = 2048
23
+
24
+ print("=" * 60)
25
+ print("Harbour Fine-tuning - Qwen3.6-35B-A3B (MoE) with Unsloth + LoRA")
26
+ print("=" * 60)
27
+
28
+ # 1. Load model from GGUF
29
+ print("\n1. Loading model from GGUF (Q4_K_M)...")
30
+ model, tokenizer = FastLanguageModel.from_pretrained(
31
+ model_name=MODEL_NAME,
32
+ gguf_file=MODEL_FILE,
33
+ max_seq_length=MAX_SEQ_LENGTH,
34
+ load_in_4bit=True,
35
+ dtype=None,
36
+ )
37
+
38
+ # 2. LoRA configuration
39
+ print("2. Configuring LoRA...")
40
+ model = FastLanguageModel.get_peft_model(
41
+ model,
42
+ r=16,
43
+ lora_alpha=32,
44
+ lora_dropout=0.05,
45
+ target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
46
+ "gate_proj", "up_proj", "down_proj"],
47
+ bias="none",
48
+ use_gradient_checkpointing="unsloth",
49
+ random_state=42,
50
+ )
51
+
52
+ # 3. Load dataset
53
+ print("3. Loading dataset...")
54
+
55
+ def load_jsonl(path):
56
+ data = []
57
+ with open(path) as f:
58
+ for line in f:
59
+ data.append(json.loads(line))
60
+ return data
61
+
62
+ train_data = load_jsonl(TRAIN_FILE)
63
+ val_data = load_jsonl(VAL_FILE)
64
+
65
+ print(f" Train: {len(train_data)} entries")
66
+ print(f" Val: {len(val_data)} entries")
67
+
68
+ # 4. Format conversations
69
+ print("4. Formatting conversations...")
70
+
71
+ def format_conversation(entry):
72
+ messages = entry["messages"]
73
+ text = tokenizer.apply_chat_template(
74
+ messages,
75
+ tokenize=False,
76
+ add_generation_prompt=False,
77
+ )
78
+ return {"text": text}
79
+
80
+ train_dataset = Dataset.from_list([format_conversation(e) for e in train_data])
81
+ val_dataset = Dataset.from_list([format_conversation(e) for e in val_data])
82
+
83
+ # 5. Tokenize
84
+ print("5. Tokenizing...")
85
+
86
+ def tokenize_function(examples):
87
+ return tokenizer(
88
+ examples["text"],
89
+ truncation=True,
90
+ max_length=MAX_SEQ_LENGTH,
91
+ padding=False,
92
+ )
93
+
94
+ train_dataset = train_dataset.map(
95
+ tokenize_function,
96
+ batched=True,
97
+ remove_columns=["text"],
98
+ desc="Tokenizing train",
99
+ )
100
+ val_dataset = val_dataset.map(
101
+ tokenize_function,
102
+ batched=True,
103
+ remove_columns=["text"],
104
+ desc="Tokenizing val",
105
+ )
106
+
107
+ print(f" Train tokens: {sum(len(x) for x in train_dataset['input_ids']):,}")
108
+ print(f" Val tokens: {sum(len(x) for x in val_dataset['input_ids']):,}")
109
+
110
+ # 6. Training arguments
111
+ print("6. Setting up training...")
112
+ training_args = TrainingArguments(
113
+ output_dir=str(OUTPUT_DIR),
114
+ num_train_epochs=3,
115
+ per_device_train_batch_size=1,
116
+ gradient_accumulation_steps=16,
117
+ learning_rate=1e-4,
118
+ weight_decay=0.01,
119
+ warmup_ratio=0.1,
120
+ lr_scheduler_type="cosine",
121
+ logging_steps=5,
122
+ save_steps=50,
123
+ save_total_limit=3,
124
+ eval_strategy="steps",
125
+ eval_steps=50,
126
+ load_best_model_at_end=True,
127
+ metric_for_best_model="eval_loss",
128
+ bf16=False,
129
+ fp16=False,
130
+ dataloader_num_workers=1,
131
+ report_to="none",
132
+ remove_unused_columns=False,
133
+ max_grad_norm=1.0,
134
+ optim="adamw_8bit",
135
+ )
136
+
137
+ # 7. Create trainer
138
+ print("7. Creating trainer...")
139
+ trainer = SFTTrainer(
140
+ model=model,
141
+ tokenizer=tokenizer,
142
+ args=training_args,
143
+ train_dataset=train_dataset,
144
+ eval_dataset=val_dataset,
145
+ max_seq_length=MAX_SEQ_LENGTH,
146
+ dataset_text_field="text",
147
+ )
148
+
149
+ # 8. Train
150
+ print("\n8. Starting training...")
151
+ print("=" * 60)
152
+ trainer.train()
153
+
154
+ # 9. Save LoRA adapter
155
+ print("\n9. Saving LoRA adapter...")
156
+ trainer.save_model(str(OUTPUT_DIR / "final"))
157
+ tokenizer.save_pretrained(str(OUTPUT_DIR / "final"))
158
+
159
+ # 10. Export to GGUF (optional)
160
+ print("\n10. Exporting to GGUF...")
161
+ model.save_pretrained_gguf(
162
+ str(OUTPUT_DIR / "gguf"),
163
+ tokenizer,
164
+ quantization_method="q4_k_m",
165
+ )
166
+
167
+ print("\n" + "=" * 60)
168
+ print("Training complete!")
169
+ print(f"LoRA adapter saved to: {OUTPUT_DIR / 'final'}")
170
+ print(f"GGUF model saved to: {OUTPUT_DIR / 'gguf'}")
171
+ print("=" * 60)