Inicio / Artículos

De la predicción de token siguiente al código funcional: cómo generan Python los LLMs

Explicación en orden de los tokens, softmax, temperatura, capas de autoatención y capas feed-forward, con un ejemplo paso a paso de clasificación y los límites estrictos que surgen de la predicción.

Editor: REACTAPP.TOP9 min de lectura1998 palabras

Fuentes: How LLMs Actually Work: From Predicting the Next Word to Writing Code.

Herramientas como ChatGPT y Copilot escriben funciones, corrigen errores y explican algoritmos, y puede parecer que están haciendo algo más que simplemente completar texto. El modelo mental que se presenta a continuación parte de lo básico: la predicción de tokens, la atención, y la razón por la cual el mecanismo que completa una oración también genera código Python válido.

Una pregunta, formulada repetidamente

Ya sea que el resultado sea un haiku, un correo electrónico de marketing o un algoritmo de ordenamiento por fusión, un modelo de lenguaje responde una sola pregunta una y otra vez: teniendo en cuenta todo lo visto hasta ahora, ¿cuál es el siguiente token más probable?

No existe una comprensión semántica en el sentido tradicional, ni hay una etapa en la que el modelo decida escribir una función antes de generar la palabra def. Predice token por token. Con miles de millones de parámetros y texto de entrenamiento que suma cientos de miles de millones de tokens, las predicciones terminan pareciendo mucho más bien razonamiento.

Qué es un token

