Una de las mayores ventajas de PEFT es que solo necesitas guardar los parámetros del adaptador (LoRA), no el modelo base completo. Esto tiene enormes implicaciones prácticas:
Después del entrenamiento, el adaptador LoRA se guarda como pesos adicionales. El modelo base permanece intacto.
# Guardar el adaptador LoRA
model.save_pretrained("./lora_adapter")
# Guardar tokenizer (si se modificó, aunque es raro)
tokenizer.save_pretrained("./lora_adapter")
Esto crea un directorio ./lora_adapter con archivos como:
adapter_config.json — Configuración LoRA (r, alpha, target_modules, etc.)adapter_model.bin — Pesos LoRA (A y B)README.md (opcional) — MetadatosImportante: El modelo base no se guarda aquí. Debes mantener acceso al modelo base original (por ejemplo, desde Hugging Face Hub) para cargar el adaptador posteriormente.
Para usar el adaptador entrenado:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import PeftModel
import torch
# Configuración de cuantización (opcional para inferencia eficiente)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
# Cargar modelo base
model_name = "Qwen/Qwen2.5-0.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto",
trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
# Cargar adaptador LoRA
model = PeftModel.from_pretrained(model, "./lora_adapter")
# El modelo ahora tiene comportamiento especializado
model.eval() # Establecer en modo de evaluación para inferencia
Aunque la carga dinámica de adaptadores es flexible, para despliegue en producción o inferencia más rápida, fusionar pesos LoRA en el modelo base es útil. Esto crea un modelo completo especializado que no requiere infraestructura PEFT durante la inferencia.
# Fusionar adaptador LoRA con modelo base
model = model.merge_and_unload()
# Ahora el modelo es un modelo completo con pesos actualizados
# Guardar como modelo Hugging Face estándar
model.save_pretrained("./merged_model")
tokenizer.save_pretrained("./merged_model")
Advertencia:
- Una vez fusionado, no puedes recargar otro adaptador sin recargar el modelo base original.
- El modelo fusionado ocupa el mismo espacio en disco que el modelo base original (~1GB para Qwen2.5-0.5B en FP16).
- La fusión solo es posible si el modelo está en precisión completa (FP16/BF16). Si está cuantizado a 4 bits, primero descuantiza (requiere más memoria).
# Si el modelo es de 4 bits, primero descuantiza (requiere más VRAM)
model = model.dequantize() # Convierte pesos a BF16/FP16
# Luego fusiona
model = model.merge_and_unload()
# Guardar
model.save_pretrained("./merged_model_full_precision")
Una vez fusionado y guardado, el modelo se comporta como cualquier modelo Hugging Face estándar:
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"./merged_model",
device_map="auto",
trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained("./merged_model", trust_remote_code=True)
# Listo para inferencia sin PEFT!