Cómo hacer fine-tuning de un LLM paso a paso
20 de abril de 2025· 5 min read
Esta es la guía que me hubiera gustado tener la primera vez que hice fine-tuning. Sin rodeos, con los errores incluidos.
Antes de empezar: ¿realmente necesitas fine-tuning?
Fine-tuning tiene sentido cuando:
- Necesitas consistencia de formato que el prompting no garantiza
- El comportamiento del modelo no es el correcto después de optimizar el prompt
- Tienes volumen suficiente para que el ahorro de tokens justifique el costo
No tiene sentido cuando el problema es de información (usa RAG) o cuando no has agotado el prompting primero.
Si tienes dudas, lee este artículo sobre cuándo usar fine-tuning vs RAG antes de continuar.
Paso 1: Prepara los datos
Formato requerido por OpenAI
{"messages": [
{"role": "system", "content": "Tu system prompt aquí"},
{"role": "user", "content": "Pregunta del usuario"},
{"role": "assistant", "content": "Respuesta ideal"}
]}
Un archivo JSONL con una entrada por línea. Cada entrada es una conversación completa.
Cuántos ejemplos necesitas
- Mínimo viable: 50 ejemplos (resultados inconsistentes)
- Para resultados decentes: 100-200 ejemplos
- Para comportamiento robusto: 500-1000 ejemplos
- Para casos muy específicos: A veces 50 bien elegidos superan a 500 mediocres
La calidad supera a la cantidad. 100 ejemplos perfectos > 500 mediocres.
Cómo conseguir los datos
Opción 1 — Datos existentes: Si ya tienes conversaciones reales (logs de soporte, Q&A, etc.), filtra los de alta calidad. Son los mejores porque son representativos de uso real.
Opción 2 — Generados por GPT-4: Usa el modelo potente para generar los pares de entrenamiento. Tienes control total del formato pero pueden ser genéricos.
Opción 3 — Escribir a mano: Los mejores para comportamiento muy específico. Los peores en escala.
El approach recomendado: Empieza con un prompt bien diseñado en GPT-4 o Claude, genera 200-300 ejemplos, filtra manualmente los 100 mejores, y ahí tienes tu conjunto inicial.
Criterios de calidad para los ejemplos
Cada ejemplo debe:
- Representar un caso de uso real
- Tener la respuesta exactamente como quieres que sea
- Variar suficientemente del anterior (no copies con mínimas diferencias)
- No contener errores (un ejemplo malo contamina el entrenamiento)
Validar el formato antes de enviar
import json
def validate_training_file(filepath: str) -> None:
errors = []
with open(filepath) as f:
for i, line in enumerate(f):
try:
entry = json.loads(line)
if "messages" not in entry:
errors.append(f"Línea {i}: falta 'messages'")
for msg in entry["messages"]:
if "role" not in msg or "content" not in msg:
errors.append(f"Línea {i}: mensaje sin role o content")
except json.JSONDecodeError:
errors.append(f"Línea {i}: JSON inválido")
if errors:
print("Errores encontrados:")
for e in errors: print(f" {e}")
else:
print(f"✓ {i+1} ejemplos válidos")
Paso 2: Lanza el entrenamiento
Con la API de OpenAI
from openai import OpenAI
client = OpenAI()
# 1. Sube el archivo
with open("training_data.jsonl", "rb") as f:
upload = client.files.create(file=f, purpose="fine-tune")
print(f"File ID: {upload.id}")
# 2. Lanza el job
job = client.fine_tuning.jobs.create(
training_file=upload.id,
model="gpt-4o-mini-2024-07-18",
hyperparameters={
"n_epochs": 3, # Default, generalmente funciona bien
}
)
print(f"Job ID: {job.id}")
Monitoreo del training
# Revisa el estado
import time
while True:
job = client.fine_tuning.jobs.retrieve(job_id)
print(f"Estado: {job.status}")
if job.status in ["succeeded", "failed", "cancelled"]:
break
time.sleep(60)
if job.status == "succeeded":
print(f"Modelo: {job.fine_tuned_model}")
El entrenamiento típicamente tarda 15-60 minutos dependiendo del tamaño del dataset.
Parámetros importantes
n_epochs: Cuántas veces pasa el modelo por todos los datos. 3 es el default y funciona para la mayoría de casos. Si el modelo overfitta (comportamiento demasiado mecánico), reduce a 1-2.
learning_rate_multiplier: Por defecto auto. No toques esto a menos que sepas lo que haces.
Paso 3: Evalúa el modelo resultante
Este paso es el más importante y el más frecuentemente saltado.
Compara contra el modelo base
Ejecuta ambos modelos (el base y el fine-tuned) en tu eval set:
def evaluate_models(test_cases: list, models: list) -> dict:
results = {model: [] for model in models}
for case in test_cases:
for model in models:
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": case["system"]},
{"role": "user", "content": case["input"]}
]
)
results[model].append({
"input": case["input"],
"expected": case["expected"],
"actual": response.choices[0].message.content
})
return results
Qué medir
Consistencia de formato: ¿El modelo fine-tuned respeta siempre el formato requerido?
Calidad del contenido: ¿Las respuestas son mejores, iguales o peores que el base?
Regresiones: ¿Hay tipos de consultas que funcionaban bien y ahora son peores?
Señales de overfitting
- Las respuestas suenan "mecánicas" o demasiado similares a los ejemplos de entrenamiento
- Funciona muy bien en ejemplos parecidos a los de entrenamiento pero mal en casos nuevos
- El modelo "rellena" respuestas con patrones del entrenamiento aunque no sean relevantes
Si hay overfitting: reduce n_epochs o añade más variedad a los datos de entrenamiento.
Paso 4: Decisión de producción
Antes de usar el modelo fine-tuned en producción, verifica:
- [ ] Supera al modelo base en tus métricas clave
- [ ] No tiene regresiones en casos que antes funcionaban bien
- [ ] El ahorro de costo/latencia justifica el mantenimiento
- [ ] Tienes un plan para re-entrenar cuando los datos cambien
El costo de mantenimiento
El mayor coste oculto del fine-tuning no es el entrenamiento inicial: es el re-entrenamiento.
Cuando cambien tus requisitos (y cambiarán), necesitas:
- Actualizar los datos de entrenamiento
- Re-lanzar el entrenamiento
- Re-evaluar el nuevo modelo
- Migrar en producción
Si tus requisitos cambian frecuentemente, el prompting es más ágil.
Checklist antes de hacer fine-tuning
- [ ] He intentado solucionar el problema con prompt engineering primero
- [ ] Tengo al menos 100 ejemplos de alta calidad
- [ ] Tengo un eval set para medir antes y después
- [ ] Entiendo el costo de entrenamiento e inferencia
- [ ] Tengo un plan para mantener el modelo actualizado
Si has marcado todo: procede. Si no: vuelve al paso correspondiente.
Pon en práctica lo que has aprendido
Selector de modelo IA
¿Fine-tuning o RAG? El selector te ayuda a decidir.
Abrir herramienta gratuita →Artículos relacionados
Cómo evaluar si un sistema de IA funciona bien
Los evals (evaluaciones) son la única forma de saber si tu sistema de IA realmente funciona. Aprende cómo diseñar, implementar y automatizar evaluaciones para agentes y asistentes.
Qué es RAG explicado de forma simple
RAG (Retrieval-Augmented Generation) permite a los modelos de IA responder con información actualizada y verificable. Aquí lo explicamos paso a paso, sin jerga innecesaria.
Context Engineering vs Fine-tuning: cuándo usar cada uno
Dos estrategias para mejorar un LLM, objetivos completamente distintos. Guía práctica para decidir qué necesitas según tu caso de uso, datos y presupuesto.
Recibe lo mejor de Contextología
Diseño de contexto, agentes y workflows de IA directamente en tu correo.