himu1780 commited on
Commit
cd3e6b8
Β·
verified Β·
1 Parent(s): 02a89de

Update train.py

Browse files
Files changed (1) hide show
  1. train.py +58 -52
train.py CHANGED
@@ -1,8 +1,8 @@
1
  """
2
  DocuMint Smart Training Pipeline
3
- - Core Adapter (Frozen)
4
- - Skill-wise Adapters
5
- - Safe Continual Learning
6
  """
7
 
8
  import os
@@ -29,8 +29,9 @@ from huggingface_hub import login
29
 
30
  BASE_MODEL = "Qwen/Qwen2-0.5B-Instruct"
31
 
32
- CORE_ADAPTER_REPO = "himu1780/DocuMint-Core"
33
- SKILL_ADAPTER_REPO = "himu1780/DocuMint-Skill" # will be suffixed
 
34
  OUTPUT_DIR = "./lora_output"
35
 
36
  MAX_LENGTH = 512
@@ -77,28 +78,29 @@ def format_example(ex):
77
  )
78
  else:
79
  text = ex.get("text", str(ex))
 
80
  return {"text": text}
81
 
82
 
83
  def prepare_dataset(tokenizer, dataset_name):
84
- ds = load_dataset(dataset_name, split="train")
85
- ds = ds.map(format_example, remove_columns=ds.column_names)
86
 
87
  def tokenize(ex):
88
- out = tokenizer(
89
  ex["text"],
90
  truncation=True,
91
  padding="max_length",
92
  max_length=MAX_LENGTH,
93
  )
94
- out["labels"] = out["input_ids"].copy()
95
- return out
96
 
97
- ds = ds.map(tokenize, remove_columns=["text"])
98
- return ds
99
 
100
 
101
- # ================== MODEL LOADING ==================
102
 
103
  def load_base():