La precisión es importante antes de abordar la predicción. Los modelos no trabajan con caracteres o palabras, sino con tokens, unidades subpalabras generadas por un algoritmo como el Byte Pair Encoding. En resumen:

  • Las palabras comunes suelen convertirse en un único token, como "the", "def" y "return".
  • Las palabras poco comunes se dividen en partes, por lo que "unhappiness" se convierte en ["un", "happiness"].
  • Los símbolos de código suelen ser tokens individuales, como por ejemplo "(", ":", "==" y "->".
  • En el caso de GPT-4, un token equivale a aproximadamente 0.75 palabras en inglés, mientras que en código está más cerca de 3 o 4 caracteres, ya que el código está repleto de tokens de un solo carácter como : y (.

    El modelo también cuenta con un vocabulario, una lista fija de tokens conocidos que generalmente comprende entre 50,000 y 100,000 entradas. En cada paso asigna una probabilidad a cada entrada y elige la más probable o toma una muestra de la distribución, siendo la elección determinada por la temperatura.

    El bucle de predicción

    Para la secuencia “El gato se sentó en el”, la cantidad que se debe calcular es una probabilidad condicional:

    P(next_token | "The", "cat", "sat", "on", "the")
    

    Esa es una distribución sobre todo el vocabulario. Una pasada forward a través de la red genera un vector del tamaño del vocabulario, que la función softmax convierte en una distribución de probabilidades válida:

    P(token_i) = exp(logit_i) / Σⱼ exp(logit_j)
    

    En el decodificación codiciosa se elige el token con mayor probabilidad. De lo contrario, se selecciona un token en proporción a la distribución, siendo temperature el parámetro que controla su dispersión:

    • temperature = 0 siempre elige el token con mayor probabilidad, por lo que la salida es determinista.
    • temperature = 1 realiza muestras desde la distribución original, lo que resulta en resultados variados y creativos.
    • Cuando este valor es superior a 1, la distribución se aplana y la salida se vuelve más aleatoria.
    • Cuando es inferior a 1, la distribución se vuelve más estrecha y la salida se vuelve más conservadora.

    Por esta razón, un mismo prompt puede generar respuestas diferentes en ejecuciones distintas.

    El Transformer

    La función que convierte una secuencia de tokens en una distribución de tokens siguientes es un Transformer, específicamente uno dedicado únicamente al decodificador, y este es el diseño subyacente en GPT, Llama, Mistral y Claude. El flujo general es el siguiente:

    Token IDs → Embedding layer → [Attention + FFN] × N layers → Linear head → Softmax → P(next token)
    

    Las capas, en orden:

    1. Capa de incrustación. Cada identificador de token entero se convierte en un vector denso de tamaño d_model; por ejemplo, 4096 en Llama-3 8B. Las incrustaciones posicionales, o RoPE en los modelos modernos, añaden información sobre el orden.
    2. Capas Transformer, repetidas N veces. Cada una contiene atención autónoma multi-cabeza, una red feed-forward, normalización de capa aplicada antes de cada subcapa al estilo “pre-norm”, y conexiones residuales.
    3. Cabeza lineal y softmax. El estado oculto final se mapea a logits de forma [|V|], y el softmax genera la distribución.

    Atención autónoma

    La autoatención permite que un token observe a otros tokens en la secuencia para crear una imagen más completa de sí mismo. Es lo que da a los Transformers una ventaja sobre las RNN: cada token puede llegar a cualquier otro token en un solo paso, sin que el gradiente disminuya con la distancia.

    Con n tokens, cada uno de ellos se proyecta de tres maneras:

    Q = XWᴬ_Q    (Query: what am I looking for?)
    K = XWᴬ_K    (Key: what do I contain?)
    V = XWᴬ_V    (Value: what do I contribute?)
    

    Aquí X es la matriz de entrada de forma [n, d_model] y las tres matrices W son pesos aprendidos. La puntuación entre el token i, que actúa como consulta, y el token j, que actúa como clave, es:

    score(i, j) = qᵢ · kⱼᵀ / √dₖ
    

    Dividir entre la raíz cuadrada de la dimensión clave evita que los productos escalar crezcan demasiado cuando dₖ es alto, lo cual haría que softmax se desplazara a regiones con gradientes muy pequeños. El cálculo completo es:

    Attention(Q, K, V) = softmax(QKᵀ / √dₖ) · V
    

    En un modelo de solo decodificador como GPT, la atención es causal o enmascarada: el token i solo puede prestar atención a posiciones hasta i. Las posiciones futuras reciben una puntuación de infinito negativo antes de la función softmax, por lo que sus pesos son exactamente cero.

    Atención multi-cabeza ejecuta h funciones de atención independientes en paralelo, cada una con la dimensión más pequeña d_model / h, y concatena las salidas:

    MultiHead(Q, K, V) = Concat(head₁, ..., headₕ) · W_O
    headᵢ = Attention(QWᵢ_Q, KWᵢ_K, VWᵢ_V)
    

    Diferentes componentes se encargan de tratar relaciones distintas. Uno puede seguir las dependencias sintácticas, otro la coreferencia y otro la proximidad posicional.

    La red feed-forward

    Después de la atención, la representación de cada token pasa por una FFN por posición:

    FFN(x) = max(0, xW₁ + b₁)W₂ + b₂
    

    Las arquitecturas modernas como Llama y Mistral utilizan SwiGLU en su lugar:

    FFN(x) = (SiLU(xW_gate) ⊙ xW_up) · W_down
    

    La mayor parte del conocimiento memorizado por un modelo se encuentra en el FFN. Funciona como un almacén de tipo clave-valor para asociaciones factuales. La atención dirige la información entre tokens, y el FFN busca los hechos y patrones almacenados. En los modelos grandes, el FFN tiene aproximadamente cuatro veces más dimensiones que d_model. Llama-3 70B tiene d_model = 8192 y un tamaño intermedio de 28672, y es allí donde residen la mayoría de los parámetros.

    Por qué los modelos pueden escribir código

    El código es una secuencia de tokens, al igual que el lenguaje natural. Para un modelo, una función de Python no es nada especial, solo una serie de tokens como def, sort, _list, (, arr, ), : y así sucesivamente.

    Un resultado sintácticamente válido es puramente una consecuencia de la distribución de entrenamiento. Considere estas probabilidades condicionales:

    P("(" | ..., "def", " quicksort") ≈ 1.0
    P(":" | ..., "def", " quicksort", "(", "arr", ")") ≈ 1.0
    P("return" | context inside function body) >> P("import" | same context)
    

    Tienen un pico pronunciado porque el modelo ha visto millones de archivos de Python que obedecen todas las mismas reglas. La gramática de Python no está codificada de forma fija en ninguna parte de la red; surge de las estadísticas del corpus.

    También explica por qué a veces los modelos generan código perfectamente estructurado pero lógicamente incorrecto. Ellos maximizan la probabilidad del siguiente token teniendo en cuenta la distribución de entrenamiento. No ejecutan el código ni lo verifican.

    Una función de ordenamiento, paso a paso

    Supongamos que la instrucción es “Escribe una función de Python para ordenar una lista”. El modelo la trata como una secuencia de tokens y agrega la salida uno por uno. Aproximadamente:

    • Paso 1, después de la instrucción: def con una probabilidad de aproximadamente 0.91.
    • Paso 2, después de def: sort con una probabilidad de aproximadamente 0.78.
    • Paso 3: _list o ( con una probabilidad de aproximadamente 0.65.
    • Paso 4, después de sort(: arr o lst alrededor de 0.71.
    • Pasos 5 a 7: ), luego :, luego un salto de línea, cada uno alrededor de 0.99.
    • Paso 8: el sangrado de cuatro espacios alrededor de 0.97.

    En los pasos 5 a 8 el modelo alcanza una certeza relativa con respecto a los tokens sintácticos. Eso no significa que entienda Python; lo que ocurre es una simple completación de patrones, aprendida a partir de un corpus en el que todas las definiciones de función se ven iguales.

    Las verdaderas decisiones se toman antes, en los pasos 1 a 4, donde se elige el nombre de la función, el nombre de los parámetros y la estructura general. Esas decisiones están influenciadas por el contenido de la instrucción mediante la atención. El token sort en la instrucción tiene un alto peso de atención cuando se genera el nombre de la función.

    Temperatura en la generación de código

    Copilot y herramientas similares suelen funcionar a baja temperatura, alrededor de 0.1 a 0.3, para el código:

    • Los tokens sintácticos necesitan ser casi deterministas.
    • Suele haber una única implementación correcta.
    • Las APIs inventadas se convierten en un importante motivo de fallo a alta temperatura.

    Para partes creativas como los nombres de variables, las cadenas de documentación y los comentarios, es aceptable una temperatura ligeramente más alta. Algunas herramientas también utilizan búsqueda por haz, la cual mantiene activas al mismo tiempo las secuencias parciales de los k mejores y elige al final aquella con la mejor probabilidad conjunta.

    Por qué los modelos más grandes se comportan de manera diferente

    Un modelo de 7B y uno de 70B comparten la misma arquitectura. La diferencia radica en la escala: más capas, un d_model más amplio y más cabezas de atención. Sin embargo, el modelo más grande muestra mejoras cualitativas, como razonamiento multi-paso, código más correcto y aprendizaje emergente dentro del contexto.

    A gran escala, el modelo aprende más que simplemente las estadísticas de los tokens superficiales. Construye representaciones comprimidas de patrones más profundos como la estructura algorítmica, las dependencias lógicas y las restricciones de tipo. Un modelo de 70 mil millones de parámetros ha visto suficiente código con errores junto a sus fallos de prueba como para vincular implícitamente ciertos patrones con la corrección. Esta es la base empírica de la hipótesis de escalado: la capacidad sigue una curva suave en términos de capacidad de cómputo, datos y parámetros, y la calidad del código la sigue con la misma fiabilidad que cualquier otra habilidad.

    Límites derivados del diseño

    Conocer el mecanismo revela algunos límites innegociables:

    1. Ejecución. No existe un entorno de ejecución dentro del modelo. Lo que emite se asemeja a la salida de una ejecución correcta, pero en realidad no se ejecutó nada.
    2. Exactitud garantizada. La predicción maximiza la verosimilitud según la distribución de entrenamiento, no la validez lógica.
    3. Verdadera novedad. No se puede inventar un algoritmo sin precedentes estadísticos en los datos de entrenamiento. El modelo puede combinar y adaptarse, pero no crear algo original.
    4. Recuperación exacta. No existe una tabla de consulta. Toda la memoria está distribuida entre los pesos, por lo que las APIs, las firmas de funciones y las versiones de las bibliotecas a veces pueden generar información errónea.

    Ninguno de estos problemas es un error que aguarde corrección. Surgen directamente de la arquitectura, y conocerlos permite a cualquiera utilizar mejor a los asistentes de programación.

    Resumen general

    • Un token es una unidad subpalabra, equivalente a aproximadamente 0.75 palabras en inglés.
    • La predicción se realiza mediante softmax sobre el vocabulario en cada paso.
    • La autoatención permite que cada token preste atención a todos los tokens anteriores a través de productos escalar de consulta-clave.
    • La atención multi-cabeza ejecuta varias de estas operaciones en paralelo para capturar diferentes relaciones.
    • El FFN funciona como una memoria de tipo clave-valor para las asociaciones factuales.
    • La generación de código funciona de manera similar a la generación de texto, con la sintaxis que surge de las estadísticas de entrenamiento.
    • La temperatura determina cuán aguda es la distribución de muestreo.
    • Los límites inherentes son la ausencia de ejecución, la falta de corrección garantizada y la ausencia de verdadera novedad.

    Todo en este mecanismo, desde la atención y el FFN hasta los residuos y la norma de capa, tiene un único propósito: hacer que la probabilidad condicional del siguiente token, dada toda la información anterior, sea lo más precisa posible. El resto surge de forma emergente.

    Leer más

  • Notas prácticas: Cómo funcionan realmente los LLMs: Tokens, Transformers y el siguiente token — Guía detallada de las Notas prácticas: Cómo funcionan realmente los LLMs: Tokens, Transformers y el siguiente token: contratos, verificaciones y espacios para código listo para usar para los equipos que implementan este patrón.
  • Cincuenta años de investigación en búsqueda oculta dentro de tu pipeline RAG — El fragmentado en RAG, la búsqueda híbrida, HyDE, el reclasificado y las evaluaciones tienen antepasados de décadas en la recuperación de información. Un recorrido por la investigación y sus limitaciones.
  • Notas prácticas: ZQ Intelligence: Orchestrator-Agentes Especialistas para Finanzas — Guía paso a paso de las Notas prácticas: ZQ Intelligence: Orchestrator-Agentes Especialistas para Finanzas: contratos, cheques y espacios para código adicional para los equipos que implementan este patrón.
  • Por qué las lenguas indias costan más tokens en LLMs y cómo se arreglan los tokenizadores — La misma oración requiere 5 tokens en inglés y 34 en tamil. Se explica cómo los datos de entrenamiento BPE causan esto, qué cambios en el reequilibrio y el tamaño del vocabulario se necesitan, y cómo funciona la expansión del vocabulario.