Volver al Blog
Blog

Fine-Tuning de LLMs: Enseñando a la IA a Hablar Tu Idioma

Aug 17, 2025·8 min read·Shranya Mahna
#custom AI#domain-specific AI#fine-tuning LLMs#language models#personalized AI
Fine-Tuning de LLMs: Enseñando a la IA a Hablar Tu Idioma

Parte 3 de 5: Personalización de Modelos Preentrenados

¡Bienvenido de vuelta! En nuestro artículo anterior, construimos un sistema RAG que da acceso a la IA a tu información específica. Hoy, vamos un paso más allá — vamos a modificar realmente cómo un modelo de IA piensa y responde mediante el ajuste fino. Voy a usar un modelo de código abierto para este ejemplo de demostración.

RAG vs Ajuste Fino: ¿Cuál es la Diferencia?

Piénsalo así:

RAG es como darle a alguien un libro de referencia. Siguen siendo la misma persona, pero ahora tienen acceso a información específica al responder preguntas.

Ajuste fino es como enviar a alguien a un entrenamiento especializado. Realmente estás cambiando cómo piensan y responden en función de tus requisitos específicos.

¿Cuándo Deberías Hacer Ajuste Fino?

El ajuste fino es poderoso, pero no siempre es necesario. Considera el ajuste fino cuando:

  • Necesitas que la IA adopte un tono o estilo específico
  • Tu dominio tiene terminología o conceptos especializados
  • Quieres respuestas consistentes en muchos escenarios diferentes
  • RAG no te está dando la calidad de respuestas que necesitas
  • Tienes suficientes datos de entrenamiento (generalmente cientos de ejemplos)
  • Necesitas que el modelo funcione sin conexión o en entornos aislados

Configurando Tu Entorno

Usaremos Google Colab con una GPU T4 para este tutorial, pero puedes adaptarlo para cualquier entorno compatible con CUDA:

# Install required packages

!pip install bitsandbytes
import os import torch from datasets import Dataset from transformers import ( AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer, BitsAndBytesConfig ) from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, PeftModel

Eligiendo el Modelo Correcto

Para este tutorial, usaremos TinyLlama-1.1B, pero aquí hay algunas opciones excelentes para diferentes necesidades:

# Ultra-light models (good for experimentation)

# model_name = "distilgpt2"                          # 82M parameters

# model_name = "gpt2"                                # 124M parameters

# model_name = "EleutherAI/gpt-neo-125M"            # 125M parameters
# Small but capable models # model_name = "microsoft/DialoGPT-medium" # 355M parameters # model_name = "microsoft/DialoGPT-large" # 762M parameters model_name = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" # 1.1B parameters - choosing this one # For production use (if you have more GPU memory) # model_name = "microsoft/phi-2" # 2.7B parameters # model_name = "stabilityai/stablelm-2-1_6b" # 1.6B parameters

Preparando Tus Datos de Entrenamiento

La clave para un ajuste fino exitoso son datos de entrenamiento de alta calidad. Así es cómo los estructuramos:

# Sample dataset for MyNextDeveloper (MND)

data = {

"text": [

"User asks: Write a 3-bullet overview of MND.nAssistant: - Remote-first, founded 2022 in Mumbain- Staff augmentation + full-cycle web/API, UI/UX, AI/MLn- Agile/TDD, POSH culture, transparent pricing",

"User asks: Where is MND headquartered?nAssistant: Malabar Hill, Mumbai",

"User asks: What services does MND offer?nAssistant: Staff augmentation, API development, web development, UI/UX design, AI/ML solutions",

"User asks: What is MND's tech stack?nAssistant: Angular, React, Next.js, Node.js, Django, Python, Docker, AWS",

"User asks: What is MND's pricing model?nAssistant: Project pricing starting at $10,000 with hourly rates between $25 and $49",

"User asks: What is MND's mission?nAssistant: To solve the trust gap between startups and engineers by emphasizing empathy, communication, and transparency",

"User asks: What is MND's culture like?nAssistant: Agile practices, test-driven development, and POSH-compliant culture",

"User asks: When was MND founded?nAssistant: 2022"

]

}
# Convert to HuggingFace dataset dataset = Dataset.from_dict(data)

Principios clave para los datos de entrenamiento:

  • Usa formato consistente (nota el patrón "User asks:" y "Assistant:")
  • Mantén las respuestas factual y concisas
  • Cubre la información más importante sobre tu dominio
  • Calidad sobre cantidad: 50 ejemplos perfectos superan 500 mediocres

Entrenamiento Eficiente con LoRA y Cuantización

En lugar de hacer ajuste fino a todo el modelo (que requiere memoria GPU masiva), usaremos dos técnicas de eficiencia:

1. Cuantización (4-bit)

