Fusion y Exportacion de Modelos
De Adaptador LoRA a Modelo Desplegable
Despues del entrenamiento, tienes un adaptador LoRA — un archivo pequeno (10-100MB) que contiene solo los cambios de pesos aprendidos. Para desplegar, necesitas servir el adaptador junto al modelo base o fusionarlo en un modelo independiente. Esta leccion cubre todas las estrategias de fusion, formatos de exportacion y flujos de publicacion que necesitas.
Estrategias de Fusion LoRA
Fusion Basica: merge_and_unload
El enfoque mas simple y comun. Agrega los pesos LoRA a los pesos del modelo base y elimina las capas LoRA.
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
# Cargar modelo base (en precision completa para fusion)
base_model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B-Instruct",
torch_dtype=torch.float16,
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B-Instruct")
# Cargar adaptador LoRA
model = PeftModel.from_pretrained(base_model, "./output/lora-adapter")
# Fusionar y descargar
merged_model = model.merge_and_unload()
# Guardar el modelo fusionado
merged_model.save_pretrained("./output/merged-model")
tokenizer.save_pretrained("./output/merged-model")
Importante: Al fusionar un adaptador QLoRA, primero debes descuantizar el modelo base. Cargar el modelo base en float16 (no en 4 bits) antes de fusionar evita artefactos de cuantizacion en el modelo final.
Fusion TIES
TIES (TrIM, Elect Sign & Merge) es una estrategia avanzada de fusion para combinar multiples adaptadores LoRA. Resuelve conflictos entre adaptadores recortando valores pequenos, resolviendo conflictos de signo y fusionando los parametros restantes.
from peft import PeftModel, PeftConfig
import torch
# Cargar modelo base
base_model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B-Instruct",
torch_dtype=torch.float16,
device_map="auto",
)
# Fusion TIES con multiples adaptadores
adapters = ["./adapter-legal", "./adapter-medical", "./adapter-finance"]
weights = [0.4, 0.3, 0.3] # Ponderar la contribucion de cada adaptador
density = 0.5 # Mantener el 50% superior de parametros por magnitud
model = PeftModel.from_pretrained(base_model, adapters[0], adapter_name="legal")
model.load_adapter(adapters[1], adapter_name="medical")
model.load_adapter(adapters[2], adapter_name="finance")
# Fusionar usando TIES
model.add_weighted_adapter(
adapters=["legal", "medical", "finance"],
weights=weights,
adapter_name="merged",
combination_type="ties",
density=density,
)
model.set_adapter("merged")
merged = model.merge_and_unload()
Fusion DARE
DARE (Drop And REscale) elimina aleatoriamente parametros antes de fusionar, lo cual puede mejorar la generalizacion al combinar multiples adaptadores:
model.add_weighted_adapter(
adapters=["legal", "medical", "finance"],
weights=weights,
adapter_name="merged",
combination_type="dare_ties", # DARE combinado con TIES
density=0.5,
)
Cuando usar fusion multi-adaptador: Cuando has entrenado adaptadores LoRA separados para diferentes tareas o dominios y quieres crear un modelo unico que combine todas las capacidades.
Formatos de Exportacion
Safetensors (Por Defecto)
El formato estandar para modelos de Hugging Face. Seguro, rapido de cargar y soporta mapeo de memoria:
# Ya se guarda en formato safetensors por defecto
merged_model.save_pretrained("./output/merged-model")
# Crea: model-00001-of-00002.safetensors, model-00002-of-00002.safetensors, etc.
GGUF (para llama.cpp y Ollama)
GGUF es el formato usado por llama.cpp, Ollama, LM Studio y otras herramientas de inferencia local. Incluye cuantizacion integrada para inferencia eficiente en CPU y GPU.
Metodo 1: Usando Unsloth (mas facil)
# Si entrenaste con Unsloth
model.save_pretrained_gguf(
"output/gguf",
tokenizer,
quantization_method="q4_k_m", # Buen balance de calidad y tamano
)
Metodo 2: Usando llama.cpp directamente
# Clonar llama.cpp
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
# Convertir de formato HF a GGUF
python convert_hf_to_gguf.py ../output/merged-model --outfile model-f16.gguf --outtype f16
# Cuantizar a tamanos mas pequenos
./llama-quantize model-f16.gguf model-q4_k_m.gguf Q4_K_M
./llama-quantize model-f16.gguf model-q5_k_m.gguf Q5_K_M
./llama-quantize model-f16.gguf model-q8_0.gguf Q8_0
Metodos de cuantizacion GGUF explicados:
| Metodo | Tamano (7B) | Calidad | Velocidad | Caso de Uso | |--------|------------|---------|-----------|-------------| | Q4_K_M | ~4.1 GB | Buena | Rapida | Mejor balance para la mayoria | | Q5_K_M | ~4.8 GB | Mejor | Rapida | Cuando necesitas mayor calidad | | Q6_K | ~5.5 GB | Muy buena | Media | Tareas sensibles a calidad | | Q8_0 | ~7.2 GB | Casi FP16 | Mas lenta | Cuando la calidad es critica | | F16 | ~14 GB | Referencia | La mas lenta | Referencia / desarrollo |
AWQ (Activation-aware Weight Quantization)
AWQ produce modelos cuantizados a 4 bits optimizados para inferencia en GPU con vLLM:
from awq import AutoAWQForCausalLM
model = AutoAWQForCausalLM.from_pretrained(
"./output/merged-model",
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("./output/merged-model")
# Dataset de calibracion (usa una muestra representativa)
quant_config = {
"zero_point": True,
"q_group_size": 128,
"w_bit": 4,
"version": "GEMM",
}
model.quantize(tokenizer, quant_config=quant_config)
model.save_quantized("./output/merged-model-awq")
tokenizer.save_pretrained("./output/merged-model-awq")
GPTQ
Similar a AWQ pero usa un algoritmo de cuantizacion diferente:
from transformers import GPTQConfig
gptq_config = GPTQConfig(
bits=4,
dataset="c4", # Dataset de calibracion
tokenizer=tokenizer,
)
model = AutoModelForCausalLM.from_pretrained(
"./output/merged-model",
quantization_config=gptq_config,
device_map="auto",
)
model.save_pretrained("./output/merged-model-gptq")
Publicando en Hugging Face Hub
Creando un Model Card
Cada modelo publicado debe tener un model card (README.md) que documente su proposito, detalles de entrenamiento y limitaciones:
card_content = """
---
license: llama3.1
base_model: meta-llama/Llama-3.1-8B-Instruct
tags:
- fine-tuned
- legal
- LoRA
---
# Asistente Legal - Llama 3.1 8B Fine-Tuned
## Descripcion del Modelo
Llama 3.1 8B con fine-tuning para analisis de documentos legales, entrenado con 2,000
ejemplos de revision de contratos, resumen de clausulas y evaluacion de riesgos.
## Detalles de Entrenamiento
- **Modelo base:** meta-llama/Llama-3.1-8B-Instruct
- **Metodo:** QLoRA (4-bit, rango 16, alpha 32)
- **Dataset:** 2,000 ejemplos legales curados
- **Epocas:** 3
- **Hardware:** 1x RTX 3090
## Uso Previsto
Analisis de documentos legales para contratos y acuerdos en ingles.
## Limitaciones
- No sustituye el asesoramiento legal profesional
- Entrenado principalmente en derecho contractual de EE.UU.
- Puede no generalizar a otros sistemas legales
"""
Subiendo al Hub
from huggingface_hub import HfApi
api = HfApi()
# Crear repositorio y subir modelo fusionado
api.create_repo("tu-usuario/legal-llama3-8b", private=False)
merged_model.push_to_hub("tu-usuario/legal-llama3-8b")
tokenizer.push_to_hub("tu-usuario/legal-llama3-8b")
# Subir GGUF separadamente (opcional)
api.upload_file(
path_or_fileobj="output/gguf/model-q4_k_m.gguf",
path_in_repo="legal-llama3-8b-q4_k_m.gguf",
repo_id="tu-usuario/legal-llama3-8b-gguf",
)
Consideraciones de Licencia
Al publicar modelos fine-tuned, debes cumplir con la licencia del modelo base:
- Llama 3.1: Licencia Comunitaria de Meta. Uso comercial permitido. Debe incluir atribucion. Se debe aceptar la licencia para usar.
- Mistral: Apache 2.0. Muy permisiva. Uso comercial permitido.
- Qwen: Apache 2.0 o Licencia Qwen dependiendo de la version.
- Gemma: Terminos de Uso de Google. Uso comercial permitido con restricciones.
Siempre verifica la licencia del modelo base antes de publicar tu version fine-tuned. Tu modelo fine-tuned hereda las restricciones de licencia del modelo base.
Control de Versiones para Modelos
Rastrea tus modelos sistematicamente:
models/
legal-assistant/
v1.0/
adapter/ # Archivos del adaptador LoRA
merged/ # Modelo fusionado completo
gguf/ # Versiones cuantizadas GGUF
eval_results.json # Puntuaciones de evaluacion
training_config.json # Hiperparametros usados
v1.1/
...
Almacena configuraciones de entrenamiento junto a los modelos para poder reproducir cualquier version:
import json
config = {
"base_model": "meta-llama/Llama-3.1-8B-Instruct",
"lora_rank": 16,
"lora_alpha": 32,
"learning_rate": 2e-4,
"epochs": 3,
"dataset": "legal-contracts-v2",
"dataset_size": 2000,
"eval_loss": 0.847,
"eval_win_rate_vs_base": 0.78,
}
with open("models/legal-assistant/v1.0/training_config.json", "w") as f:
json.dump(config, f, indent=2)
En la proxima leccion, tomaremos tu modelo exportado y lo desplegaremos con motores de inferencia de produccion — vLLM para alto rendimiento y Ollama para despliegue local.