36 · Proyecto final: un GPT diminuto en NumPy
Construye el PASO HACIA ADELANTE de un GPT solo-decoder en NumPy puro — embeddings, bloques de atención enmascarada y decodificación voraz — exactamente lo que se ejecuta dentro de GPT en la inferencia.
El paso hacia adelante de un GPT solo-decoder es solo esto: embed + codificación posicional → bloques de atención enmascarada apilados → LayerNorm final → cabeza lineal → logits. Argmax de la ÚLTIMA posición para obtener el siguiente token. Construimos todo en NumPy.
Sin esto:
Sin construir tú mismo el paso hacia adelante, GPT sigue siendo una caja negra; con él, has visto el mecanismo exacto que se ejecuta dentro de todo gran modelo de lenguaje en la inferencia.
Este es el proyecto final del capítulo — y, en realidad, de todo el arco desde el perceptrón en la lección bc-dl-01 hasta aquí. Vamos a construir el paso hacia adelante de un GPT diminuto solo-decoder en NumPy puro.
Para ser honestos sobre lo que es posible dentro del presupuesto de Pyodide, hacemos solo inferencia: un paso hacia adelante y decodificación voraz (greedy). No hay entrenamiento — ni retropropagación, ni descenso de gradiente — porque eso sería demasiado pesado aquí. Pero esa es la parte hermosa: lo que construimos ES, mecánicamente, exactamente lo que se ejecuta dentro de GPT cuando escribes un prompt y te devuelve texto en streaming. Un GPT entrenado es este mismo paso hacia adelante con pesos ajustados a billones de tokens; uno sin entrenar (pesos aleatorios, como el nuestro) ejecuta el cómputo idéntico pero produce galimatías. El mecanismo es real; solo los pesos son aleatorios.
El modelo es solo-decoder (como todo LLM moderno): no hay encoder ni atención cruzada — solo una pila de bloques de auto-atención enmascarada. Cada bloque es:
x → AutoAtenciónEnmascarada → Add & Norm → FFN → Add & Norm
El paso hacia adelante completo es:
tokens → embedding de tokens + codificación posicional → N bloques de atención enmascarada → LayerNorm final → cabeza lineal → logits (seq, vocab)
Para predecir el siguiente token tomas los logits de la última posición y eliges el argmax (greedy) — o muestreas del softmax para dar variedad. Luego añades ese token y vuelves a ejecutar todo. Ese bucle es la generación autoregresiva. Construyámoslo.
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Read-along de PyTorch: el mismo GPT diminuto como nn.Module — nn.Embedding (token + posición), una ModuleList de bloques de atención enmascarada, LayerNorm final, cabeza Linear y un método generate voraz
En un GPT solo-decoder, ¿qué produce la predicción del siguiente token?
- El paso hacia adelante de un GPT solo-decoder es: embedding de token + codificación posicional → N bloques de auto-atención enmascarada → LayerNorm final → cabeza lineal → logits (seq, vocab).
- Para generar, toma los logits de la ÚLTIMA posición, haz argmax (greedy) o muestrea el siguiente token, añádelo y repite — ese bucle es la decodificación autoregresiva.
- Pesos aleatorios sin entrenar ejecutan el mismo cómputo idéntico que un GPT real pero producen galimatías: el mecanismo es real, solo difieren los pesos — la escala + el entrenamiento es lo que convierte esto en GPT/LLaMA/Claude.
Este paso hacia adelante es literalmente lo que se ejecuta dentro de GPT, LLaMA, Mistral y Claude cada vez que generan un token. Los servidores de inferencia ejecutan exactamente este bucle (más caché de KV y muestreo) a escala de miles de millones de parámetros.
Si lo quitas: Entenderías los transformers en teoría pero nunca habrías visto ejecutarse el bucle de generación de extremo a extremo, dejando '¿cómo produce texto GPT en realidad?' como una abstracción en lugar de código que has construido y ejecutado.