Fabián Murgado
~10 min
Los modelos de lenguaje como ChatGPT, Gemini o Claude no leen el texto palabra a palabra de forma secuencial como lo hacemos los humanos. Leen todo el texto a la vez, en paralelo, esto proporciona muchas ventajas, como la paralelización en GPUs, pero también plantea un problema: ¿cómo sabe el modelo el orden de las palabras? Vamos a explorar la solución más adoptada por los modelos modernos: RoPE.
La importancia de la posición
En los modelos de lenguaje modernos, basados en la arquitectura transformer, el primer paso es un preprocesado del texto en el que este se pasa a una representación numérica, más apta para un modelo de deep learning. Este proceso consta de dos partes, por un lado el tokenizado, que divide el texto en fragmentos (tokens), y por otro lado el embedding, que crea representaciones vectoriales de estos tokens (embeddings).
Un embedding, por sí solo, captura el significado de un token. Sin embargo, el significado de un texto no depende solamente del significado de cada token, sino también del orden de estos. "El perro persigue al gato" y "El gato persigue al perro" contienen exactamente los mismos tokens, pero no significan lo mismo.
Por defecto, un LLM de arquitectura transformer recibe una secuencia de embeddings y los procesa en paralelo, como un conjunto desordenado. Aquí "en paralelo" no significa que los tokens se procesen de forma aislada, sino que en cada capa cada token mira a todos los demás, decide cuánto pesa cada uno de ellos y se reinterpreta a partir de esa mezcla. Ese mecanismo es la atención, y es también donde la falta de orden hace daño: mezclar un token con los que lo rodean sin saber cuáles vienen antes o después es tratar el texto como una bolsa de palabras. Por eso se necesita alguna forma de introducir la noción de orden.
Dos preguntas, no una lista
Es tentador contar la historia de la codificación posicional como una cronología: primero APE, luego ALiBi, luego RoPE, cada una mejor que la anterior. Pero se entiende mucho mejor si en lugar de una lista la vemos como un espacio de diseño con dos preguntas independientes:
¿Qué se codifica: la posición absoluta o la distancia relativa? Esta pregunta determina cómo se comporta el modelo con secuencias más largas que las vistas en entrenamiento. Una posición absoluta que nunca se ha visto es un valor desconocido, mientras que una distancia relativa de 3 tokens es la misma en la posición 10 que en la 10.000.
¿En qué punto del proceso se inyecta esa información? Esta pregunta determina cuánto interfiere la posición con el contenido. No es lo mismo modificar el embedding de entrada —que arrastra esa modificación por toda la red— que intervenir únicamente en el cálculo de la atención, dejando intacto lo que cada token significa.
APE, ALiBi, T5 y RoPE son respuestas distintas a este par de preguntas. Vamos a verlas.
Respuestas parciales
APE
La primera solución, introducida en el propio Attention Is All You Need, fue Absolute Position Encoding (APE). Este mecanismo consiste en que antes de que el modelo procese el embedding de cada token, se calcula un vector fijo para cada posición de la secuencia y se suma directamente al embedding. De esta forma el embedding codifica información tanto semántica como posicional.
Una solución obvia hubiera sido simplemente numerar los tokens: asignar el valor 1 al primero, 2 al segundo, y así sucesivamente. El problema de esta aproximación es que esos números crecen sin límite y tienen escalas muy distintas a los valores de los embeddings, que suelen ser números pequeños entre -1 y 1. Sumar números grandes a un vector de valores decimales distorsionaría completamente la información semántica del embedding. Es por esto que se utilizan las funciones seno y coseno, que siempre producen valores entre -1 y 1.
El uso de las funciones seno y coseno de forma alternada no es arbitrario. El seno y el coseno están desfasados 90° entre sí, lo que los hace complementarios. Juntos pueden describir inequívocamente cualquier punto en una rotación. Este detalle, como veremos, anticipa la idea central de RoPE.
Volviendo a nuestras dos preguntas, APE responde absoluta a la primera y en el embedding de entrada a la segunda. Y de ahí salen sus dos limitaciones.
La primera es consecuencia de codificar posiciones absolutas: el modelo no generaliza bien para secuencias más largas que las vistas en entrenamiento. Si entrenamos el modelo con secuencias de 512 tokens, los vectores posicionales de las posiciones 513, 514 o 515 son patrones que nunca ha visto y no sabe interpretar. Además, la distancia relativa —que suele ser lo relevante en el lenguaje— no está codificada explícitamente: el modelo tiene que reconstruirla a partir de dos posiciones absolutas, y le resulta más fácil saber que un token está en la posición 5 que saber que está a 3 posiciones de otro.
La segunda es consecuencia de actuar sobre el embedding de entrada: una vez sumado el vector posicional, la información de posición y la de significado viven en el mismo espacio y son indistinguibles para las capas siguientes. El modelo tiene que dedicar capacidad a separar ambas señales, y esa contaminación se arrastra por toda la red, no solo por el mecanismo de atención.
Sesgos sobre la atención: ALiBi y T5
Otra solución relevante es ALiBi (Attention with Linear Biases), de hecho posterior a PoPE, aunque durante un tiempo convivieron. Su propuesta es dejar intactos los embeddings y penalizar la atención entre dos tokens en función de la distancia que los separa: cuanto más lejos están, menos atención se prestan.
Un apunte antes de la fórmula: la atención es un número por cada pareja de tokens, no por token, y se calcula en varias copias paralelas, las cabezas de atención, cada una de las cuales hace un cálculo distinto, fijándose en diferentes aspectos del texto.
ALiBi responde relativo a la primera pregunta y en la matriz de atención a la segunda, y con eso corrige los dos problemas de APE de golpe. Los embeddings quedan limpios, y la penalización sigue una función que se puede evaluar para cualquier distancia, la haya visto el modelo o no: si nunca vio una secuencia de 600 tokens, simplemente aplica la fórmula.
El precio es una limitación distinta. La penalización no se aprende: es un sesgo fijo que el modelo no puede desactivar. Cada cabeza de atención tiene su propia pendiente —en progresión geométrica—, así que las cabezas de pendiente pequeña sí pueden mirar lejos, pero incluso ellas siguen obligadas a decaer monótonamente con la distancia. ALiBi impone como axioma algo que en el lenguaje solo es cierto de media: que lo cercano importa más que lo lejano. Un nombre propio mencionado en la primera página de un documento largo sigue siendo relevante cien mil tokens después.
La idea de penalizar por distancia, sin embargo, es anterior a ALiBi, y no tiene por qué ser tan rígida. El sesgo relativo que introdujo T5 en 2019 entrena un valor propio para cada rango de distancias en lugar de fijar una pendiente a mano, así que ni viene impuesto ni está obligado a decaer: si al modelo le conviene que cierto rango lejano pese mucho, puede aprenderlo. La aportación de ALiBi, dos años después, fue mostrar que ese aprendizaje era prescindible: un sesgo fijo bastaba, y además extrapolaba a secuencias más largas que las vistas en entrenamiento.
Aprendido o fijo, los dos comparten algo: el ajuste se suma encima de una puntuación de atención ya calculada y depende solo de la distancia, sin mirar qué dicen los tokens. La posición corrige la comparación entre contenidos, pero no participa en ella.
Codificando la posición como rotaciones
RoPE (Rotary Position Embedding) es el mecanismo de codificación de la información posicional introducido en el paper RoFormer (2021) y posteriormente adoptado por la mayoría de los LLM modernos.
De cada token se derivan tres vectores con papeles distintos: el query, lo que ese token busca; el key, lo que ofrece a los demás; y el value, la información que aporta si alguien le atiende. La puntuación de atención sale de comparar el query de un token con el key de otro: queries y keys deciden quién habla con quién, los values son lo que se dice.
Aquí conviene deshacer un malentendido habitual, porque RoPE suele describirse como "APE pero rotando en vez de sumando". La operación cambia, sí, pero lo importante es dónde ocurre: RoPE no toca el embedding de entrada. Actúa dentro de cada capa de atención, rotando los vectores query y key justo antes de calcular su producto escalar. Los vectores value y el resto de la representación del token quedan intactos. Es decir, la posición influye en con quién habla cada token, pero no en qué contiene ese token.
RoPE se basa en una propiedad fundamental pero simple de la geometría: el producto escalar entre dos vectores rotados en el mismo plano depende únicamente de la diferencia entre sus ángulos de rotación, no de los ángulos absolutos. Esto es exactamente lo que necesitamos, porque el producto entre query y key es lo que el modelo utiliza para decidir cuánta atención se prestan dos tokens. Como cada token se rota una cantidad proporcional a su posición, la diferencia de ángulos entre dos tokens es precisamente su distancia relativa. La posición entra como absoluta y sale como relativa, sin necesidad de calcular explícitamente la distancia entre cada par de tokens.
El diagrama es solo una simplificación de lo que hace RoPE. En la práctica hay una diferencia clave: RoPE no rota el vector completo, sino que divide sus dimensiones en parejas y hace rotaciones 2D en vez de una sola rotación -dimensional. Esto se debe a dos motivos. Por un lado, las rotaciones 2D son mucho más eficientes computacionalmente. Por otro, nos permiten rotar cada pareja a una frecuencia distinta, de forma que capturen distancias a distintas escalas.
El mecanismo es muy similar al de un reloj, solo que en lugar de medir tiempo mide distancia en una secuencia de tokens. Cada pareja de dimensiones, con su propia frecuencia de rotación, representa una aguja de este reloj. Las parejas de frecuencia alta (rotan rápido) capturan las distancias cortas, mientras que las de frecuencia baja (rotan lentamente) capturan las distancias largas. Juntas, describen la distancia entre tokens a todas las escalas a la vez, igual que segundero, minutero y horario juntos determinan la hora exacta.
La fórmula de RoPE para una pareja de dimensiones (x₁, x₂) en la posición m es:
Y el ángulo de rotación de cada pareja:
Donde:
- : las dos dimensiones del vector query o key que forman la pareja
- : posición del token en la secuencia
- : frecuencia de rotación de la pareja i (decrece con i)
- : índice de la pareja (0, 1, 2, ...)
- : dimensión total del vector
- : misma constante base que en APE, controla el rango de frecuencias
Con esto, RoPE ocupa la casilla que ninguna de las anteriores cubría: es relativo, como ALiBi y T5, pero actúa dentro del producto query-key en lugar de sobre el resultado de ese producto. Y esa distinción es la que importa. Un sesgo, aprendido o no, ajusta una comparación que ya se ha hecho, sin saber qué contenían los tokens comparados. RoPE, en cambio, cambia la comparación misma: la distancia entra en el cálculo junto con el contenido, y de ahí sale una puntuación en la que ambos han intervenido a la vez.
Con un matiz: RoPE tampoco es del todo neutro. Al girar cada pareja a un ritmo distinto, sus contribuciones se desalinean con la distancia y la atención tiende a decaer. Pero ese decaimiento es un efecto lateral de la geometría, no una regla impuesta: es irregular en vez de monótono, y el modelo puede compensarlo. Un sesgo blando que el entrenamiento contrarresta, no una penalización que se aplica pase lo que pase.
Resumiendo las dos preguntas del principio:
Qué codifica | Dónde actúa | |
APE | Posición absoluta | Sobre el embedding de entrada |
ALiBi | Distancia relativa | Sobre la puntuación de atención ya calculada (sesgo fijo) |
T5 | Distancia relativa | Sobre la puntuación de atención ya calculada (sesgo aprendido) |
RoPE | Distancia relativa | Dentro del cálculo de la puntuación de atención |
Lo que RoPE no resuelve
Aquí hay que ser honesto, porque se repite mucho que RoPE resuelve la extrapolación y no es cierto. Un modelo entrenado con RoPE a 4.096 tokens tampoco funciona bien a 16.000. La fórmula se puede evaluar para cualquier posición, sí, pero las parejas de frecuencia baja apenas completan una fracción de vuelta durante el entrenamiento, así que al superar la longitud vista entran en regiones angulares que nunca han aparecido. El modelo sabe calcular la rotación; lo que no sabe es qué significa.
Precisamente por eso existe toda una familia de técnicas para extender la ventana de contexto de modelos ya entrenados con RoPE: Position Interpolation, que comprime las posiciones para que quepan en el rango conocido, el NTK-aware scaling, o YaRN, que ajusta cada frecuencia de forma distinta según lo que haya visto durante el entrenamiento. Todas ellas son parches sobre RoPE, y su existencia es la mejor prueba de que RoPE por sí solo no extrapola.
Lo que explica su adopción, entonces, no es la extrapolación, ni tampoco que delegue en el entrenamiento la política de qué distancia importa —eso ya lo hacía T5—. Es el sitio donde ocurre: RoPE no corrige una comparación ya hecha, sino que hace que la distancia forme parte de la comparación misma. Modula cómo se miden entre sí query y key, con un coste añadido despreciable y sin ensuciar lo que cada token significa. De ahí que resulte lo bastante neutro como para admitir después parches como YaRN, algo que un sesgo rígido como el de ALiBi no permite igual de bien.
No es casualidad que modelos como LLaMA, Gemma o Qwen lo hayan adoptado como estándar, y que muy probablemente esté también detrás de modelos como GPT o Claude, cuyos detalles técnicos no son públicos. Cuando un modelo entiende que "a 3 tokens de distancia" significa lo mismo en la posición 10 que en la 10.000, es RoPE quien está girando las agujas.
Referencias
- Attention is All You Need (2017)
- RoFormer: Enhanced Transformer with Rotary Position Embedding (2021)
- Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation (2021)
- Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer (2019)
- Extending Context Window of Large Language Models via Positional Interpolation (2023)
- YaRN: Efficient Context Window Extension of Large Language Models (2023)