Large Language Models (LLMs)
Desde BERT y GPT hasta agentes autónomos: la revolución de los grandes modelos de lenguaje. Arquitecturas encoder-only vs decoder-only, pre-training a escala, tokenización, scaling laws, fine-tuning con PEFT/LoRA, RLHF, DPO, prompting avanzado, modelos de razonamiento, LLMs multimodales, function calling y frameworks de agentes.
De Transformers a LLMs
El Transformer (Vaswani et al., 2017) introdujo una arquitectura basada enteramente en atención que reemplazó a las RNNs. Pero fue la idea de pre-entrenar masivamente un Transformer con texto no etiquetado y luego ajustarlo (fine-tuning) a tareas específicas la que dio lugar a los Large Language Models (LLMs).
Dos filosofías divergentes emergieron casi simultáneamente en 2018:
BERT: Bidirectional Encoder Representations from Transformers
BERT (Devlin et al., 2018) fue el primer modelo en demostrar que un Transformer encoder pre-entrenado bidireccionalmente podía lograr resultados SOTA en 11 tareas de NLP simultáneamente, simplemente añadiendo una capa de clasificación encima.
📄 Paper: "BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding"
Devlin, Chang, Lee & Toutanova (2018).
arXiv:1810.04805 ·
GitHub
Arquitectura del Encoder
BERT usa exclusivamente el encoder del Transformer original:
Objetivos de pre-entrenamiento
Se enmascara aleatoriamente el 15% de los tokens de entrada y el modelo debe predecir los tokens originales. De ese 15%:
- 80% → se reemplaza por
[MASK] - 10% → se reemplaza por un token aleatorio
- 10% → se deja sin cambiar
Esta estrategia evita que el modelo dependa del token especial [MASK]
(que nunca aparece en fine-tuning/inferencia) y fuerza representaciones robustas.
Donde \(\mathcal{M}\) es el conjunto de posiciones enmascaradas.
Dado un par de frases (A, B), el modelo predice si B es la frase siguiente real de A
(IsNext) o una frase aleatoria (NotNext). Se usa la representación
del token [CLS] para la clasificación binaria.
Nota: estudios posteriores (RoBERTa, ALBERT) demostraron que NSP tiene un impacto limitado y que eliminar este objetivo no afecta (o mejora) los resultados.
Input Representation
Cada token de entrada es la suma de tres embeddings:
| Embedding | Descripción | Ejemplo |
|---|---|---|
| Token | WordPiece embedding del subword | "play" → "play", "##ing" → "##ing" |
| Segment | Indica frase A o B (para tareas de pares) | [0, 0, 0, 1, 1, 1] |
| Position | Posición aprendida (no sinusoidal, max 512) | [0, 1, 2, ..., 511] |
Configuraciones de BERT
| Modelo | Capas (L) | Hidden (H) | Heads (A) | Parámetros |
|---|---|---|---|---|
| BERTBASE | 12 | 768 | 12 | 110M |
| BERTLARGE | 24 | 1024 | 16 | 340M |
Familia y variantes de BERT
Tras el éxito de BERT surgieron numerosas variantes que mejoran aspectos específicos:
Robustly Optimized BERT Approach. Elimina NSP, usa más datos (160 GB vs 16 GB), más batch size, secuencias más largas, y masking dinámico (diferente máscara cada epoch).
Resultados: +2-4 puntos sobre BERT en GLUE, SQuAD y RACE.
A Lite BERT. Dos técnicas de reducción de parámetros:
- Factorized Embedding: separa la dimensión del vocabulario (V×E) de la hidden (E×H)
- Cross-Layer Parameter Sharing: todas las capas comparten pesos
ALBERT-xxlarge: 235M → 12M parámetros únicos, con rendimiento similar a BERT-large.
Knowledge distillation aplicada a BERT. Un modelo "estudiante" de 6 capas que aprende de BERT-base (12 capas) como "profesor".
Resultado: 60% más rápido, 40% menos parámetros (66M), retiene el 97% del rendimiento de BERT.
En lugar de MLM, usa un esquema GAN-like: un generador pequeño reemplaza tokens y un discriminador (el modelo principal) predice qué tokens fueron reemplazados (replaced token detection).
Ventaja: cada token recibe una señal de entrenamiento (no solo el 15% enmascarado), lo que lo hace mucho más eficiente computacionalmente.
Disentangled attention: separa las representaciones de contenido y posición en la atención. Añade un Enhanced Mask Decoder que usa posición absoluta solo en la capa final.
DeBERTa-v3 fue el primer modelo en superar el rendimiento humano en el benchmark SuperGLUE.
| Modelo | Params | Mejora clave | GLUE Score | Año |
|---|---|---|---|---|
| BERT-base | 110M | MLM + NSP | 79.6 | 2018 |
| RoBERTa-large | 355M | Más datos, sin NSP | 88.5 | 2019 |
| ALBERT-xxlarge | 235M | Parameter sharing | 89.4 | 2019 |
| DistilBERT | 66M | Distillation | 77.0 | 2019 |
| ELECTRA-large | 335M | Replaced token detection | 89.5 | 2020 |
| DeBERTa-v3 | 304M | Disentangled attention | 91.4 | 2020 |
Fine-tuning de BERT
El paradigma "pre-train then fine-tune" de BERT revolucionó el NLP. La idea central es simple: tomar el encoder pre-entrenado y añadir una capa de clasificación específica para cada tarea.
# ═══════════════════════════════════════════════════
# Fine-tuning BERT para clasificación de sentimiento
# ═══════════════════════════════════════════════════
from transformers import BertTokenizer, BertForSequenceClassification
from transformers import Trainer, TrainingArguments
from datasets import load_dataset
# 1. Cargar modelo pre-entrenado
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained(
'bert-base-uncased',
num_labels=2 # positivo / negativo
)
# 2. Dataset
dataset = load_dataset('imdb')
def tokenize(batch):
return tokenizer(batch['text'], padding='max_length',
truncation=True, max_length=512)
tokenized = dataset.map(tokenize, batched=True)
# 3. Training
args = TrainingArguments(
output_dir='./results',
num_train_epochs=3,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
learning_rate=2e-5, # LR bajo, típico de fine-tuning
weight_decay=0.01,
evaluation_strategy='epoch',
warmup_steps=500,
fp16=True, # Mixed precision
)
trainer = Trainer(
model=model,
args=args,
train_dataset=tokenized['train'],
eval_dataset=tokenized['test'],
)
trainer.train() # ~93% accuracy en IMDb
GPT: Generative Pre-trained Transformer
GPT (Radford et al., 2018) tomó el camino opuesto a BERT: usar solo el decoder del Transformer con atención causal (masked) para modelar la probabilidad del siguiente token.
📄 Papers de la serie GPT
- GPT-1: "Improving Language Understanding by Generative Pre-Training" (Radford et al., 2018) [PDF]
- GPT-2: "Language Models are Unsupervised Multitask Learners" (Radford et al., 2019) [PDF] · GitHub
- GPT-3: "Language Models are Few-Shot Learners" (Brown et al., 2020) arXiv:2005.14165
- GPT-4: "GPT-4 Technical Report" (OpenAI, 2023) arXiv:2303.08774
Modelado autoregresivo
GPT modela la distribución de probabilidad del lenguaje de forma causal (izquierda a derecha):
El objetivo de pre-entrenamiento es maximizar la log-verosimilitud:
La máscara causal impide que cada token atienda a tokens futuros, lo que permite la generación autoregresiva token a token.
Evolución de GPT
| Modelo | Params | Datos | Context | Innovación clave |
|---|---|---|---|---|
| GPT-1 | 117M | BookCorpus (5 GB) | 512 | Pre-train + fine-tune con decoder-only |
| GPT-2 | 1.5B | WebText (40 GB) | 1024 | "Zero-shot learning" sin fine-tuning |
| GPT-3 | 175B | 300B tokens | 2048 | In-context learning, few-shot |
| GPT-3.5 | ~175B | Idem + RLHF | 4096 | InstructGPT → ChatGPT |
| GPT-4 | ~1.8T* | ~13T tokens* | 8K-128K | MoE, multimodal, razonamiento |
| GPT-4o | — | — | 128K | Natively multimodal (texto+imagen+audio) |
* Estimaciones no oficiales (fuentes: análisis independientes, filtraciones).
BERT vs GPT: Comparativa
| Aspecto | BERT (Encoder-only) | GPT (Decoder-only) |
|---|---|---|
| Dirección | Bidireccional | Unidireccional (izq → der) |
| Pre-training | MLM + NSP | Causal Language Modeling |
| Uso principal | Comprensión (clasificación, NER, QA) | Generación (texto, código, chat) |
| Fine-tuning | Necesario para cada tarea | Opcional (in-context learning) |
| Contexto | Ventana completa (fija, 512) | Ventana creciente (hasta 128K+) |
| Atención | Full attention (O(n²)) | Causal mask (triangular inferior) |
| Escalado | ~340M max (limitado) | ~1.8T (escala masivamente) |
| Embeddings | Token + Segment + Position (aprendido) | Token + Position (aprendido/RoPE) |
| Normalización | Post-LayerNorm | Pre-LayerNorm (GPT-2+) → RMSNorm |
| Activación FFN | GELU | GELU → SwiGLU (LLaMA+) |
| Ventaja | Contexto bidireccional rico | Genera texto, escala mejor |
🔬 Widget: Comparador de tamaño de modelos
Visualiza la escala de diferentes LLMs en términos de parámetros y datos de entrenamiento.
El ecosistema open-source
A partir de 2023, una ola de modelos open-source / open-weight democratizó el acceso a LLMs de alta calidad:
| Modelo | Organización | Params | Licencia | Innovación |
|---|---|---|---|---|
| LLaMA | Meta | 7-65B | Research | Modelos fundacionales eficientes |
| LLaMA 2 | Meta | 7-70B | Comercial | Datos 40% más, GQA en 70B |
| LLaMA 3 | Meta | 8-405B | Comercial | 15T tokens, 128K context |
| Mistral 7B | Mistral | 7B | Apache 2.0 | Sliding Window Attention, GQA |
| Mixtral 8×7B | Mistral | 46.7B (12.9B activos) | Apache 2.0 | Mixture of Experts (MoE) |
| Qwen 2.5 | Alibaba | 0.5-72B | Apache 2.0 | Multilingüe, código, matemáticas |
| Gemma 2 | 2-27B | Abierta | Destilación de Gemini | |
| DeepSeek-V3 | DeepSeek | 671B (37B activos) | MIT | MoE eficiente, FP8 training |
| Phi-3 | Microsoft | 3.8B | MIT | Datos curados de alta calidad |
📚 Repositorios clave
- meta-llama/llama3 — Modelo LLaMA 3
- mistralai/mistral-src — Modelo Mistral
- HuggingFace Model Hub — Miles de modelos open-source
- huggingface/transformers — Librería unificada para LLMs
- vllm-project/vllm — Inferencia eficiente para LLMs
Pre-training de LLMs: el cimiento
El pre-training es la fase donde un LLM aprende la estructura del lenguaje, conocimiento factual y capacidad de razonamiento a partir de billones de tokens de texto no etiquetado. Es la fase más costosa computacionalmente (millones de dólares en GPUs durante semanas o meses).
Datasets de pre-training
La calidad y diversidad de los datos determina en gran medida las capacidades del modelo. Los datasets modernos combinan múltiples fuentes:
| Dataset | Tamaño | Fuentes | Usado por |
|---|---|---|---|
| Common Crawl | ~250B páginas | Web crawl global | GPT-3, LLaMA, todos |
| C4 | ~750 GB | Common Crawl filtrado | T5, PaLM |
| The Pile | 825 GB | 22 fuentes diversas | GPT-NeoX, Pythia |
| RedPajama | 1.2T tokens | Réplica de LLaMA | Open-source |
| FineWeb | 15T tokens | Common Crawl curado por HF | Open-source |
| The Stack v2 | ~4TB | Código fuente (GitHub) | StarCoder 2 |
| Wikipedia | ~20 GB | Enciclopedia | BERT, GPT-3, todos |
| Books3 | ~100 GB | Libros | GPT-3, LLaMA (controversia) |
| arXiv | ~85 GB | Papers científicos | Galactica, LLaMA |
Ref: Penedo et al. (2024) "The FineWeb Datasets" (arXiv:2406.17557)
Tokenización para LLMs
Los LLMs no procesan texto crudo sino tokens — unidades subword que equilibran la granularidad entre caracteres y palabras.
import tiktoken
# GPT-4 tokenizer
enc = tiktoken.get_encoding("cl100k_base")
text = "Los Large Language Models procesan tokens, no palabras."
tokens = enc.encode(text)
print(f"Texto: {text}")
print(f"Tokens: {tokens}")
print(f"Nº tokens: {len(tokens)}")
print(f"Decodificado: {[enc.decode([t]) for t in tokens]}")
# Output:
# Texto: Los Large Language Models procesan tokens, no palabras.
# Tokens: [30832, 20902, 11688, 27972, 62853, 11, 912, 84113, 13]
# Nº tokens: 9
# Decodificado: ['Los', ' Large', ' Language', ' Models', ' procesan', ' tokens', ',', ' no', ' palabras', '.']
Scaling Laws: las leyes del escalado
Un descubrimiento fundamental de la era LLM es que el rendimiento del modelo sigue leyes de potencia predecibles con respecto al tamaño del modelo, la cantidad de datos y el compute total.
📄 Papers fundamentales
- Kaplan et al. (2020): "Scaling Laws for Neural Language Models" arXiv:2001.08361
- Hoffmann et al. (2022): "Training Compute-Optimal Large Language Models" (Chinchilla) arXiv:2203.15556
Leyes de Kaplan (OpenAI, 2020)
La loss del modelo sigue una ley de potencia con tres variables:
Donde \(N\) = parámetros, \(D\) = tokens, \(C\) = FLOPs. Los exponentes encontrados: \(\alpha_N \approx 0.076\), \(\alpha_D \approx 0.095\), \(\alpha_C \approx 0.050\).
Chinchilla: ratio óptimo de datos/modelo
Es decir, un modelo de 10B parámetros debería entrenarse con ~200B tokens. GPT-3 (175B params, 300B tokens) estaba sub-entrenado según esta regla.
| Modelo | Params N | Tokens D | Ratio D/N | ¿Chinchilla-optimal? |
|---|---|---|---|---|
| GPT-3 | 175B | 300B | 1.7× | ❌ Sub-trained |
| Chinchilla | 70B | 1.4T | 20× | ✅ Optimal |
| LLaMA | 7B | 1T | 143× | ✅ Over-trained (deliberado) |
| LLaMA 2 | 70B | 2T | 28.5× | ≈ Sí |
| LLaMA 3 | 8B | 15T | 1875× | ✅ "Over-trained" para eficiencia en inferencia |
💡 Tendencia post-Chinchilla
Modelos recientes (LLaMA 3, Phi-3) intencionalmente sobre-entrenan modelos pequeños con muchos más datos de lo óptimo según Chinchilla. ¿Por qué? Porque el coste de inferencia (que depende de N) domina al de training. Un modelo de 8B con 15T tokens rinde como uno de 70B pero es 10× más barato de servir.
Arquitectura moderna de LLMs
Los LLMs modernos (LLaMA, Mistral, Qwen, etc.) han convergido en un conjunto de mejoras arquitectónicas respecto al Transformer original:
| Componente | Transformer original | LLMs modernos | Beneficio |
|---|---|---|---|
| Normalización | Post-LayerNorm | Pre-RMSNorm | Training más estable |
| Pos. Encoding | Sinusoidal | RoPE (rotary) | Generalización a contextos largos |
| Activación FFN | ReLU/GELU | SwiGLU | +1-2% quality |
| Attention | Multi-Head (MHA) | GQA / MQA | KV-cache 8× más pequeño |
| FFN ratio | 4×d | 8/3×d (SwiGLU) | Más eficiente |
| Bias | Sí (en Linear) | No (sin bias) | Menos params, misma calidad |
| Tying | A veces | Token embedding = LM head | Reduce params |
| Context | 512-2048 | 8K-1M+ (RoPE + YaRN/NTK) | Documentos largos |
RoPE (Su et al., 2021) codifica posición rotando los vectores query y key en el espacio complejo:
Propiedad clave: el producto punto entre queries/keys solo depende de la distancia relativa entre posiciones, no de la absoluta. Esto permite la extensión de contexto (ej: entrenar en 4K pero inferir en 128K con interpolación NTK/YaRN).
En Multi-Head Attention (MHA), cada cabeza tiene su propio K y V, lo que genera un KV-cache enorme. GQA (Ainslie et al., 2023) agrupa varias cabezas de query para compartir un mismo par K/V.
- MHA: h cabezas, h K/V → KV-cache = 2 × h × d × seq_len
- GQA: h cabezas query, g grupos K/V (g < h) → KV-cache / (h/g)×
- MQA: caso extremo con g=1 (un único K/V para todas las cabezas)
LLaMA 2 70B, LLaMA 3, Mistral: usan GQA con 8 grupos KV.
Propuesta por Shazeer (2020), SwiGLU combina Swish con un mecanismo de gating:
Donde \(\text{Swish}(x) = x \cdot \sigma(\beta x)\). El FFN con SwiGLU usa dimensión \(\frac{8}{3}d\) (vs 4d con ReLU) para igualar el número de parámetros.
Infraestructura de pre-training
Entrenar un LLM a escala requiere paralelismo masivo en miles de GPUs. Las técnicas principales son:
| Modelo | GPUs | Tiempo | Coste estimado | Framework |
|---|---|---|---|---|
| GPT-3 (175B) | 10,000 V100 | ~14 días | ~$4.6M | Custom (Megatron-LM) |
| LLaMA (65B) | 2,048 A100 80GB | 21 días | ~$2.4M | Custom |
| LLaMA 3 (405B) | 16,384 H100 | ~54 días | ~$100M+ | Custom (fairscale) |
| DeepSeek-V3 | 2,048 H800 | ~2 meses | ~$5.6M | HAI-LLM (custom) |
| Mistral 7B | ~512 A100 | ~días | ~$500K | Megatron-LM |
🔧 Frameworks de training distribuido
- Megatron-LM (NVIDIA) — Estándar para 3D parallelism
- DeepSpeed (Microsoft) — ZeRO optimizer, pipeline parallelism
- PyTorch FSDP — Fully Sharded Data Parallel nativo
- JAX + XLA — TPU-native, usado por Google (PaLM, Gemini)
| Técnica | Descripción | Ahorro |
|---|---|---|
| Mixed Precision (BF16) | Forward/backward en BFloat16, master weights en FP32 | 2× memoria, ~1.5× velocidad |
| Gradient Checkpointing | Re-computa activaciones en backward en lugar de almacenarlas | ~60% memoria, +30% tiempo |
| Flash Attention 2 | Kernel fusionado GPU para attention, tiling I/O-aware | 2-4× más rápido, O(n) memoria |
| Gradient Accumulation | Acumula gradientes sobre micro-batches | Permite batches grandes con poca memoria |
| FP8 training | Forward en FP8 (DeepSeek-V3, Hopper GPUs) | 2× vs BF16 |
| ZeRO Stage 3 | Fragmenta params, gradients y optimizer state entre GPUs | N× memoria (N = nº GPUs) |
Ref: Dao (2023) "FlashAttention-2" (arXiv:2307.08691); Rajbhandari et al. (2020) "ZeRO" (arXiv:1910.02054)
🧮 Widget: Estimador de coste de pre-training
Estima el coste aproximado de pre-entrenar un LLM con la regla de 6ND FLOPs.
Mixture of Experts (MoE)
Los modelos MoE escalan el número de parámetros sin incrementar proporcionalmente el coste computacional. Solo un subconjunto de "expertos" se activa para cada token.
| Modelo MoE | Total params | Params activos | Expertos | Top-K |
|---|---|---|---|---|
| Mixtral 8×7B | 46.7B | 12.9B | 8 | 2 |
| GPT-4 (estimado) | ~1.8T | ~280B | 16 | 2 |
| DeepSeek-V3 | 671B | 37B | 256 | 8 |
| DBRX | 132B | 36B | 16 | 4 |
| Grok-1 | 314B | ~80B | 8 | 2 |
📄 Papers de MoE
- Shazeer et al. (2017): "Outrageously Large Neural Networks: The Sparsely-Gated MoE Layer" arXiv:1701.06538
- Fedus et al. (2022): "Switch Transformers: Scaling to Trillion Parameter Models" arXiv:2101.03961
- Jiang et al. (2024): "Mixtral of Experts" arXiv:2401.04088
De modelo base a chatbot: las 3 fases
Un LLM pre-entrenado (modelo "base") solo sabe completar texto. Para convertirlo en un asistente útil que siga instrucciones se necesitan tres fases adicionales:
Supervised Fine-Tuning (SFT)
El SFT adapta el modelo base a seguir instrucciones entrenándolo con pares (instrucción, respuesta) escritos por humanos o generados sintéticamente.
Formato de datos SFT
# Formato típico de datos SFT (chat template)
data = [
{
"messages": [
{"role": "system", "content": "Eres un asistente experto en ML."},
{"role": "user", "content": "¿Qué es el dropout?"},
{"role": "assistant", "content": "El dropout es una técnica de regularización..."}
]
},
{
"messages": [
{"role": "user", "content": "Escribe una función que ordene una lista en Python."},
{"role": "assistant", "content": "def sort_list(lst):\n return sorted(lst)"}
]
}
]
# La loss se calcula SOLO sobre los tokens del assistant (no user/system)
| Dataset SFT | Tamaño | Fuente | Notas |
|---|---|---|---|
| InstructGPT data | ~13K prompts | Humanos (labelers) | Dataset original de OpenAI |
| FLAN v2 | ~1.8K tareas / 15M ej. | Datasets NLP reformateados | Google, instruction tuning |
| ShareGPT | ~90K conversaciones | Conversaciones con ChatGPT | Usado por Vicuna |
| OpenAssistant | ~160K mensajes | Crowdsourcing | Multilingüe, open-source |
| UltraChat | ~1.5M diálogos | Sintéticos (GPT-3.5/4) | Usado por Zephyr |
| Alpaca | 52K | Sintéticos (text-davinci-003) | Self-instruct de Stanford |
Fine-tuning eficiente: PEFT
Fine-tunear todos los parámetros de un LLM de 70B requiere enormes recursos. PEFT (Parameter-Efficient Fine-Tuning) congela la mayoría del modelo y solo entrena un número reducido de parámetros.
LoRA en detalle
LoRA (Hu et al., 2021) es la técnica PEFT más utilizada. En lugar de actualizar la matriz de pesos \(W \in \mathbb{R}^{d \times k}\), LoRA añade una descomposición de bajo rango:
Con \(r = 16\), una capa de \(4096 \times 4096\) pasa de 16.7M a solo 131K parámetros entrenables (0.8%). El scaling factor \(\alpha / r\) controla la magnitud de la adaptación.
# ═══════════════════════════════════════════════════
# Fine-tuning con LoRA (PEFT library)
# ═══════════════════════════════════════════════════
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
from peft import LoraConfig, get_peft_model, TaskType
from trl import SFTTrainer
from datasets import load_dataset
# 1. Modelo base
model_name = "meta-llama/Llama-2-7b-hf"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
# 2. Configurar LoRA
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=16, # Rango de la descomposición
lora_alpha=32, # Scaling factor
lora_dropout=0.05,
target_modules=[ # Capas donde aplicar LoRA
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
bias="none",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Output: trainable params: 13,631,488 || all params: 6,751,367,168 || 0.20%
# 3. Dataset
dataset = load_dataset("mlabonne/guanaco-llama2-1k")
# 4. Training
training_args = TrainingArguments(
output_dir="./llama2-lora",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=2e-4,
fp16=True,
logging_steps=10,
save_strategy="epoch",
)
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset["train"],
dataset_text_field="text",
max_seq_length=1024,
)
trainer.train()
📄 Papers de PEFT
- LoRA: Hu et al. (2021) "LoRA: Low-Rank Adaptation of Large Language Models" arXiv:2106.09685
- QLoRA: Dettmers et al. (2023) "QLoRA: Efficient Finetuning of Quantized LLMs" arXiv:2305.14314
- Prefix Tuning: Li & Liang (2021) arXiv:2101.00190
- PEFT Library: huggingface/peft
RLHF: Reinforcement Learning from Human Feedback
RLHF es el proceso que alinea un LLM con las preferencias humanas. Fue la técnica clave detrás de ChatGPT e InstructGPT.
El objetivo de RLHF
Donde \(\pi_\theta\) es la policy (el LLM), \(R_\phi\) es el reward model entrenado con preferencias humanas, y el término KL previene que el modelo se desvíe demasiado del modelo SFT (evitando reward hacking).
El reward model se entrena con la loss de Bradley-Terry sobre pares de comparación humana:
Donde \(y_w\) es la respuesta preferida y \(y_l\) la rechazada. El reward model suele ser un LLM más pequeño (ej: 6B) con una cabeza escalar.
📄 Papers de RLHF
- InstructGPT: Ouyang et al. (2022) "Training language models to follow instructions with human feedback" arXiv:2203.02155
- RLHF original: Christiano et al. (2017) "Deep RL from Human Preferences" arXiv:1706.03741
- PPO: Schulman et al. (2017) "Proximal Policy Optimization" arXiv:1707.06347
- Anthropic RLHF: Bai et al. (2022) "Training a Helpful and Harmless Assistant" arXiv:2204.05862
DPO y alternativas a RLHF
RLHF requiere entrenar un reward model separado y usar PPO (inestable, costoso). DPO simplifica esto drásticamente.
DPO: Direct Preference Optimization
Rafailov et al. (2023) demostraron que se puede optimizar directamente la policy con datos de preferencias, sin un reward model explícito:
Equivalente a RLHF pero con una simple loss de clasificación binaria. No necesita sampling, es estable, y es 3-10× más barato que PPO.
| Método | Reward Model | Sampling | Estabilidad | Coste | Paper |
|---|---|---|---|---|---|
| RLHF (PPO) | Sí | Sí (online) | Inestable | Alto (4 modelos en GPU) | 2203.02155 |
| DPO | No (implícito) | No (offline) | Estable | Bajo | 2305.18290 |
| KTO | No | No | Estable | Bajo | 2402.01306 |
| IPO | No | No | Estable | Bajo | 2310.12036 |
| ORPO | No | No | Estable | Muy bajo (SFT+align juntos) | 2403.07691 |
| GRPO | No (rule-based) | Sí (online) | Estable | Medio | 2402.03300 (DeepSeek) |
# ═══════════════════════════════════════════════════
# DPO Training con TRL (Transformer Reinforcement Learning)
# ═══════════════════════════════════════════════════
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import DPOTrainer, DPOConfig
from datasets import load_dataset
from peft import LoraConfig
# 1. Modelo (SFT ya hecho)
model = AutoModelForCausalLM.from_pretrained(
"my-sft-model",
torch_dtype="auto",
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("my-sft-model")
# 2. Dataset de preferencias
# Cada ejemplo: { "prompt": ..., "chosen": ..., "rejected": ... }
dataset = load_dataset("argilla/ultrafeedback-binarized-preferences")
# 3. LoRA para eficiencia
peft_config = LoraConfig(
r=16, lora_alpha=32, lora_dropout=0.05,
target_modules=["q_proj","k_proj","v_proj","o_proj"],
)
# 4. DPO Training
dpo_config = DPOConfig(
output_dir="./dpo-model",
beta=0.1, # Temperatura (controla desviación de ref)
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=5e-7, # LR muy bajo para alignment
num_train_epochs=1,
fp16=True,
)
trainer = DPOTrainer(
model=model,
ref_model=None, # None → usa modelo inicial como referencia
args=dpo_config,
train_dataset=dataset["train"],
tokenizer=tokenizer,
peft_config=peft_config,
)
trainer.train()
Datasets de alignment (preferencias)
Los datasets de preferencias son la materia prima del RLHF/DPO:
| Dataset | Tamaño | Tipo | Notas |
|---|---|---|---|
| HH-RLHF | 170K | Comparaciones | Anthropic. Helpfulness + Harmlessness |
| UltraFeedback | 64K | Rankings (4 respuestas) | 4 modelos, GPT-4 como juez |
| Nectar | 183K | Rankings (7 respuestas) | Starling-LM, GPT-4 ranking |
| Chatbot Arena | ~1M+ votos | Comparaciones humanas | LMSYS. ELO ranking real |
| OASST2 | ~24K rankings | Rankings humanos | Open Assistant, crowdsource |
Ingeniería de Prompts
Prompt engineering es el arte de diseñar las entradas (prompts) al LLM para obtener las respuestas deseadas sin modificar los pesos del modelo. Con LLMs suficientemente grandes (≥ 100B params), el prompting puede reemplazar al fine-tuning para muchas tareas.
Zero-shot y Few-shot Prompting
Zero-shot
El modelo recibe solo la instrucción, sin ejemplos. Funciona sorprendentemente bien con modelos grandes (GPT-3+), especialmente tras SFT/RLHF.
# Zero-shot: solo instrucción
prompt = """Clasifica el siguiente texto como positivo, negativo o neutral.
Texto: "La película fue entretenida pero el final me decepcionó."
Clasificación:"""
# → "Neutral" o "Mixto"
Few-shot (In-Context Learning)
Proporcionar K ejemplos (típicamente 3-8) en el prompt permite al modelo "aprender" el formato y la tarea sin actualizar pesos. Este fenómeno, descubierto con GPT-3, se llama in-context learning (ICL).
# Few-shot: 3 ejemplos + query
prompt = """Clasifica el sentimiento del texto.
Texto: "Me encanta este restaurante, la comida es increíble."
Sentimiento: Positivo
Texto: "El servicio fue pésimo y tardaron una hora."
Sentimiento: Negativo
Texto: "El lugar está bien, nada especial."
Sentimiento: Neutral
Texto: "La película fue entretenida pero el final me decepcionó."
Sentimiento:"""
# → "Mixto" o "Neutral"
📄 Paper clave
Brown et al. (2020) "Language Models are Few-Shot Learners" demostró que GPT-3 con few-shot prompting podía igualar modelos fine-tuneados en muchas tareas. arXiv:2005.14165
Chain-of-Thought (CoT) Prompting
CoT (Wei et al., 2022) mejora dramáticamente el rendimiento en tareas de razonamiento al pedir al modelo que muestre su proceso paso a paso.
# ❌ Sin CoT (directo) — falla en problemas complejos
prompt_directo = """Si tengo 3 manzanas y le doy la mitad a Juan,
luego compro 5 más y le doy 2 a María, ¿cuántas tengo?
Respuesta:"""
# → A veces responde mal
# ✅ Con CoT — resuelve correctamente
prompt_cot = """Si tengo 3 manzanas y le doy la mitad a Juan,
luego compro 5 más y le doy 2 a María, ¿cuántas tengo?
Pensemos paso a paso:
1. Empiezo con 3 manzanas
2. Le doy la mitad a Juan: 3/2 = 1.5, pero como son manzanas enteras,
le doy 1 (me quedo con 2) o redondeamos (1.5)
3. Compro 5 más: 1.5 + 5 = 6.5
4. Le doy 2 a María: 6.5 - 2 = 4.5
Respuesta: 4.5 manzanas
(O con enteros: 2 + 5 - 2 = 5 manzanas)"""
# ✅ Zero-shot CoT — más simple
prompt_zero_cot = """Si tengo 3 manzanas y le doy la mitad a Juan,
luego compro 5 más y le doy 2 a María, ¿cuántas tengo?
Let's think step by step."""
📄 Papers de CoT
- CoT: Wei et al. (2022) "Chain-of-Thought Prompting Elicits Reasoning in LLMs" arXiv:2201.11903
- Zero-shot CoT: Kojima et al. (2022) "Large Language Models are Zero-Shot Reasoners" arXiv:2205.11916
- Self-Consistency: Wang et al. (2022) arXiv:2203.11171
Técnicas avanzadas de prompting
ToT (Yao et al., 2023) generaliza CoT permitiendo al modelo explorar múltiples caminos de razonamiento como un árbol, evaluar cada rama y hacer backtracking. Útil para problemas que requieren planificación (puzzles, código).
ReAct (Yao et al., 2022) intercala pasos de razonamiento (Thought) con acciones (Action: buscar en Wikipedia, ejecutar código, etc.) y observaciones (Observation: resultado de la acción).
Patrón: Thought → Action → Observation → Thought → ... → Answer
RAG (Lewis et al., 2020) complementa el conocimiento del LLM con información recuperada de una base de documentos. Pipeline:
Forzar al LLM a generar salida estructurada (JSON, XML, tablas) mediante:
- Prompting: "Responde en formato JSON con los campos: ..."
- Function calling: schema JSON como herramienta (OpenAI, Anthropic)
- Constrained decoding: gramáticas formales (Outlines, Guidance, LMQL)
| Técnica | Cuándo usar | Mejora | Coste extra |
|---|---|---|---|
| Zero-shot | Tareas simples, modelos grandes | Baseline | Ninguno |
| Few-shot | Formato específico, tareas de nicho | +5-15% | Tokens de contexto |
| CoT | Matemáticas, lógica, razonamiento | +10-40% | Más tokens de output |
| Self-Consistency | Problemas con respuesta única | +5-15% vs CoT | N× llamadas |
| ToT | Puzzles, planificación, código | Variable | Alto (exploración) |
| RAG | Conocimiento actualizado, dominio específico | Elimina alucinaciones | Infra de retrieval |
| ReAct | Tareas que requieren herramientas | Acceso a info real | Llamadas a APIs |
🛠️ Widget: Constructor de prompt
Selecciona los componentes y genera un prompt template optimizado.
Modelos razonadores: una nueva frontera
Los modelos razonadores representan un salto conceptual: en lugar de generar una respuesta directamente, el modelo "piensa" internamente durante un tiempo variable antes de responder. Usan más compute en tiempo de inferencia (test-time compute) para resolver problemas más difíciles.
Test-Time Compute: el concepto clave
Test-time compute (TTC) se refiere al compute adicional que un modelo usa durante la inferencia para mejorar su respuesta. Hay dos estrategias principales:
📄 Paper clave
Snell et al. (2024) "Scaling LLM Test-Time Compute Optimally Can Be More Effective Than Scaling Model Parameters". Demostraron que un modelo pequeño (1-3B) con suficiente test-time compute puede superar a un modelo 14× más grande con respuesta directa. arXiv:2408.03314
Antes, solo se escalaba \(N\) (más parámetros). Ahora se puede escalar \(C_{\text{inference}}\) (más tokens de pensamiento, más candidatos) para obtener mejores resultados.
OpenAI o1 / o3: la serie de razonamiento
En septiembre de 2024, OpenAI lanzó o1-preview, el primer modelo razonador comercial. Usa chain-of-thought interna (no visible al usuario) entrenada con reinforcement learning a gran escala.
| Modelo | Fecha | Capacidad clave | Benchmarks notables |
|---|---|---|---|
| o1-preview | Sep 2024 | CoT interna, RL | AIME: 83.3%, Codeforces: 89th %ile |
| o1 | Dic 2024 | Más training, herramientas | AIME: 96.4%, GPQA: 78.8% |
| o3-mini | Ene 2025 | Eficiente, ajuste de esfuerzo | Codeforces: 96th %ile |
| o3 | 2025 | SOTA en razonamiento | ARC-AGI: 87.5%, Frontier Math |
Aunque OpenAI no ha publicado paper, el consenso de la comunidad es:
DeepSeek-R1: razonamiento open-source
DeepSeek-R1 (DeepSeek AI, enero 2025) fue el primer modelo razonador open-source con rendimiento comparable a o1. Su paper reveló los detalles del entrenamiento que OpenAI no publicó.
📄 Paper
"DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning" arXiv:2501.12948 · GitHub
Proceso de entrenamiento de R1
Panorama de modelos razonadores
| Modelo | Org. | Open? | Técnica | Benchmark |
|---|---|---|---|---|
| o1 / o3 | OpenAI | ❌ | Internal CoT + RL | AIME 96.4% |
| DeepSeek-R1 | DeepSeek | ✅ MIT | GRPO, cold start, distill | AIME 79.8% |
| QwQ-32B | Alibaba | ✅ | RL, thinking tokens | AIME 79.5% |
| Gemini 2.0 Flash Thinking | ❌ | Thinking tokens | GPQA 74% | |
| Claude 3.5 (extended thinking) | Anthropic | ❌ | Extended CoT interna | — |
| Kimi k1.5 | Moonshot | ❌ | RL + long CoT | AIME 77.5% |
| Open-Reasoner-Zero | NVIDIA | ✅ | GRPO puro (inspirado en R1-Zero) | MATH 86.4% |
📚 Papers y recursos
- "Scaling LLM Test-Time Compute" — Snell et al. arXiv:2408.03314
- "Let's Verify Step by Step" (PRM) — Lightman et al. arXiv:2305.20050
- "Large Language Monkeys" (escalado de test-time) — Brown et al. arXiv:2407.21787
- "s1: Simple Test-Time Scaling" — Muennighoff et al. arXiv:2501.19393
LLMs multimodales: más allá del texto
Los LLMs multimodales (MLLMs) extienden la capacidad de los LLMs para procesar y/o generar múltiples modalidades: texto, imágenes, audio, vídeo. No son modelos separados para cada modalidad, sino un único LLM que integra encoders especializados.
Arquitectura: cómo se integran las modalidades
El patrón dominante para LLMs multimodales sigue una estructura de tres componentes:
| Componente | Función | Ejemplos |
|---|---|---|
| Vision Encoder | Convierte imagen en secuencia de embeddings | CLIP ViT-L, SigLIP, InternViT |
| Audio Encoder | Convierte audio en embeddings | Whisper encoder, USM |
| Projection Layer | Alinea embeddings visuales al espacio del LLM | MLP lineal, Q-Former, Perceiver Resampler |
| LLM Backbone | Procesa tokens multimodales autoregressivamente | LLaMA, Qwen, Gemma, Vicuna |
Modelos multimodales clave
CLIP (Contrastive Language-Image Pre-training) aprende un espacio compartido entre imágenes y texto mediante contrastive learning sobre 400M de pares (imagen, caption) de Internet.
CLIP no genera texto, pero sus embeddings son la base de muchos modelos multimodales.
LLaVA (Liu et al., 2023) conecta CLIP ViT con LLaMA mediante una simple proyección MLP. Es el modelo multimodal open-source más influyente:
- Pre-training: 595K pares imagen-caption para alinear vision y LLM
- Instruction tuning: 158K instrucciones visuales generadas por GPT-4
- LLaVA-1.5: mejoras con MLP proyector + datos mejores → SOTA en 11 benchmarks
GPT-4V (2023) fue el primer LLM comercial con capacidad de visión de alta calidad. GPT-4o (2024) va más allá: es natively multimodal, procesando texto, imagen y audio en un único modelo end-to-end, sin pipeline de ASR.
GPT-4o puede generar voz expresiva con emociones, cantar, y entender diagramas complejos.
Gemini (Google, 2023) fue entrenado desde el inicio como modelo multimodal (a diferencia de GPT-4V que añadió visión post-hoc). Gemini 1.5 Pro acepta hasta 1M tokens (1h de vídeo, 11h de audio, 30K líneas de código).
arXiv:2312.11805 (Gemini 1.0) · arXiv:2403.05530 (Gemini 1.5)
| Modelo | Modalidades | Vision Enc. | LLM | Open? | Innovación |
|---|---|---|---|---|---|
| LLaVA-1.5 | Imagen+Texto | CLIP ViT-L | Vicuna 13B | ✅ | Simple MLP projection |
| InternVL 2.5 | Imagen+Texto | InternViT-6B | InternLM2 | ✅ | Vision encoder enorme |
| Qwen-VL | Img+Txt+Bbox | ViT | Qwen 7B | ✅ | Grounding, multi-imagen |
| GPT-4o | Txt+Img+Audio | Nativo | GPT-4 | ❌ | Any-to-any nativo |
| Gemini 1.5 | Txt+Img+Audio+Video | Nativo | MoE | ❌ | 1M tokens context |
| Claude 3.5 | Imagen+Texto | — | Claude | ❌ | Excelente visión |
| Pixtral | Imagen+Texto | Custom ViT | Mistral | ✅ | Resolución variable |
Cómo se entrenan los LLMs multimodales
El entrenamiento típico sigue un proceso en fases:
# ═══════════════════════════════════════════════════
# Inferencia multimodal con LLaVA
# ═══════════════════════════════════════════════════
from transformers import LlavaNextProcessor, LlavaNextForConditionalGeneration
from PIL import Image
import torch
# 1. Cargar modelo
processor = LlavaNextProcessor.from_pretrained("llava-hf/llava-v1.6-mistral-7b-hf")
model = LlavaNextForConditionalGeneration.from_pretrained(
"llava-hf/llava-v1.6-mistral-7b-hf",
torch_dtype=torch.float16,
device_map="auto",
)
# 2. Preparar input multimodal
image = Image.open("mi_imagen.jpg")
prompt = "[INST] \nDescribe esta imagen en detalle. ¿Qué objetos ves y qué relaciones hay entre ellos? [/INST]"
inputs = processor(prompt, image, return_tensors="pt").to("cuda")
# 3. Generar
output = model.generate(**inputs, max_new_tokens=300, do_sample=True, temperature=0.7)
print(processor.decode(output[0], skip_special_tokens=True))
📚 Papers y recursos multimodales
- CLIP: Radford et al. (2021) arXiv:2103.00020
- LLaVA: Liu et al. (2023) arXiv:2304.08485
- Flamingo: Alayrac et al. (2022) arXiv:2204.14198
- Whisper: Radford et al. (2022) arXiv:2212.04356
- ImageBind: Girdhar et al. (2023) arXiv:2305.05665
De LLMs a agentes: el salto
Un agente es un LLM que, además de generar texto, puede tomar acciones en el mundo real: ejecutar código, buscar en internet, enviar emails, interactuar con APIs, navegar por webs, etc. El LLM actúa como "cerebro" que decide qué herramienta usar y cuándo.
Function Calling: la base del agente
Function calling (o tool use) es la capacidad de un LLM de generar llamadas estructuradas a funciones externas en lugar de texto plano. El LLM no ejecuta la función — genera los parámetros en JSON y el sistema host la ejecuta.
# ═══════════════════════════════════════════════════
# Function Calling con OpenAI API
# ═══════════════════════════════════════════════════
from openai import OpenAI
import json
client = OpenAI()
# 1. Definir herramientas (schema JSON)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Obtener el clima actual de una ciudad",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "Nombre de la ciudad"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
},
{
"type": "function",
"function": {
"name": "search_web",
"description": "Buscar información en internet",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Consulta de búsqueda"}
},
"required": ["query"]
}
}
}
]
# 2. Llamar al LLM
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "¿Qué tiempo hace en Madrid?"}],
tools=tools,
tool_choice="auto", # El modelo decide si usar herramienta
)
# 3. El modelo genera una llamada a función (no ejecuta)
tool_call = response.choices[0].message.tool_calls[0]
print(f"Función: {tool_call.function.name}")
print(f"Args: {tool_call.function.arguments}")
# → Función: get_weather
# → Args: {"city": "Madrid", "unit": "celsius"}
# 4. TÚ ejecutas la función y devuelves el resultado
result = get_weather(city="Madrid", unit="celsius") # Tu implementación
messages.append({"role": "tool", "content": json.dumps(result),
"tool_call_id": tool_call.id})
# 5. El LLM genera la respuesta final con el resultado
final = client.chat.completions.create(
model="gpt-4o", messages=messages
)
print(final.choices[0].message.content)
# → "En Madrid hace 22°C con cielo despejado."
MCP: Model Context Protocol
🔌 MCP (Anthropic, 2024)
El Model Context Protocol es un estándar abierto para conectar LLMs con herramientas y fuentes de datos de forma estandarizada. Define un protocolo cliente-servidor donde:
- MCP Server: expone herramientas, recursos y prompts
- MCP Client: el LLM/aplicación que consume las herramientas
- Transporte: stdio (local) o SSE/HTTP (remoto)
Frameworks de agentes
| Framework | Organización | Enfoque | Mejor para |
|---|---|---|---|
| LangChain | LangChain Inc. | Modular, chains/agents/tools | Prototipos, RAG, flujos complejos |
| LangGraph | LangChain Inc. | Grafos de estado, ciclos | Agentes multi-step con estado |
| CrewAI | CrewAI | Multi-agente, roles | Equipos de agentes colaborativos |
| AutoGen | Microsoft | Multi-agente conversacional | Debates entre agentes, código |
| Smolagents | Hugging Face | Code agents, minimalista | Agentes que escriben código Python |
| OpenAI Assistants | OpenAI | API managed, threads | Producción con OpenAI |
| Claude Code | Anthropic | Agente de código CLI | Desarrollo de software autónomo |
# ═══════════════════════════════════════════════════
# Agente ReAct con LangGraph
# ═══════════════════════════════════════════════════
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
# 1. Definir herramientas
@tool
def calculate(expression: str) -> str:
"""Evalúa una expresión matemática."""
return str(eval(expression))
@tool
def search(query: str) -> str:
"""Busca información en una base de conocimiento."""
# Tu implementación de búsqueda
return f"Resultado para: {query}"
# 2. Crear agente ReAct
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_react_agent(llm, tools=[calculate, search])
# 3. Ejecutar
result = agent.invoke({
"messages": [("user", "¿Cuánto es el PIB de España dividido por su población?")]
})
# El agente internamente:
# Thought: Necesito buscar el PIB y la población de España
# Action: search("PIB España 2024")
# Observation: "El PIB de España en 2024 es ~1.5T EUR"
# Action: search("población España 2024")
# Observation: "La población de España es ~48M"
# Action: calculate("1500000000000 / 48000000")
# Observation: "31250.0"
# Answer: "El PIB per cápita de España es ~31,250 EUR"
Patrones de diseño de agentes
El patrón más popular. El agente alterna entre razonamiento (Thought), acción (Action) y observación (Observation) hasta llegar a la respuesta.
Un planificador (LLM) crea un plan de alto nivel (lista de pasos), y un ejecutor (otro LLM o el mismo) ejecuta cada paso. Permite replanning si un paso falla.
Múltiples agentes con roles diferentes (researcher, coder, reviewer) colaboran para resolver una tarea compleja. Pueden debatir, revisar el trabajo de otros, y llegar a consenso. Ejemplos: AutoGen, CrewAI, ChatDev.
arXiv:2308.00352 (MetaGPT)
Reflexion (Shinn et al., 2023): el agente revisa su propia salida, identifica errores, y se corrige. Usa un "critic" o autoevaluación para mejorar iterativamente.
En lugar de usar herramientas predefinidas, el agente escribe y ejecuta código Python como su mecanismo de acción principal. Más flexible y composable que function calling.
Usado por: HuggingFace smolagents, OpenAI Code Interpreter, Claude Artifacts. Ref: arXiv:2401.00812 (Executable Code Actions)
Evaluación, limitaciones y futuro
| Benchmark | Qué evalúa | SOTA |
|---|---|---|
| SWE-bench | Resolver issues reales de GitHub | ~50% (Claude 3.5 + agentic) |
| WebArena | Tareas web (navegar, comprar, buscar) | ~35% |
| GAIA | Tareas generales con herramientas | ~70% (nivel 1) |
| TAU-bench | Tool use real (airline, retail) | ~50% |
| HumanEval | Generación de código | ~95%+ (GPT-4o, Claude 3.5) |
- Reliability: los agentes aún fallan en ~30-70% de tareas complejas
- Error compounding: cada paso tiene probabilidad de error, que se acumula
- Cost: muchas llamadas a la API, tokens de reasoning → caro
- Safety: un agente con acceso a herramientas puede causar daño real
- Evaluation: difícil medir el progreso sin benchmarks estandarizados
📚 Papers y recursos de agentes
- ReAct: Yao et al. (2022) arXiv:2210.03629
- Toolformer: Schick et al. (2023) arXiv:2302.04761
- Voyager: Wang et al. (2023) arXiv:2305.16291
- Survey: LLM-based Agents: Wang et al. (2024) arXiv:2308.11432
- LangChain: GitHub
- LangGraph: GitHub
🏗️ Widget: Selector de arquitectura de agente
Según tu caso de uso, te recomendamos el patrón y framework de agente más adecuado.
Recursos y referencias generales
| Recurso | Tipo | Enlace |
|---|---|---|
| Andrej Karpathy — "Let's build GPT" | Video/Tutorial | YouTube |
| Lilian Weng — "LLM Powered Autonomous Agents" | Blog | Blog |
| Jay Alammar — "The Illustrated Transformer" | Blog visual | Blog |
| Sebastian Raschka — "Build an LLM from Scratch" | Libro | GitHub |
| Hugging Face NLP Course | Curso | HF Course |
| LMSYS Chatbot Arena | Benchmark | Arena |
| Open LLM Leaderboard | Rankings | HF Spaces |
| Awesome LLM — curated list | Lista | GitHub |