Del prompt al token: cómo un LLM convierte el texto en números y viceversa
Seguimos un prompt corto a través de la tokenización, los embeddings, la atención, las capas feed-forward, softmax y el muestreo para ver cómo elige realmente un modelo cada palabra siguiente.
Dentro del modelo no hay inglés
Pulsa Enter en un prompt y una GPU empieza a procesar miles de millones de operaciones de coma flotante antes de que aparezca el primer token. Ninguna de esas operaciones toca una palabra en inglés.
Tomemos un fragmento conocido:
"The cat sat on the "
Cuando "mat" aparece en pantalla, ese fragmento ya se ha desmontado, se ha convertido en geometría con miles de dimensiones y ha pasado por decenas de capas matemáticas idénticas.
Hablamos de esto con bastante ligereza. El modelo «leyó» el prompt, «entendió» el contexto y «eligió» una continuación sensata. Nada de eso ocurre literalmente. El programa en ejecución no contiene inglés, ni reglas gramaticales que separen sujeto y predicado, ni definiciones de diccionario guardadas. Lo que ocurre es una cadena de montaje de operaciones con tensores: una cadena de texto se convierte en enteros, los enteros en coordenadas en el espacio, las coordenadas se mezclan a lo largo de decenas de capas y, al final, se lanza una vez un dado trucado.
Para entender de verdad los modelos de lenguaje, deja las metáforas y sigue los datos. Esta es la ruta que recorre tu texto.
Paso 1: el tokenizador
Las redes neuronales no pueden trabajar con caracteres en bruto, porque no hay álgebra que hacer con la letra «c». Necesitan números. Por eso, antes de que el prompt se acerque siquiera al modelo, lo procesa un programa aparte llamado tokenizador.
El tokenizador corta la cadena en trozos llamados tokens. Un token puede ser una palabra entera, una sílaba, un prefijo o un solo signo de puntuación. Nuestra frase se divide limpiamente en cinco:
"The"" cat"" sat"" on"" the"
Fíjate en los espacios iniciales. No son erratas. Los tokenizadores modernos pegan al token el espacio que precede a la palabra, de modo que "cat" y " cat" son dos tokens distintos.
Cada token se corresponde con un entero en una tabla de vocabulario fija. Con un vocabulario de, por ejemplo, 50257 tokens, la frase se convierte en cinco números:
[464, 3797, 3372, 319, 262]
Todavía no se ha ejecutado ninguna capa del modelo de lenguaje y la cadena ya ha desaparecido. Solo quedan cinco enteros.
Paso 2: la tabla de embeddings
Ahora entra en juego la red propiamente dicha, y su primera tarea es resolver un problema básico. Los enteros no sirven para el cálculo. El número 3797, que representa « cat», no está más cerca de «dog» que de «airplane». Son etiquetas arbitrarias, y con etiquetas no se puede hacer geometría.
La solución es convertir cada entero en una lista densa de números de coma flotante, un vector de embedding. Imagina una tabla de consulta gigantesca en la memoria de la GPU. Supongamos que el vocabulario tiene 32.000 tokens y la dimensión oculta es 4.096. La tabla es entonces una matriz de 32.000 filas por 4.096 columnas, y el modelo simplemente consulta:
- El token
464obtiene la fila 464. - El token
3797obtiene la fila 3797. - El token
3372obtiene la fila 3372. - El token
319obtiene la fila 319. - El token
262obtiene la fila 262.
En esta fase no hay aritmética. Es una simple lectura de memoria. Lo que sale es una matriz de forma [5, 4096], cinco filas de 4.096 valores continuos cada una.
Ahora cada token es un punto en un espacio de 4.096 dimensiones, donde la dirección tiene significado y las posiciones codifican relaciones aprendidas a partir de miles de millones de ejemplos de entrenamiento.
Antes de que los vectores sigan bajando se añade un ingrediente más: la información de posición. Las operaciones con matrices por sí solas pueden desordenar las palabras, así que el modelo mezcla señales de posición en las coordenadas. Sin eso, «The cat sat on the» y «The on sat cat the» le parecerían idénticas a la red.
Paso 3: la pila del transformer
La matriz [5, 4096] entra ahora en el transformer. En un diseño típico de 7.000 millones de parámetros, la pila tiene 32 bloques idénticos. La matriz conserva su forma en todos ellos: entra en la capa 1 y sale de la capa 32 como [5, 4096]. Lo que cambia es la información guardada en esos números.
Recién salido de la tabla de embeddings, cada vector está aislado. El vector de " sat" sabe que significa «se sentó», pero no puede decir quién, dónde ni por qué. Dos mecanismos dentro de cada bloque lo resuelven.
Atención
Aquí los vectores se comunican. La atención permite que cada posición mire hacia las anteriores y extraiga lo que sea relevante.
Tomemos el quinto token, " the". Mide su similitud con "The", " cat", " sat" y " on". Como tiene que ayudar a predecir qué sustantivo sigue a una preposición, su vector se apoya mucho en la acción y en el sujeto. Mediante productos escalares entre esas posiciones, la capa de atención actualiza cada vector con el contexto de sus vecinos.
La red feed-forward
Una vez que los tokens han intercambiado información, cada fila pasa por su cuenta por una red feed-forward (un MLP). Si la atención es que los tokens hablen entre sí, esta capa es cada token haciendo sus propias cuentas. Proyecta el contexto recién reunido a través de miles de pesos aprendidos, lo que permite al modelo activar asociaciones factuales almacenadas en sus parámetros.
Todo esto se repite 32 veces. En la capa 32, el quinto vector ya no es un sustituto genérico de la palabra " the", porque ha absorbido la historia de toda la frase. Ahora representa un artículo determinado que sigue a un gato sentado.
Unembedding
Para producir la siguiente palabra, las cuatro primeras filas ya no importan, así que el modelo se queda solo con la última: un vector de 4.096 números. Ahora el problema del embedding se recorre al revés. Tiene un punto en un espacio de 4.096 dimensiones y necesita una palabra.
Una segunda matriz, la matriz de unembedding (a menudo simplemente la tabla de embeddings traspuesta), multiplica ese vector y reparte sus 4.096 valores de nuevo sobre todo el vocabulario. El resultado es una puntuación sin normalizar para cada token del vocabulario, por ejemplo:
Arriba del todo verías " mat" con 16,2 y " rug" con 13,8, seguidos de " floor" con 12,1 y " couch" con 10,4. Muy abajo en la lista, "LeBron James" tiene -12,5.
Estas puntuaciones en bruto son los logits. Un logit más alto significa que los parámetros aprendidos de la red encontraron una coincidencia geométrica más fuerte entre el estado final del prompt y ese candidato.
Softmax
Los logits no se pueden usar tal cual. Algunos son grandes y positivos, otros negativos, y su suma es arbitraria. Así que el modelo pasa todo el vector por softmax: para cada elemento, se eleva e a su puntuación y se divide por la suma de esas exponenciales sobre todos los elementos.
Softmax hace dos cosas. La exponencial vuelve estrictamente positivo cada valor. La división por el total obliga a que todo sume 1,0. Lo que obtienes es una distribución de probabilidad auténtica sobre los 32.000 tokens, más o menos así:
El líder, " mat", se lleva el 68,4 %. " rug" obtiene el 17,1 %, " floor" el 9,2 % y " couch" el 4,1 %. En el otro extremo, a " LeBron James" le queda un 0,000001 %.
Muestreo
Todo lo anterior es determinista. Con los mismos pesos y la misma entrada, las probabilidades no varían ni en un decimal. La imprevisibilidad de los LLM entra en el último paso, el muestreo.
Si el sistema tomara siempre el token más probable, aquí " mat" con el 68,4 %, eso sería decodificación voraz. Es determinista, pero en salidas largas tiende a caer en bucles repetitivos y poco naturales. Por eso el software lanza un dado ponderado. Aproximadamente el 68 % de las veces sale " mat", y alrededor del 17 %, " rug".
El ajuste de temperatura en una llamada a la API cambia la forma de esta curva antes de lanzar el dado. Una temperatura baja exagera las diferencias y puede llevar " mat" hacia el 95 %. Una temperatura alta aplana la curva, de modo que los tokens peor situados tienen muchas más opciones de salir elegidos.
Se lanza el dado y gana el token con ID 2603.
Destokenización y el bucle
El programa busca el ID 2603 en un mapa de vocabulario inverso, encuentra la cadena " mat" y la envía a tu terminal o navegador.
Aquí aparece el hecho central de la inferencia: en ningún momento sabe el modelo qué viene después de " mat". No puede planificar tres palabras por adelantado ni guarda un esquema del párrafo que está escribiendo. Para avanzar, añade la palabra nueva a la entrada y forma un prompt completamente nuevo:
"The cat sat on the mat"
Tokeniza las seis palabras, obtiene los embeddings de las seis filas, pasa las seis posiciones por las 32 capas, calcula los logits de la sexta posición, aplica softmax, lanza el dado y elige el séptimo token. Ese ciclo completo, de cadena a tensor y a tirada de dado, se repite una vez por cada token que aparece en tu pantalla.
Preguntas que plantea esta cadena
Vista con ojos de ingeniero, la mecánica plantea preguntas incómodas. Parece que cada palabra generada exige pasar toda la conversación acumulada por miles de millones de operaciones, así que los chats largos deberían dejar el hardware casi parado. (Por qué no ocurre se debe al almacenamiento en caché en memoria, tema para otro día.)
El primer paso es todavía más desconcertante: el salto del lenguaje humano a los números. Antes de que actuara la atención o se ejecutara una sola capa, el prompt ya estaba troceado en fragmentos numéricos arbitrarios. ¿Por qué subpalabras y no caracteres, palabras completas o bytes en bruto? ¿Por qué las cadenas poco habituales o las líneas de Python hacen que el número de tokens se comporte de forma impredecible? La tokenización es la primera caja de la cadena, y es la que toca abrir a continuación.