La cuantización es una técnica de compresión usada para hacer modelos de lenguaje grandes (LLMs) más pequeños y rápidos sin reducir mucho la precisión.

  • Normalmente, los pesos de LLM se almacenan como números de punto flotante de 32 bits (FP32).
  • La cuantización reduce esta precisión a 16-bit (FP16/BF16), 8-bit (INT8), 4-bit (INT4) o incluso menor.

👉 Ejemplo:

  • Un modelo con 10 mil millones de parámetros en FP32 necesita ~40 GB de memoria.
  • Si lo cuantizamos a INT8 (8-bit) → solo necesita ~10 GB.
  • Si vamos a INT4 (4-bit) → solo ~5 GB.

¿Por qué es útil?

  • Hace que los modelos funcionen en GPUs más pequeñas (o incluso CPUs).
  • Acelera la inferencia.
  • Ligera compensación en precisión, pero a menudo insignificante.
# Configure 4-bit quantization

bnb_config = BitsAndBytesConfig(

load_in_4bit=True,

bnb_4bit_quant_type="nf4",

bnb_4bit_use_double_quant=True,

bnb_4bit_compute_dtype=torch.float16

)
# Load model with quantization model = AutoModelForCausalLM.from_pretrained( model_name, quantization_config=bnb_config, device_map="auto", torch_dtype=torch.float16 )

2. LoRA (Adaptación de Bajo Rango)

LoRA es un método de ajuste fino eficiente en parámetros (PEFT).

Normalmente, para hacer ajuste fino a un LLM enorme (como LLaMA-65B o GPT-J), necesitaríamos cientos de GB de memoria GPU. LoRA resuelve esto al:

  • Congelar los pesos del modelo original.
  • Agregar pequeñas matrices entrenables (adaptadores de bajo rango) dentro de las capas del modelo.
  • Durante el ajuste fino, solo se actualizan estas pequeñas matrices.

👉 Ejemplo:

  • El ajuste fino completo de un modelo de 65B podría requerir ~1 TB de memoria GPU.
  • Con LoRA, solo entrenas algunos millones de parámetros → necesita < 20 GB de memoria GPU.

¿Por qué es útil?

  • Hace que el ajuste fino de LLMs masivos sea posible en hardware de consumidor (1–2 GPUs).
  • Fácil de "fusionar" o "desfusionar" adaptadores → puedes cambiar tareas rápidamente.
  • A menudo logra rendimiento cercano al ajuste fino completo.
# Configure LoRA based on model architecture

if "TinyLlama" in model_name or "Llama" in model_name:

target_modules = ["q_proj", "k_proj", "v_proj", "o_proj"]

elif "gpt" in model_name.lower() or "DialoGPT" in model_name:

target_modules = ["c_attn", "c_proj"]

else:

