12 papers de IA que lo cambiaron todo: explicación detallada
1. Resumen general
La mayoría de los sistemas de IA que usas a diario — ChatGPT, Midjourney, Google Search con AI Overview — se basan en alrededor de una docena de papers de investigación. Este artículo repasa esos 12 papers, explicando sus ideas centrales en lenguaje accesible, e ilustrando cada concepto con código Java conciso. Tras leerlo, comprenderás por qué Transformer domina el mundo del NLP, por qué RAG resuelve las alucinaciones, y por qué un simple prompt como “piensa paso a paso” es tan poderoso.
2. AlexNet (2012) — deep learning comienza a “ver”
Antes de AlexNet, la visión por computadora se basaba en ingeniería de características manual. AlexNet utilizó redes neuronales convolucionales (CNN) con activación ReLU y dropout, entrenado en GPU, y superó a todos los competidores en ImageNet 2012 con un error casi 10 puntos porcentuales menor. Este fue el disparo de salida de la era del deep learning.
public class ConvOutputSizeCalculator {
public static int outputSize(int inputSize, int kernelSize, int stride, int padding) {
return (inputSize - kernelSize + 2 * padding) / stride + 1;
}
public static void main(String[] args) {
// Imagen de entrada de AlexNet: 227x227, kernel 11x11, stride 4
int size = outputSize(227, 11, 4, 0);
System.out.println(size);
}
}
55
outputSize calcula el tamaño del mapa de características después de una capa convolucional. Con entrada 227×227 y kernel 11×11 stride 4, la salida es 55×55×96 — exactamente el tamaño de la primera capa de AlexNet. ReLU evita que el gradiente “muera” como sucedía con sigmoid, por lo que las redes más profundas se podían entrenar correctamente.
3. GAN (2014) — dos redes enfrentadas para generar imágenes realistas
Generative Adversarial Network pone dos redes en una contienda: el generator intenta crear imágenes falsas para engañar al discriminator, mientras que el discriminator intenta distinguir imágenes reales de falsas. Ambos mejoran continuamente a lo largo de cada ronda de entrenamiento.
public record GanLosses(double discriminatorLoss, double generatorLoss) {}
public class GanLossCalculator {
public static GanLosses compute(double probReal, double probFake) {
double dLoss = -(Math.log(probReal) + Math.log(1 - probFake));
double gLoss = -Math.log(probFake);
return new GanLosses(dLoss, gLoss);
}
}
probReal es la probabilidad de que el discriminator identifique correctamente la imagen real, probFake es la probabilidad de que sea engañado por el generator. El discriminator quiere que probReal → 1 y probFake → 0; el generator quiere lo opuesto. Este es un juego de suma cero típico.
Nota: Los GAN son famosos por ser difíciles de entrenar — es fácil caer en mode collapse (el generator solo genera unos pocos tipos de imágenes repetidas). Los modelos de difusión posteriores son mucho más estables, por lo que la mayoría de los sistemas de generación de imágenes modernos (DALL·E, Stable Diffusion) ya no usan GAN.
4. Transformer (2017) — “Attention Is All You Need”
Transformer elimina completamente RNN/LSTM, reemplazándolos con self-attention: cada token mira directamente a todos los demás tokens en la secuencia para calcular su relevancia, sin necesidad de procesamiento secuencial. Esta es la arquitectura base de GPT, Claude, Llama, BERT.
public class ScaledDotProductAttention {
public static double[] attendFirstToken(double[][] query, double[][] key) {
int seqLen = key.length;
int dim = query[0].length;
double scale = Math.sqrt(dim);
double[] scores = new double[seqLen];
for (int j = 0; j < seqLen; j++) {
double dot = 0;
for (int k = 0; k < dim; k++) dot += query[0][k] * key[j][k];
scores[j] = dot / scale;
}
return softmax(scores);
}
private static double[] softmax(double[] row) {
double max = Arrays.stream(row).max().orElse(0);
double sum = 0;
double[] exps = new double[row.length];
for (int i = 0; i < row.length; i++) {
exps[i] = Math.exp(row[i] - max);
sum += exps[i];
}
for (int i = 0; i < exps.length; i++) exps[i] /= sum;
return exps;
}
}
La línea dot / scale divide el producto punto por sqrt(dim) para evitar que los valores sean demasiado grandes y saturen la softmax. El resultado de softmax son los pesos de atención — los tokens más relevantes para el token actual obtendrán pesos más altos, que se usan para combinar los vectores de valor.
5. Scaling Laws (2020) — la pérdida disminuye siguiendo una ley de potencia
OpenAI descubrió que: aumentar el número de parámetros, datos o computación exponencialmente, la pérdida disminuye siguiendo una curva de ley de potencia suave y predecible — no hay “magia”, solo escalar correctamente.
public class ScalingLawEstimator {
// L(N) = (Nc / N)^alpha — N: número de parámetros en billones, Nc, alpha: constantes empíricas
public static double estimateLoss(double paramsBillion, double nc, double alpha) {
return Math.pow(nc / paramsBillion, alpha);
}
}
Con nc y alpha fijas a partir de datos empíricos, aumentar paramsBillion hace que estimateLoss disminuya gradualmente pero cada vez más lentamente (retornos decrecientes). Esta es la razón por la que los laboratorios de IA invierten cientos de millones en computación: la disminución de la pérdida es predecible, no es una apuesta.
Nota: Las leyes de escala no son infinitas. Después de cierto punto, para reducir la pérdida un poco más, necesitas aumentar la computación exponencialmente — por eso la industria está pivotando hacia mejorar los datos y la arquitectura en lugar de simplemente hacer todo más grande.
6. GPT-3 (2020) — la escala crea nuevas capacidades
GPT-3 con 175 mil millones de parámetros demostró que: siendo lo suficientemente grande, el modelo puede hacer few-shot learning — solo necesita unos pocos ejemplos en el prompt, sin necesidad de fine-tuning.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
@Service
public class FewShotClassifier {
private final ChatClient chatClient;
public FewShotClassifier(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
public String classifySentiment(String review) {
String prompt = """
Reseña: "Producto bueno, envío rápido" -> Positiva
Reseña: "Artículo defectuoso, no funciona" -> Negativa
Reseña: "%s" ->
""".formatted(review);
return chatClient.prompt(prompt).call().content();
}
}
Los dos ejemplos en el prompt actúan como “enseñanza” para que el modelo entienda el formato de respuesta justo en el contexto — sin necesidad de entrenamiento adicional. Esta es precisamente una capacidad emergente que los modelos más pequeños no pueden lograr bien.
7. InstructGPT & RLHF (2022) — transformar LLM en bruto en un asistente útil
El GPT-3 original era bueno prediciendo el siguiente token, pero no “obedecía” — podía dar respuestas fuera de tema u ofensivas. InstructGPT utiliza Reinforcement Learning from Human Feedback (RLHF): los humanos califican las respuestas, luego se entrena un reward model, y finalmente se usa ese reward model para optimizar la política usando PPO.
public record Completion(String text, double rewardScore) {}
public class RewardBasedSelector {
public Completion pickBest(List<Completion> candidates) {
return candidates.stream()
.max(Comparator.comparingDouble(Completion::rewardScore))
.orElseThrow();
}
}
El código anterior solo ilustra el paso final: seleccionar la completion con la puntuación de recompensa más alta según lo evaluado por el reward model. En la práctica, PPO actualiza los pesos del policy model gradualmente para que genere respuestas de puntuación alta directamente, sin necesidad de seleccionar después.
Nota: RLHF requiere una gran cantidad de datos etiquetados por humanos (rankings), lo que es costoso y susceptible a sesgos del evaluador. Técnicas como DPO (Direct Preference Optimization) surgieron después para reducir estos costos.
8. ViT (2020) — las imágenes también pueden ser una “oración”
Vision Transformer divide la imagen en pequeños parches (por ejemplo, 16×16 píxeles), aplana cada parche en un vector, y luego los trata como tokens que se pasan al encoder Transformer — la arquitectura es idéntica al procesamiento de texto.
public class PatchEmbeddingCalculator {
public static int numPatches(int imageSize, int patchSize) {
int gridSize = imageSize / patchSize;
return gridSize * gridSize;
}
}
Con una imagen de 224×224 y parches de 16×16, numPatches devuelve 196 — equivalente a una “oración” de 196 tokens que se pasan al Transformer. De esta manera, ViT reutiliza todas las técnicas de atención que demostraron ser efectivas en NLP para tareas de visión, y supera a CNN cuando hay datos de entrenamiento suficientemente grandes.
9. DDPM (2020) — agregar ruido y aprender a eliminarlo
Denoising Diffusion Probabilistic Model es la base de todos los modelos de difusión modernos: el proceso forward agrega ruido Gaussiano gradualmente a la imagen en múltiples pasos, y el proceso reverse aprende a predecir y eliminar ese ruido para reconstruir la imagen original.
public class ForwardDiffusion {
public static double[] addNoise(double[] x0, double alphaBarT, Random random) {
double[] xt = new double[x0.length];
for (int i = 0; i < x0.length; i++) {
double noise = random.nextGaussian();
xt[i] = Math.sqrt(alphaBarT) * x0[i] + Math.sqrt(1 - alphaBarT) * noise;
}
return xt;
}
}
alphaBarT controla la proporción de imagen original versus ruido en el paso t: cercano a 1 significa que está cerca de la imagen original, cercano a 0 significa que es casi puro ruido. El modelo de generación aprende a invertir este proceso — comenzando desde ruido puro, eliminando gradualmente el ruido paso a paso para obtener una imagen significativa.
10. Latent Diffusion (2021) — eliminación de ruido en espacio comprimido
Ejecutar difusión directamente en píxeles consume mucho cómputo. Latent Diffusion comprime la imagen en un espacio latente más pequeño usando un autoencoder, ejecuta todo el proceso de denoising allí, y luego decodifica de vuelta a imagen — este es el diseño detrás de Stable Diffusion.
public class LatentCompressionCalculator {
public static long pixelCount(int width, int height, int channels) {
return (long) width * height * channels;
}
}
pixelCount(512, 512, 3) = 786_432 // espacio de píxeles
pixelCount(64, 64, 4) = 16_384 // espacio latente
Una compresión de casi 48 veces permite que la difusión se ejecute mucho más rápido mientras mantiene la calidad de imagen, porque la mayoría de la información “redundante” en el espacio de píxeles (áreas de color uniforme, pequeños detalles) es eliminada por el autoencoder durante la compresión.
11. CLIP (2021) — conectar imágenes y texto en un mismo espacio
CLIP entrena aprendizaje contrastivo en cientos de millones de pares (imagen, caption): los pares correctos tienen embeddings cercanos, los pares incorrectos están lejos. El resultado es un espacio común que permite comparar texto e imagen usando similitud de coseno.
@Service
public class ImageTextMatcher {
private final EmbeddingModel embeddingModel;
public ImageTextMatcher(EmbeddingModel embeddingModel) {
this.embeddingModel = embeddingModel;
}
public double similarity(String caption, float[] imageEmbedding) {
float[] textEmbedding = embeddingModel.embed(caption);
return cosine(textEmbedding, imageEmbedding);
}
private double cosine(float[] a, float[] b) {
double dot = 0, normA = 0, normB = 0;
for (int i = 0; i < a.length; i++) {
dot += a[i] * b[i];
normA += a[i] * a[i];
normB += b[i] * b[i];
}
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}
}
similarity devuelve un valor cercano a 1 si el caption coincide con el contenido de la imagen, cercano a 0 o negativo si no está relacionado. Este es el mecanismo detrás de la búsqueda de imágenes por descripción de texto (text-to-image search) que muchos sitios de comercio electrónico están usando.
12. Chain-of-Thought (2022) — un prompt abre el razonamiento
Solo necesitas agregar la frase “piensa paso a paso” al prompt, y los LLM grandes descomponen automáticamente problemas complejos en pasos pequeños, reduciendo significativamente errores de cálculo y lógica comparado con responder directamente.
public String solveWithReasoning(ChatClient chatClient, String question) {
String prompt = """
Por favor, piensa paso a paso antes de responder.
Pregunta: %s
Razonamiento:
""".formatted(question);
return chatClient.prompt(prompt).call().content();
}
Pedir al modelo que “razone” antes de finalizar la respuesta lo obliga a generar tokens intermedios como punto de apoyo — similar a cómo los humanos escriben borradores antes de responder preguntas difíciles.
Nota: Chain-of-Thought aumenta el número de tokens generados, lo que resulta en mayor costo y latencia. Para preguntas simples (búsqueda directa de hechos), forzar CoT solo ralentiza sin mejorar la precisión.
13. RAG (2020) — recuperar y luego generar, sin alucinar
Retrieval-Augmented Generation vincula un LLM con un paso de recuperación de documentos reales antes de generar la respuesta, ayudando a reducir alucinaciones y permitiendo respuestas basadas en datos actualizados fuera del alcance del entrenamiento original.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
@Service
public class DocumentAnsweringService {
private final VectorStore vectorStore;
private final ChatClient chatClient;
public DocumentAnsweringService(VectorStore vectorStore, ChatClient.Builder builder) {
this.vectorStore = vectorStore;
this.chatClient = builder.build();
}
public String answer(String question) {
List<Document> relevant = vectorStore.similaritySearch(
SearchRequest.query(question).withTopK(3));
String context = relevant.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n---\n"));
String prompt = """
Basándote en los siguientes documentos, responde la pregunta. Si no hay información, di "No está claro".
Documentos:
%s
Pregunta: %s
""".formatted(context, question);
return chatClient.prompt(prompt).call().content();
}
}
similaritySearch recupera los 3 fragmentos de documentos más relevantes para la pregunta, los combina en el prompt como contexto, y luego el modelo responde basándose en ese contexto en lugar de “recordar” vagamente del entrenamiento.
class DocumentAnsweringServiceTest {
@Test
void shouldReturnUnknownWhenNoRelevantDocument() {
VectorStore emptyStore = mock(VectorStore.class);
when(emptyStore.similaritySearch(any())).thenReturn(List.of());
ChatClient stubClient = mock(ChatClient.class, RETURNS_DEEP_STUBS);
when(stubClient.prompt(anyString()).call().content()).thenReturn("No está claro");
ChatClient.Builder builder = mock(ChatClient.Builder.class);
when(builder.build()).thenReturn(stubClient);
DocumentAnsweringService service = new DocumentAnsweringService(emptyStore, builder);
String result = service.answer("¿En qué año se fundó la empresa?");
assertThat(result).contains("No está claro");
}
}
El test confirma que cuando no se encuentran documentos relevantes, la respuesta debe admitir “No está claro” en lugar de inventar una — ese es el objetivo de grounding de RAG.
Nota: Si tu repositorio de documentos tiene solo decenas de páginas, meter todo directamente en la context window es más simple y barato que construir un pipeline RAG completo con vector store. RAG solo vale la pena cuando los datos son grandes o cambian frecuentemente.
14. Conclusión
Estos 12 papers no son independientes — se construyen unos sobre otros: Transformer es la base para GPT-3 y ViT; Scaling Laws explica por qué GPT-3 funciona; RLHF convierte GPT-3 en ChatGPT; DDPM es la base de Latent Diffusion; CLIP es el puente para que los modelos de difusión entiendan prompts de texto. Comprender cada pieza te ayuda a leer papers nuevos más rápidamente, porque la mayoría de las ideas “nuevas” hoy en día son variaciones o combinaciones de estos fundamentos.