Subject-Emu-5259 commited on
Commit
7f161c2
·
verified ·
1 Parent(s): 9f9b065

Upload training/train_dpo.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. training/train_dpo.py +74 -17
training/train_dpo.py CHANGED
@@ -23,14 +23,29 @@ try:
23
  except ImportError:
24
  print("Install required packages: pip install transformers peft trl datasets torch")
25
 
 
 
 
 
 
 
 
 
 
 
 
26
  # Configuration
27
  @dataclass
28
  class DPOTrainingConfig:
29
  """DPO training configuration"""
30
  base_model: str = "HuggingFaceTB/SmolLM2-360M-Instruct"
31
- dataset_path: str = "/home/workspace/Projects/NeuralAI/data/train_dpo_v7.jsonl"
32
- output_dir: str = "/home/workspace/Projects/NeuralAI/checkpoints/dpo_model_v7"
33
  adapter_path: str = "" # Path to existing adapter if continuing training
 
 
 
 
34
 
35
  # DPO parameters
36
  beta: float = 0.1 # KL penalty coefficient
@@ -39,15 +54,20 @@ class DPOTrainingConfig:
39
  gradient_accumulation_steps: int = 4
40
  max_length: int = 512
41
  max_prompt_length: int = 256
42
- epochs: int = 1
43
 
 
 
 
 
 
44
  # Optimization
45
  warmup_ratio: float = 0.1
46
  weight_decay: float = 0.01
47
  lr_scheduler: str = "cosine"
48
 
49
  # Device
50
- device: str = "cuda" if torch.cuda.is_available() else "cpu"
51
 
52
 
53
  class DPODatasetBuilder:
@@ -263,16 +283,30 @@ def train_dpo(config: DPOTrainingConfig):
263
 
264
  # Load tokenizer
265
  tokenizer = AutoTokenizer.from_pretrained(config.base_model)
266
- tokenizer.pad_token = tokenizer.eos_token
 
267
 
268
  # Load base model with memory optimization
 
269
  model = AutoModelForCausalLM.from_pretrained(
270
  config.base_model,
271
- torch_dtype=torch.float32, # Use float32 for CPU
272
- device_map=None, # Manual device placement
273
  ).to(config.device)
274
 
275
- # Load existing adapter if available
 
 
 
 
 
 
 
 
 
 
 
 
276
  if config.adapter_path and Path(config.adapter_path).exists():
277
  print(f"Loading adapter from {config.adapter_path}")
278
  model = PeftModel.from_pretrained(model, str(config.adapter_path), is_trainable=True)
@@ -324,12 +358,16 @@ def train_dpo(config: DPOTrainingConfig):
324
  gradient_accumulation_steps=config.gradient_accumulation_steps,
325
  use_cpu=(config.device == "cpu"),
326
  max_length=config.max_length,
 
327
  num_train_epochs=config.epochs,
328
  warmup_ratio=config.warmup_ratio,
329
  weight_decay=config.weight_decay,
330
  lr_scheduler_type=config.lr_scheduler,
331
  save_strategy="epoch",
332
  logging_steps=1,
 
 
 
333
  )
334
 
335
  # Create trainer
@@ -345,11 +383,19 @@ def train_dpo(config: DPOTrainingConfig):
345
  print(f"Starting DPO training on {len(dataset)} pairs...")
346
  trainer.train()
347
 
348
- # Save
349
- trainer.save_model(config.output_dir)
 
350
  tokenizer.save_pretrained(config.output_dir)
351
 
352
- print(f"DPO model saved to {config.output_dir}")
 
 
 
 
 
 
 
353
 
354
  return trainer
355
 
@@ -358,14 +404,21 @@ def main():
358
  """Main entry point"""
359
  config = DPOTrainingConfig()
360
 
361
- # Check if running interactively
362
  import argparse
363
- parser = argparse.ArgumentParser(description="DPO Training")
364
  parser.add_argument("--generate-only", action="store_true", help="Only generate preference dataset")
365
- parser.add_argument("--beta", type=float, default=0.1)
366
- parser.add_argument("--epochs", type=int, default=3)
367
- parser.add_argument("--lr", type=float, default=5e-5)
368
- parser.add_argument("--data", type=str, default="/home/workspace/Projects/NeuralAI/data/train_dpo_v8.jsonl")
 
 
 
 
 
 
 
 
369
  args = parser.parse_args()
370
 
371
  if args.generate_only:
@@ -378,6 +431,10 @@ def main():
378
  config.epochs = args.epochs
379
  config.learning_rate = args.lr
380
  config.dataset_path = args.data
 
 
 
 
381
 
382
  train_dpo(config)
383
 
 
23
  except ImportError:
24
  print("Install required packages: pip install transformers peft trl datasets torch")
25
 
26
+ # Resolve repo root so paths work on any machine (macOS, Linux, etc.)
27
+ REPO_ROOT = Path(__file__).resolve().parent.parent
28
+
29
+ def detect_device() -> str:
30
+ """Pick the best available accelerator."""
31
+ if torch.cuda.is_available():
32
+ return "cuda"
33
+ if getattr(torch.backends, "mps", None) is not None and torch.backends.mps.is_available():
34
+ return "mps"
35
+ return "cpu"
36
+
37
  # Configuration
38
  @dataclass
39
  class DPOTrainingConfig:
40
  """DPO training configuration"""
41
  base_model: str = "HuggingFaceTB/SmolLM2-360M-Instruct"
42
+ dataset_path: str = str(REPO_ROOT / "data" / "train_dpo_v14.jsonl")
43
+ output_dir: str = str(REPO_ROOT / "checkpoints" / "dpo_model_v14")
44
  adapter_path: str = "" # Path to existing adapter if continuing training
