#!/usr/bin/env python3
"""
Bitcoin AI Fine-Tuning Script
CPU-optimized QLoRA fine-tuning for Bitcoin operations assistant.
"""
import os
import json
import torch
from pathlib import Path
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments,
)
from peft import (
LoraConfig,
get_peft_model,
prepare_model_for_kbit_training,
)
from datasets import Dataset
# Configuration
MODEL_NAME = "Qwen/Qwen2.5-7B-Instruct"
OUTPUT_DIR = Path(__file__).parent.parent / "output"
DATA_DIR = Path(__file__).parent.parent / "data" / "bitcoin_finetuning.json"
MAX_STEPS = 1000 # Adjust based on dataset size and time available
def load_model_cpu():
"""Load model optimized for CPU inference/training."""
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float32,
bnb_4bit_use_double_quant=True,
)
print("Loading base model (this may take a while on CPU)...")
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
quantization_config=bnb_config,
device_map="cpu",
torch_dtype=torch.float32,
)
model = prepare_model_for_kbit_training(model)
return model
def add_lora(model):
"""Add LoRA adapters for efficient fine-tuning."""
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
return get_peft_model(model, lora_config)
def prepare_dataset():
"""Load and format training data."""
if not DATA_DIR.exists():
raise FileNotFoundError(f"Training data not found: {DATA_DIR}")
with open(DATA_DIR, 'r') as f:
data = json.load(f)
# Convert to HuggingFace Dataset format
dataset = Dataset.from_list(data)
return dataset
def train():
"""Run the fine-tuning process."""
print("Starting Bitcoin AI fine-tuning...")
print(f"Base model: {MODEL_NAME}")
print(f"Training steps: {MAX_STEPS}")
# Load components
model = load_model_cpu()
model = add_lora(model)
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
dataset = prepare_dataset()
# Training arguments optimized for CPU
training_args = TrainingArguments(
output_dir=str(OUTPUT_DIR),
num_train_epochs=1,
max_steps=MAX_STEPS,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
learning_rate=2e-4,
fp16=False,
bf16=False,
logging_steps=10,
save_steps=100,
save_total_limit=3,
optim="adamw_torch",
warmup_ratio=0.1,
logging_dir=str(OUTPUT_DIR / "logs"),
report_to="none",
)
print("Configuration ready. Starting training...")
print("This will run on CPU and take ~7-14 days")
# TODO: Implement actual training loop with Trainer
# This is the skeleton - will be fleshed out with proper tokenization
if __name__ == "__main__":
train()