target_modules = ["q_proj", "v_proj"]
lora_config = LoraConfig( r=8, # Rank of adaptation lora_alpha=16, # LoRA scaling parameter target_modules=target_modules, lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) # Apply LoRA to the model model = get_peft_model(model, lora_config) model.print_trainable_parameters()

¡Solo estamos entrenando el 0.2% de los parámetros!

Entrenamiento del Modelo

# Tokenize the data

def tokenize_function(examples):

tokenized_inputs = tokenizer(

examples["text"],

truncation=True,

padding="max_length",

max_length=512,

return_tensors="pt"

)

# Create labels by copying input tokens

tokenized_inputs["labels"] = tokenized_inputs["input_ids"].clone()

return tokenized_inputs
# Split dataset train_dataset = dataset.select(range(8)) eval_dataset = dataset.select(range(8, 11)) # Apply tokenization train_dataset = train_dataset.map(tokenize_function, batched=True) eval_dataset = eval_dataset.map(tokenize_function, batched=True) # Configure training training_args = TrainingArguments( output_dir="./mnd-finetune-outputs", num_train_epochs=5, per_device_train_batch_size=4, per_device_eval_batch_size=4, gradient_accumulation_steps=2, warmup_steps=10, learning_rate=3e-4, weight_decay=0.01, logging_steps=1, save_steps=30, eval_strategy="steps", eval_steps=15, save_total_limit=2, load_best_model_at_end=True, fp16=True, report_to=None # Disable wandb logging ) # Create trainer and start training trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, tokenizer=tokenizer, ) print("Starting training...") trainer.train() # Save the adapter adapter_dir = "./mnd-finetune-outputs/final_adapter" model.save_pretrained(adapter_dir) tokenizer.save_pretrained(adapter_dir)

Prueba del Modelo Ajustado Finamente

def load_model_for_inference():

"""Load the fine-tuned model for inference"""

# Load base model

base_model = AutoModelForCausalLM.from_pretrained(

model_name,

quantization_config=bnb_config,

device_map="auto",

torch_dtype=torch.float16

)

# Load the fine-tuned adapter

model = PeftModel.from_pretrained(base_model, adapter_dir)

model = model.merge_and_unload()

# Load tokenizer

tokenizer = AutoTokenizer.from_pretrained(adapter_dir)

return model, tokenizer

def generate_response(model, tokenizer, prompt, max_length=256, temperature=0.7):

"""Generate response for a given prompt"""

formatted_prompt = f"User asks: {prompt}nAssistant:"

inputs = tokenizer.encode(formatted_prompt, return_tensors="pt")

inputs = inputs.to(model.device)

with torch.no_grad():

outputs = model.generate(

inputs,

max_length=max_length,

temperature=temperature,

top_p=0.9,

do_sample=True,

pad_token_id=tokenizer.eos_token_id,

repetition_penalty=1.1

)

response = tokenizer.decode(outputs[0], skip_special_tokens=True)

assistant_response = response.split("Assistant:")[-1].strip()

return assistant_response

# Load fine-tuned model and test

model, tokenizer = load_model_for_inference()

test_prompts = [

"What makes MND different from other development companies?",

"Can you tell me about MND's team?",

"What is the company culture at MND?"

]

for prompt in test_prompts:

response = generate_response(model, tokenizer, prompt)

print(f"Q: {prompt}")

print(f"A: {response}n")

Google Colab

Aquí está el enlace de Google Colab para este artículo que puedes ejecutar en un clic: enlace

Los Costos Reales

A diferencia de las APIs comerciales, tus costos son principalmente:

  1. Configuración Inicial: Tiempo de GPU para entrenamiento
  2. Almacenamiento: Pesos del modelo (~4GB para TinyLlama con adaptadores LoRA)
  3. Inferencia: Tu propio hardware o instancias GPU en la nube

Para un modelo pequeño como TinyLlama, puedes ejecutar inferencia en:

  • Google Colab (nivel gratuito con limitaciones)
  • AWS t3.medium con GPU (~$0.05/hora)
  • Tu propio hardware (RTX 3060 o mejor)

Mejores Prácticas desde Experiencia Real

1. Comienza en Pequeño y Escala Comienza con distilgpt2 o gpt2 para probar tus datos y proceso, luego muévete a modelos más grandes.

2. Monitorea el Sobreajuste Con conjuntos de datos pequeños, los modelos pueden memorizar en lugar de aprender. Observa tu pérdida de evaluación.

3. La Consistencia de Formato es Crítica El formato exacto de tus datos de entrenamiento importa enormemente. Sé consistente con puntuación, espaciado y estructura.

4. Prueba con Preguntas No Vistas Siempre prueba con preguntas que no estén en tus datos de entrenamiento para asegurar generalización.

5. Guarda Puntos de Control Regulares El entrenamiento puede ser interrumpido. Guarda frecuentemente y prueba puntos de control intermedios.

Trampas Comunes y Soluciones

Problema: El modelo genera texto repetitivo o sin sentido Solución: Reduce la tasa de aprendizaje, aumenta la regularización, o mejora la calidad de los datos de entrenamiento

Problema: El modelo olvida el conocimiento general Solución: Incluye algunos ejemplos generales en tus datos de entrenamiento o usa un modelo base más grande

Problema: Las respuestas son demasiado genéricas Solución: Haz que tus ejemplos de entrenamiento sean más específicos y detallados

Problema: Problemas de memoria GPU Solución: Reduce el tamaño del lote, usa cuantización más agresiva, o punto de control de gradiente

Combinando con RAG

Aquí está la parte poderosa: puedes combinar tu modelo ajustado finamente con RAG para lo mejor de ambos mundos:

  1. Ajusta finamente para comprensión del dominio, tono, y conocimiento general de la empresa
  2. Usa RAG para información actual, documentos específicos, o especificaciones técnicas detalladas

Esto te da un modelo que "piensa" como tu empresa pero puede acceder a información actualizada.

¿Qué Sigue?

En nuestro próximo artículo, vamos completamente personalizado — construyendo un modelo de lenguaje desde cero, enteramente tuyo, ejecutándose en tu hardware con tus datos.

El ajuste fino de modelos de código abierto te da control sin precedentes sobre tu asistente de IA. Puedes asegurar que entienda tu dominio, hable en tu voz, y nunca envíe tus datos a terceros. Con técnicas modernas de eficiencia como LoRA y cuantización, es más accesible que nunca.

El futuro de la IA no es solo usar el modelo de alguien más — es hacer que la IA sea verdaderamente tuya.


Próximamente: Artículo 4 — "Construyendo Tu Propio Modelo de Lenguaje: Pequeño Pero Poderoso"