45
+
46
+ # Hugging Face upload (set push_to_hub=True to auto-sync after training)
47
+ push_to_hub: bool = False
48
+ hub_repo: str = "Subject-Emu-5259/NeuralAI"
49
 
50
  # DPO parameters
51
  beta: float = 0.1 # KL penalty coefficient
 
54
  gradient_accumulation_steps: int = 4
55
  max_length: int = 512
56
  max_prompt_length: int = 256
57
+ epochs: int = 3
58
 
59
+ # LoRA (produces a small adapter compatible with the deployed demo)
60
+ lora_r: int = 16
61
+ lora_alpha: int = 32
62
+ lora_dropout: float = 0.05
63
+
64
  # Optimization
65
  warmup_ratio: float = 0.1
66
  weight_decay: float = 0.01
67
  lr_scheduler: str = "cosine"
68
 
69
  # Device
70
+ device: str = detect_device()
71
 
72
 
73
  class DPODatasetBuilder:
 
283
 
284
  # Load tokenizer
285
  tokenizer = AutoTokenizer.from_pretrained(config.base_model)
286
+ if tokenizer.pad_token is None:
287
+ tokenizer.pad_token = tokenizer.eos_token
288
 
289
  # Load base model with memory optimization
290
+ dtype = torch.float32 if config.device == "cpu" else torch.bfloat16
291
  model = AutoModelForCausalLM.from_pretrained(
292
  config.base_model,
293
+ torch_dtype=dtype,
294
+ device_map=None,
295
  ).to(config.device)
296
 
297
+ # Wrap in LoRA so the output is a small adapter (matches the deployed demo)
298
+ lora_config = LoraConfig(
299
+ r=config.lora_r,
300
+ lora_alpha=config.lora_alpha,
301
+ lora_dropout=config.lora_dropout,
302
+ target_modules="all-linear",
303
+ bias="none",
304
+ task_type="CAUSAL_LM",
305
+ )
306
+ model = PeftModel(model, lora_config)
307
+ model.print_trainable_parameters()
308
+
309
+ # Load existing adapter if available (continue training)
310
  if config.adapter_path and Path(config.adapter_path).exists():
311
  print(f"Loading adapter from {config.adapter_path}")
312
  model = PeftModel.from_pretrained(model, str(config.adapter_path), is_trainable=True)
 
358
  gradient_accumulation_steps=config.gradient_accumulation_steps,
359
  use_cpu=(config.device == "cpu"),
360
  max_length=config.max_length,
361
+ max_prompt_length=config.max_prompt_length,
362
  num_train_epochs=config.epochs,
363
  warmup_ratio=config.warmup_ratio,
364
  weight_decay=config.weight_decay,
365
  lr_scheduler_type=config.lr_scheduler,
366
  save_strategy="epoch",
367
  logging_steps=1,
368
+ report_to="none",
369
+ push_to_hub=config.push_to_hub,
370
+ hub_model_id=config.hub_repo if config.push_to_hub else None,
371
  )
372
 
373
  # Create trainer
 
383
  print(f"Starting DPO training on {len(dataset)} pairs...")
384
  trainer.train()
385
 
386
+ # Save the LoRA adapter (not the full base model)
387
+ Path(config.output_dir).mkdir(parents=True, exist_ok=True)
388
+ model.save_pretrained(config.output_dir)
389
  tokenizer.save_pretrained(config.output_dir)
390
 
391
+ print(f"DPO LoRA adapter saved to {config.output_dir}")
392
+
393
+ # Optionally push the adapter straight to the Hub
394
+ if config.push_to_hub:
395
+ print(f"Pushing adapter to Hugging Face: {config.hub_repo}")
396
+ model.push_to_hub(config.hub_repo, commit_message="DPO LoRA update")
397
+ tokenizer.push_to_hub(config.hub_repo, commit_message="DPO LoRA update")
398
+ print("✅ Adapter pushed to Hugging Face.")
399
 
400
  return trainer
401
 
 
404
  """Main entry point"""
405
  config = DPOTrainingConfig()
406
 
 
407
  import argparse
408
+ parser = argparse.ArgumentParser(description="NeuralAI DPO Training")
409
  parser.add_argument("--generate-only", action="store_true", help="Only generate preference dataset")
410
+ parser.add_argument("--beta", type=float, default=config.beta)
411
+ parser.add_argument("--epochs", type=int, default=config.epochs)
412
+ parser.add_argument("--lr", type=float, default=config.learning_rate)
413
+ parser.add_argument("--data", type=str, default=config.dataset_path,
414
+ help="Path to DPO jsonl (prompt/chosen/rejected)")
415
+ parser.add_argument("--output", type=str, default=config.output_dir,
416
+ help="Where to save the LoRA adapter")
417
+ parser.add_argument("--adapter", type=str, default="",
418
+ help="Existing adapter dir to continue training from")
419
+ parser.add_argument("--push", action="store_true",
420
+ help="Push the trained adapter to the Hugging Face Hub")
421
+ parser.add_argument("--hub-repo", type=str, default=config.hub_repo)
422
  args = parser.parse_args()
423
 
424
  if args.generate_only:
 
431
  config.epochs = args.epochs
432
  config.learning_rate = args.lr
433
  config.dataset_path = args.data
434
+ config.output_dir = args.output
435
+ config.adapter_path = args.adapter
436
+ config.push_to_hub = args.push
437
+ config.hub_repo = args.hub_repo
438
 
439
  train_dpo(config)
440