104
  tokenizer = AutoTokenizer.from_pretrained(
@@ -109,7 +111,7 @@ def load_base():
109
 
110
  model = AutoModelForCausalLM.from_pretrained(
111
  BASE_MODEL,
112
- torch_dtype=torch.float32,
113
  device_map="cpu",
114
  trust_remote_code=True,
115
  low_cpu_mem_usage=True,
@@ -117,7 +119,7 @@ def load_base():
117
  return model, tokenizer
118
 
119
 
120
- def build_lora():
121
  return LoraConfig(
122
  r=8,
123
  lora_alpha=16,
@@ -128,37 +130,35 @@ def build_lora():
128
  )
129
 
130
 
131
- # ================== CORE + SKILL LOGIC ==================
132
 
133
  def load_core_adapter(model):
134
- """
135
- Core adapter is ALWAYS frozen.
136
- """
137
- if not os.path.exists(OUTPUT_DIR + "/core"):
138
  raise RuntimeError("Core adapter not found. Train core first.")
139
 
140
- model = PeftModel.from_pretrained(model, OUTPUT_DIR + "/core")
 
 
141
  for p in model.parameters():
142
  p.requires_grad = False
143
 
144
- print("🧠 Core adapter loaded & frozen")
145
  return model
146
 
147
 
148
- def load_or_create_skill_adapter(model, skill_name):
149
- """
150
- Skill adapter is trainable.
151
- """
152
- skill_path = f"{OUTPUT_DIR}/{skill_name}"
153
 
154
- if os.path.exists(skill_path):
155
- print(f"πŸ” Loading existing skill adapter: {skill_name}")
156
  model = PeftModel.from_pretrained(
157
- model, skill_path, is_trainable=True
158
  )
159
  else:
160
- print(f"πŸ†• Creating new skill adapter: {skill_name}")
161
- model = get_peft_model(model, build_lora())
162
 
163
  model.print_trainable_parameters()
164
  return model
@@ -174,18 +174,22 @@ def train_skill(
174
  batch_size: int,
175
  ):
176
  """
177
- Train a skill adapter WITHOUT destroying core knowledge.
 
 
178
  """
179
 
180
  hf_auth()
181
 
182
  model, tokenizer = load_base()
183
 
184
- # Load & freeze core
185
- model = load_core_adapter(model)
 
 
186
 
187
- # Load / create skill adapter
188
- model = load_or_create_skill_adapter(model, skill_name)
189
 
190
  dataset = prepare_dataset(tokenizer, dataset_name)
191
 
@@ -206,7 +210,8 @@ def train_skill(
206
  )
207
 
208
  collator = DataCollatorForLanguageModeling(
209
- tokenizer=tokenizer, mlm=False
 
210
  )
211
 
212
  trainer = Trainer(
@@ -218,31 +223,32 @@ def train_skill(
218
 
219
  trainer.train()
220
 
221
- # Save skill adapter
222
- save_path = f"{OUTPUT_DIR}/{skill_name}"
223
  model.save_pretrained(save_path)
224
  tokenizer.save_pretrained(save_path)
225
 
226
- # Push to HF
227
- model.push_to_hub(f"{SKILL_ADAPTER_REPO}-{skill_name}")
228
- tokenizer.push_to_hub(f"{SKILL_ADAPTER_REPO}-{skill_name}")
 
 
 
 
 
229
 
230
  cleanup()
231
- print(f"βœ… Skill '{skill_name}' trained and saved")
232
 
233
 
234
- # ================== ROUTING (INFERENCE READY) ==================
235
 
236
  def load_for_inference(skill_name: str):
237
- """
238
- Adapter routing:
239
- Base β†’ Core β†’ Skill
240
- """
241
  model, tokenizer = load_base()
242
 
243
- model = PeftModel.from_pretrained(model, CORE_ADAPTER_REPO)
244
  model = PeftModel.from_pretrained(
245
- model, f"{SKILL_ADAPTER_REPO}-{skill_name}"
246
  )
247
 
248
  model.eval()
@@ -254,4 +260,4 @@ def load_for_inference(skill_name: str):
254
 
255
  if __name__ == "__main__":
256
  print("πŸ† DocuMint Smart Training System Ready")
257
- print("Use train_skill() to add new intelligence safely")
 
1
  """
2
  DocuMint Smart Training Pipeline
3
+ - Core adapter (one-time training)
4
+ - Skill-wise adapters (additive learning)
5
+ - Safe continual learning (no destruction)
6
  """
7
 
8
  import os
 
29
 
30
  BASE_MODEL = "Qwen/Qwen2-0.5B-Instruct"
31
 
32
+ CORE_REPO = "himu1780/DocuMint-Core"
33
+ SKILL_REPO_PREFIX = "himu1780/DocuMint-Skill"
34
+
35
  OUTPUT_DIR = "./lora_output"
36
 
37
  MAX_LENGTH = 512
 
78
  )
79
  else:
80
  text = ex.get("text", str(ex))
81
+
82
  return {"text": text}
83
 
84
 
85
  def prepare_dataset(tokenizer, dataset_name):
86
+ dataset = load_dataset(dataset_name, split="train")
87
+ dataset = dataset.map(format_example, remove_columns=dataset.column_names)
88
 
89
  def tokenize(ex):
90
+ tokens = tokenizer(
91
  ex["text"],
92
  truncation=True,
93
  padding="max_length",
94
  max_length=MAX_LENGTH,
95
  )
96
+ tokens["labels"] = tokens["input_ids"].copy()
97
+ return tokens
98
 
99
+ dataset = dataset.map(tokenize, remove_columns=["text"])
100
+ return dataset
101
 
102
 
103
+ # ================== MODEL ==================
104
 
105
  def load_base():
106
  tokenizer = AutoTokenizer.from_pretrained(
 
111
 
112
  model = AutoModelForCausalLM.from_pretrained(
113
  BASE_MODEL,
114
+ torch_dtype=torch.float32, # CPU safe
115
  device_map="cpu",
116
  trust_remote_code=True,
117
  low_cpu_mem_usage=True,
 
119
  return model, tokenizer
120
 
121
 
122
+ def lora_config():
123
  return LoraConfig(
124
  r=8,
125
  lora_alpha=16,
 
130
  )
131
 
132
 
133
+ # ================== ADAPTER LOGIC ==================
134
 
135
  def load_core_adapter(model):
136
+ core_path = os.path.join(OUTPUT_DIR, "core")
137
+
138
+ if not os.path.exists(core_path):
 
139
  raise RuntimeError("Core adapter not found. Train core first.")
140
 
141
+ model = PeftModel.from_pretrained(model, core_path)
142
+
143
+ # Freeze everything
144
  for p in model.parameters():
145
  p.requires_grad = False
146
 
147
+ print("🧠 Core adapter loaded and frozen")
148
  return model
149
 
150
 
151
+ def load_or_create_adapter(model, skill_name):
152
+ adapter_path = os.path.join(OUTPUT_DIR, skill_name)
 
 
 
153
 
154
+ if os.path.exists(adapter_path):
155
+ print(f"πŸ” Loading existing adapter: {skill_name}")
156
  model = PeftModel.from_pretrained(
157
+ model, adapter_path, is_trainable=True
158
  )
159
  else:
160
+ print(f"πŸ†• Creating new adapter: {skill_name}")
161
+ model = get_peft_model(model, lora_config())
162
 
163
  model.print_trainable_parameters()
164
  return model
 
174
  batch_size: int,
175
  ):
176
  """
177
+ skill_name:
178
+ - "core" -> core training (one time)
179
+ - others -> skill training (requires core)
180
  """
181
 
182
  hf_auth()
183
 
184
  model, tokenizer = load_base()
185
 
186
+ # IMPORTANT FIX:
187
+ # Load core ONLY if training a skill
188
+ if skill_name != "core":
189
+ model = load_core_adapter(model)
190
 
191
+ # Load or create adapter
192
+ model = load_or_create_adapter(model, skill_name)
193
 
194
  dataset = prepare_dataset(tokenizer, dataset_name)
195
 
 
210
  )
211
 
212
  collator = DataCollatorForLanguageModeling(
213
+ tokenizer=tokenizer,
214
+ mlm=False,
215
  )
216
 
217
  trainer = Trainer(
 
223
 
224
  trainer.train()
225
 
226
+ # Save locally
227
+ save_path = os.path.join(OUTPUT_DIR, skill_name)
228
  model.save_pretrained(save_path)
229
  tokenizer.save_pretrained(save_path)
230
 
231
+ # Push to Hub
232
+ if skill_name == "core":
233
+ repo = CORE_REPO
234
+ else:
235
+ repo = f"{SKILL_REPO_PREFIX}-{skill_name}"
236
+
237
+ model.push_to_hub(repo)
238
+ tokenizer.push_to_hub(repo)
239
 
240
  cleanup()
241
+ print(f"βœ… Training finished for adapter: {skill_name}")
242
 
243
 
244
+ # ================== ROUTING (INFERENCE) ==================
245
 
246
  def load_for_inference(skill_name: str):
 
 
 
 
247
  model, tokenizer = load_base()
248
 
249
+ model = PeftModel.from_pretrained(model, CORE_REPO)
250
  model = PeftModel.from_pretrained(
251
+ model, f"{SKILL_REPO_PREFIX}-{skill_name}"
252
  )
253
 
254
  model.eval()
 
260
 
261
  if __name__ == "__main__":
262
  print("πŸ† DocuMint Smart Training System Ready")
263
+ print("Use train_skill() to train core or add skills safely")