Files
agenx-lora-training/training/scripts/train.py

124 lines
3.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Train LoRA adapter on Cyron summary dataset.
Uses Hugging Face TRL for SFT training.
"""
import argparse
import os
import yaml
from pathlib import Path
import torch
def train(config_path):
"""Train LoRA adapter using TRL."""
with open(config_path) as f:
config = yaml.safe_load(f)
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments,
)
from peft import (
prepare_model_for_kbit_training,
LoraConfig,
get_peft_model,
)
from trl import SFTTrainer, SFTConfig
print(f"Loading model: {config['base_model']}")
# Load model - let the model's own quantization config handle it
# (Ornith uses CompressedTensors, not BitsAndBytes)
model = AutoModelForCausalLM.from_pretrained(
config["base_model"],
device_map="auto",
torch_dtype=torch.bfloat16,
)
# Add LoRA
lora_config = LoraConfig(
r=config["lora_r"],
lora_alpha=config["lora_alpha"],
lora_dropout=config["lora_dropout"],
target_modules=config["target_modules"],
task_type=config.get("lora_task_type", "CAUSAL_LM"),
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Load tokenizer
tokenizer = AutoTokenizer.from_pretrained(config["base_model"])
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
# Load dataset
from datasets import load_dataset
dataset = load_dataset(
"json",
data_files={
"train": config["dataset"][0]["path"].replace("../", ""),
"test": config["dataset"][0]["path"].replace("../", "").replace("combined_20k.jsonl", "test.jsonl"),
},
)
# Training arguments
training_args = TrainingArguments(
output_dir=config["train_params"]["output_dir"],
num_train_epochs=config["train_params"]["num_train_epochs"],
per_device_train_batch_size=config["train_params"]["per_device_train_batch_size"],
gradient_accumulation_steps=config["train_params"]["gradient_accumulation_steps"],
learning_rate=config["train_params"]["learning_rate"],
lr_scheduler_type=config["train_params"]["lr_scheduler_type"],
weight_decay=config["train_params"]["weight_decay"],
warmup_ratio=config["train_params"]["warmup_ratio"],
max_seq_length=config["train_params"]["max_seq_length"],
logging_steps=config["train_params"]["logging_steps"],
save_steps=config["train_params"]["save_steps"],
save_total_limit=config["train_params"]["save_total_limit"],
evaluation_strategy=config.get("eval_strategy", "steps"),
eval_steps=config.get("eval_steps", 100),
mixed_precision=config.get("mixed_precision", "bf16"),
gradient_checkpointing=config.get("gradient_checkpointing", True),
)
# SFT Trainer
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset["train"],
eval_dataset=dataset["test"],
args=training_args,
max_seq_length=config["train_params"]["max_seq_length"],
)
# Train
print("Starting training...")
trainer.train()
# Save
trainer.save_model(config["train_params"]["output_dir"])
tokenizer.save_pretrained(config["train_params"]["output_dir"])
print(f"Training complete! Model saved to {config['train_params']['output_dir']}")
def main():
parser = argparse.ArgumentParser(description="Train LoRA adapter")
parser.add_argument("--config", type=str, default="configs/llama2-7b-lora.yaml",
help="Training configuration file")
args = parser.parse_args()
train(args.config)
if __name__ == "__main__":
main()