Fine-Tuning de LLMs: Cómo Entrenar tu Propio Modelo [Tutorial 2026]
Aprende a hacer fine-tuning de LLMs paso a paso. Tutorial con código Python, datasets, y cómo crear un modelo personalizado para tu negocio.
Fine-Tuning de LLMs: Cómo Entrenar tu Propio Modelo [Tutorial 2026]
El fine-tuning te permite especializar un LLM en tu dominio específico. En lugar de depender de prompts complejos, entrenas el modelo para que entienda tu vocabulario, estilo y casos de uso particulares.
¿Cuándo Hacer Fine-Tuning?
Sí Hacer Fine-Tuning Si:
- Tienes un dominio muy específico (legal, médico, técnico)
- Necesitas un estilo o tono consistente
- El modelo debe seguir un formato específico siempre
- Tienes miles de ejemplos de interacciones ideales
- Los prompts están demasiado largos y costosos
No Hacer Fine-Tuning Si:
- Puedes lograr el resultado con buenos prompts
- Tienes menos de 100 ejemplos
- El conocimiento que necesitas es público y actual
- Necesitas que el modelo acceda a datos en tiempo real
Alternativas al Fine-Tuning
| Método | Cuándo Usarlo |
|---|---|
| Prompt engineering | Primero siempre |
| Few-shot prompting | Ejemplos en el prompt |
| RAG | Datos que cambian frecuentemente |
| Fine-tuning | Comportamiento/estilo consistente |
Opciones de Fine-Tuning en 2026
1. OpenAI Fine-Tuning (GPT-4o, GPT-4o-mini)
| Aspecto | Detalle |
|---|---|
| Modelo base | GPT-4o-mini, GPT-4o |
| Mínimo ejemplos | 10 (recomendado: 50-100) |
| Formato | JSONL con messages |
| Precio training | $25/M tokens (4o-mini) |
| Precio inference | 2x modelo base |
2. Anthropic Fine-Tuning (Claude)
| Aspecto | Detalle |
|---|---|
| Disponibilidad | Solo Enterprise |
| Proceso | Contactar ventas |
| Mínimo ejemplos | 1000+ recomendado |
3. Open Source (Llama, Mistral)
| Aspecto | Detalle |
|---|---|
| Modelos | Llama 3.2, Mistral, Qwen |
| Herramientas | Hugging Face, Axolotl |
| Hardware | GPU 24GB+ (A100, 4090) |
| Técnicas | LoRA, QLoRA, Full fine-tune |
Tutorial: Fine-Tuning con OpenAI
Paso 1: Preparar Dataset
El formato JSONL requiere conversaciones completas:
1{"messages": [{"role": "system", "content": "Eres un asistente de soporte técnico de SoftwareCorp."}, {"role": "user", "content": "No puedo iniciar sesión"}, {"role": "assistant", "content": "Entiendo que tienes problemas para acceder. Vamos a solucionarlo:\n\n1. Verifica que usas el email correcto\n2. Prueba 'Olvidé contraseña'\n3. Limpia cookies del navegador\n\n¿Cuál de estos pasos has intentado?"}]}2{"messages": [{"role": "system", "content": "Eres un asistente de soporte técnico de SoftwareCorp."}, {"role": "user", "content": "La app va muy lenta"}, {"role": "assistant", "content": "Vamos a optimizar el rendimiento:\n\n1. Cierra otras aplicaciones\n2. Actualiza a la última versión\n3. Reinicia el dispositivo\n\n¿Qué versión de la app tienes instalada?"}]}
Paso 2: Validar Dataset
1import json2 3def validate_jsonl(file_path):4 errors = []5 with open(file_path, 'r') as f:6 for i, line in enumerate(f, 1):7 try:8 data = json.loads(line)9 if 'messages' not in data:10 errors.append(f"Línea {i}: Falta 'messages'")11 for msg in data['messages']:12 if 'role' not in msg or 'content' not in msg:13 errors.append(f"Línea {i}: Mensaje mal formado")14 except json.JSONDecodeError:15 errors.append(f"Línea {i}: JSON inválido")16 return errors17 18errors = validate_jsonl('training_data.jsonl')19if errors:20 print("Errores encontrados:")21 for e in errors:22 print(e)23else:24 print("Dataset válido!")
Paso 3: Subir Dataset
1from openai import OpenAI2 3client = OpenAI()4 5# Subir archivo6file = client.files.create(7 file=open("training_data.jsonl", "rb"),8 purpose="fine-tune"9)10 11print(f"Archivo subido: {file.id}")
Paso 4: Crear Fine-Tuning Job
1job = client.fine_tuning.jobs.create(2 training_file=file.id,3 model="gpt-4o-mini-2024-07-18",4 hyperparameters={5 "n_epochs": 3,6 "batch_size": 1,7 "learning_rate_multiplier": 1.88 }9)10 11print(f"Job creado: {job.id}")
Paso 5: Monitorear Progreso
1import time2 3while True:4 job_status = client.fine_tuning.jobs.retrieve(job.id)5 print(f"Status: {job_status.status}")6 7 if job_status.status in ['succeeded', 'failed']:8 break9 10 time.sleep(60)11 12if job_status.status == 'succeeded':13 print(f"Modelo listo: {job_status.fine_tuned_model}")
Paso 6: Usar el Modelo
1response = client.chat.completions.create(2 model=job_status.fine_tuned_model, # ft:gpt-4o-mini-2024-07-18:org:custom:id3 messages=[4 {"role": "system", "content": "Eres un asistente de soporte técnico de SoftwareCorp."},5 {"role": "user", "content": "Mi cuenta está bloqueada"}6 ]7)8 9print(response.choices[0].message.content)
Tutorial: Fine-Tuning Open Source con LoRA
¿Qué es LoRA?
LoRA (Low-Rank Adaptation) entrena solo una pequeña parte del modelo, reduciendo:
- Memoria necesaria: 4-8GB en vez de 80GB
- Tiempo de entrenamiento: horas en vez de días
- Costo: GPU consumer vs cluster
Setup del Entorno
1# Crear entorno2python -m venv llm-finetune3source llm-finetune/bin/activate4 5# Instalar dependencias6pip install torch transformers datasets peft accelerate bitsandbytes7pip install trl wandb
Código de Fine-Tuning con Llama
1import torch2from datasets import load_dataset3from transformers import (4 AutoModelForCausalLM,5 AutoTokenizer,6 BitsAndBytesConfig,7 TrainingArguments8)9from peft import LoraConfig, get_peft_model10from trl import SFTTrainer11 12# Configuración de cuantización (4-bit para ahorrar memoria)13bnb_config = BitsAndBytesConfig(14 load_in_4bit=True,15 bnb_4bit_quant_type="nf4",16 bnb_4bit_compute_dtype=torch.float1617)18 19# Cargar modelo base20model_name = "meta-llama/Llama-3.2-8B-Instruct"21model = AutoModelForCausalLM.from_pretrained(22 model_name,23 quantization_config=bnb_config,24 device_map="auto"25)26 27tokenizer = AutoTokenizer.from_pretrained(model_name)28tokenizer.pad_token = tokenizer.eos_token29 30# Configuración LoRA31lora_config = LoraConfig(32 r=16, # Rank33 lora_alpha=32,34 target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],35 lora_dropout=0.05,36 bias="none",37 task_type="CAUSAL_LM"38)39 40model = get_peft_model(model, lora_config)41 42# Cargar dataset (formato: {"text": "### User: pregunta\n### Assistant: respuesta"})43dataset = load_dataset("json", data_files="training_data.json")44 45# Argumentos de entrenamiento46training_args = TrainingArguments(47 output_dir="./llama-finetuned",48 num_train_epochs=3,49 per_device_train_batch_size=4,50 gradient_accumulation_steps=4,51 learning_rate=2e-4,52 fp16=True,53 logging_steps=10,54 save_strategy="epoch"55)56 57# Trainer58trainer = SFTTrainer(59 model=model,60 train_dataset=dataset["train"],61 tokenizer=tokenizer,62 args=training_args,63 max_seq_length=204864)65 66# Entrenar67trainer.train()68 69# Guardar modelo70trainer.save_model("./llama-finetuned-final")
Usar el Modelo Fine-Tuned
1from peft import PeftModel2 3# Cargar modelo base + adaptador LoRA4base_model = AutoModelForCausalLM.from_pretrained(5 "meta-llama/Llama-3.2-8B-Instruct",6 device_map="auto",7 torch_dtype=torch.float168)9 10model = PeftModel.from_pretrained(base_model, "./llama-finetuned-final")11 12# Generar respuesta13prompt = "### User: ¿Cómo reseteo mi contraseña?\n### Assistant:"14inputs = tokenizer(prompt, return_tensors="pt").to("cuda")15 16outputs = model.generate(**inputs, max_new_tokens=200)17print(tokenizer.decode(outputs[0], skip_special_tokens=True))
Preparar Datasets de Calidad
Estructura de Datos Ideal
1{2 "instruction": "Responde como agente de soporte de SoftwareCorp",3 "input": "Mi factura tiene un error",4 "output": "Lamento el inconveniente con tu factura. Para corregirlo necesito:\n\n1. Número de factura\n2. Descripción del error\n3. Datos correctos\n\n¿Puedes proporcionarme estos datos?"5}
Fuentes de Datos
- Conversaciones reales de tu equipo de soporte
- FAQs convertidas a formato conversacional
- Documentación adaptada a Q&A
- Datos sintéticos generados con GPT-4
Generar Datos Sintéticos
1from openai import OpenAI2 3client = OpenAI()4 5def generate_training_example(topic):6 response = client.chat.completions.create(7 model="gpt-4o",8 messages=[9 {"role": "system", "content": """Genera un ejemplo de conversación10 de soporte técnico para SoftwareCorp sobre el tema dado.11 Formato JSON: {"user": "...", "assistant": "..."}"""},12 {"role": "user", "content": f"Tema: {topic}"}13 ]14 )15 return response.choices[0].message.content16 17topics = [18 "problema de login",19 "facturación incorrecta",20 "app lenta",21 "cancelar suscripción",22 "actualizar plan"23]24 25examples = [generate_training_example(t) for t in topics]
Mejores Prácticas
1. Calidad > Cantidad
- 100 ejemplos excelentes > 1000 ejemplos mediocres
- Revisa manualmente cada ejemplo
- Elimina duplicados y contradicciones
2. Diversidad de Ejemplos
- Cubre todos los casos de uso
- Incluye variaciones de la misma pregunta
- Añade casos edge
3. Consistencia de Formato
- Mismo tono en todas las respuestas
- Estructura similar (saludo, pasos, cierre)
- Longitud consistente
4. Hiperparámetros
| Parámetro | Valor Recomendado | Efecto |
|---|---|---|
| Epochs | 2-4 | Más = overfitting |
| Learning rate | 1e-5 a 2e-4 | Más alto = inestable |
| Batch size | 4-16 | Depende de GPU |
| LoRA rank | 8-64 | Más = más capacidad |
5. Evaluación
1# Métricas a evaluar2test_cases = [3 {"input": "No puedo acceder", "expected_topics": ["login", "contraseña"]},4 {"input": "Cobro incorrecto", "expected_topics": ["factura", "reembolso"]}5]6 7def evaluate_model(model, test_cases):8 results = []9 for case in test_cases:10 response = model.generate(case["input"])11 # Evaluar si cubre los temas esperados12 coverage = sum(1 for t in case["expected_topics"] if t in response.lower())13 results.append(coverage / len(case["expected_topics"]))14 return sum(results) / len(results)
Costos Estimados
OpenAI Fine-Tuning
| Concepto | GPT-4o-mini | GPT-4o |
|---|---|---|
| Training | $25/M tokens | $100/M tokens |
| Inference | $0.60/M input | $6/M input |
| 1000 ejemplos (~500K tokens) | ~$12.50 | ~$50 |
Open Source (Cloud GPU)
| Proveedor | GPU | Precio/hora | Para 8B model |
|---|---|---|---|
| RunPod | A100 40GB | $1.69 | ~$5-10 total |
| Lambda Labs | A100 80GB | $1.29 | ~$4-8 total |
| Vast.ai | 4090 | $0.40 | ~$2-5 total |
Conclusión
El fine-tuning es poderoso pero no siempre necesario. Antes de invertir tiempo y dinero:
- Prueba prompt engineering - A menudo es suficiente
- Considera RAG - Para datos que cambian
- Evalúa el ROI - ¿Justifica el costo?
Si decides hacer fine-tuning:
- Empieza con OpenAI (más fácil)
- Prepara datos de calidad
- Itera basándote en evaluaciones
- Considera open source para escalar
Recursos relacionados:
¿Listo para poner tu proyecto en producción?
Si estás siguiendo este tutorial, necesitas un servidor donde desplegarlo. Yo uso Hostinger para mis proyectos porque el panel es intuitivo, los VPS van con SSD NVMe, y a 4,99€/mes no hay nada comparable en relación calidad-precio.
* Enlace de afiliado. Si contratas a través de este enlace, nos ayudas a mantener este contenido gratuito.
Posts Relacionados
Consultoría IA en San Sebastián (Donostia): Agentes, Automatización y Modelos Privados para Empresas [2026]
Guía completa de servicios de inteligencia artificial en San Sebastián: agentes IA, automatización, modelos privados y consultoría para empresas vascas en 2026.
Kit Digital 2026 para IA: Cómo Solicitar Hasta 12.000€ para tu PYME Paso a Paso
Tutorial paso a paso para solicitar el Kit Digital 2026 con soluciones de IA. Requisitos, cuantías por segmento (hasta 12.000€), agentes digitalizadores y errores que rechazan tu solicitud.
Formación en Claude Code para Empresas en España: Proveedores, Precios y Qué Esperar [2026]
Guía de formación en Claude Code para empresas españolas: proveedores, precios (desde 4.000€), programas in-company, duración y resultados esperados.
Javier Santos Criado
Consultor de IA y Automatización | Fundador de Javadex
Experto en implementación de soluciones de Inteligencia Artificial para empresas. Especializado en automatización con n8n, integración de LLMs, y desarrollo de agentes IA.
Lleva tu proyecto a producción
Hosting web desde 2,99€/mes o VPS con SSD NVMe desde 4,99€/mes. Panel intuitivo, IP dedicada y soporte 24/7 en español.
¿Quieres más contenido de IA?
Explora nuestras comparativas y guías