Respuesta corta: qué logra el Byte Latent Transformer (BLT)
BLT (Pagnoni et al., 2024, FAIR at Meta) es un modelo de lenguaje sin tokenizador: lee bytes y los agrupa en parches según la entropía del siguiente byte. A 8B parámetros y con el mismo presupuesto de entrenamiento, promedia 61.1 en siete benchmarks frente a 60.0 de un Llama 3 con tokenizador.
Motivación: por qué quitarle el tokenizador a un modelo de lenguaje
Casi todo en un modelo de lenguaje grande (LLM) se aprende de punta a punta, salvo un paso: la tokenización. El tokenizador corta el texto en piezas de un vocabulario fijo que se decide antes de entrenar. Llama 3, por ejemplo, usa un tokenizador BPE (byte-pair encoding) con un vocabulario de 128K tokens.
Los autores, un equipo de FAIR at Meta con coautores de la Universidad de Washington y la Universidad de Chicago, listan los costos de ese paso fijo. Los tokens sesgan cómo se comprime el texto: el modelo se vuelve sensible al dominio y al ruido en la entrada, sabe poco de ortografía y trata peor a los idiomas con menos datos. Un token como "genial" llega al modelo como un número; el modelo nunca ve sus letras.
La alternativa obvia es entrenar directo sobre bytes. El problema es el costo. Un texto en bytes es varias veces más largo que en tokens, y un Transformer gasta cómputo en cada posición. El paper aclara un punto que suele malentenderse: a gran escala, lo caro no es la atención, sino las capas feed-forward grandes que corren en cada byte. Por eso los trucos de atención eficiente ayudaron sobre todo a modelos pequeños.
Hay otra limitación de los tokens. Para que cada token cubra más bytes (y el modelo dé menos pasos) hay que agrandar el vocabulario, lo que agranda la tabla de embeddings y la capa de salida. Según el paper, Llama 3 subió el tamaño medio de token de 3.7 a 4.4 bytes a cambio de una tabla de embeddings 4x más grande que la de Llama 2. Ese intercambio deja poco margen para mover el costo de inferencia.
El Byte Latent Transformer (BLT) propone otra salida: no usar vocabulario. Agrupa bytes en parches (patches) de tamaño variable y gasta el cómputo grande por parche, no por byte. La pregunta del paper es si eso alcanza a los modelos con tokenizador cuando se compara con el mismo presupuesto de cómputo.
Cómo funciona BLT: de bytes a parches y de regreso
BLT tiene tres piezas. Un codificador local (local encoder) pequeño lee los bytes y arma una representación por parche. Un Transformer latente grande (latent transformer) procesa la secuencia de parches y predice el siguiente parche. Un decodificador local (local decoder) convierte esa predicción de vuelta en bytes, uno por uno. El Transformer latente se lleva casi todo el cómputo, así que el número de parches decide el costo.
Primer paso de BLT: medir qué tan difícil es el siguiente byte
La idea central de BLT es decidir dónde cortar según la dificultad. Para eso entrenan aparte un modelo de lenguaje de bytes pequeño, de 100M parámetros y una ventana de 512 bytes. Con él calculan la entropía del siguiente byte, que es la ecuación (1) del paper:
$$H(x_i) = -\sum_{v \in \mathcal{V}} p_e(x_i = v \mid \boldsymbol{x}_{\lt i}) \log p_e(x_i = v \mid \boldsymbol{x}_{\lt i})$$
- $x_i$: el byte en la posición $i$; $\boldsymbol{x}_{\lt i}$ son todos los bytes anteriores.
- $\mathcal{V}$: el vocabulario de bytes, es decir, los 256 valores posibles.
- $p_e(x_i = v \mid \boldsymbol{x}_{\lt i})$: la probabilidad que el modelo de entropía le da a que el siguiente byte sea $v$, dado lo que ya leyó.
- $H(x_i)$: la entropía, que mide la incertidumbre. Vale cero si el modelo está seguro de un solo byte y crece cuando reparte la probabilidad entre muchos.
Una aclaración de notación: la ecuación (1) del PDF aparece sin el signo menos; aquí lo escribimos porque así se define la entropía y sin él el valor saldría negativo. La intuición: al terminar una palabra conocida la entropía cae casi a cero; al empezar una palabra nueva se dispara, porque pueden venir muchas cosas.
Segundo paso de BLT: cortar donde la entropía sube
Con las entropías, BLT marca fronteras de parche. El paper prueba dos reglas:
$$H(x_t) > \theta_g \qquad \text{o bien} \qquad H(x_t) - H(x_{t-1}) > \theta_r$$
- $\theta_g$: umbral global. Si la entropía del byte $x_t$ lo supera, ahí empieza un parche nuevo.
- $\theta_r$: umbral relativo. Corta cuando la entropía sube de golpe respecto al byte anterior; los autores la llaman restricción aproximadamente monotónica.
Si subes el umbral, hay menos cortes, parches más largos y menos pasos del Transformer latente. Si lo bajas, ocurre lo contrario. Así BLT controla el tamaño medio de parche, algo que un tokenizador no puede mover sin cambiar su vocabulario. Además, la regla solo mira bytes pasados, y eso permite decidir las fronteras mientras genera texto.
La gráfica de abajo ilustra la regla global con entropías inventadas para la frase "Python es genial".
Tercer paso de BLT: no perder la información de los bytes
Un parche de bytes no tiene un embedding propio en una tabla, como los tokens. Para darle contexto a cada byte, BLT suma embeddings de los n-gramas de bytes que terminan en él, buscados con una función hash. Es la ecuación (3):
$$e_i = x_i + \sum_{n=3,\ldots,8} E_n^{hash}(\mathrm{Hash}(g_{i,n}))$$
- $x_i$: el embedding del byte $i$ solo.
- $g_{i,n}$: el n-grama de los $n$ bytes que terminan en la posición $i$, con $n$ de 3 a 8.
- $\mathrm{Hash}$: un hash polinomial que manda cada n-grama a una fila de la tabla $E_n^{hash}$, de tamaño fijo.
- $e_i$: el embedding enriquecido que entra al codificador local.
La intuición: el byte "l" al final de "genial" no es igual al de "lápiz", y los n-gramas le avisan al modelo en qué contexto está. Después, capas de atención cruzada (cross-attention) juntan los bytes de cada parche en un solo vector para el Transformer latente, y el decodificador hace lo inverso. El paper además divide $e_i$ entre el número de tamaños de n-grama más uno, y todos sus modelos usan 500,000 hashes.
Para comparar modelos con y sin tokenizador, el paper no usa perplejidad, que depende del tokenizador. Usa bits por byte, $\mathrm{BPB}(x) = \mathcal{L}_{CE}(x) / (\ln 2 \cdot n_{bytes})$: la pérdida de entropía cruzada repartida entre los bytes del texto. Menos es mejor.
Resultados de BLT frente a Llama 2 y Llama 3 con tokenizador
Los autores entrenaron sus propios modelos con tokenizador como base (baseline), con los mismos datos y el mismo presupuesto de FLOPs de entrenamiento que BLT. También fijaron el número de bytes por lote para que ningún modelo viera más contexto que otro. Es una comparación controlada, pero son modelos del propio equipo, no los Llama publicados por Meta.
Leyes de escalamiento con el mismo cómputo
Con el dataset de Llama 2 entrenaron modelos de 1B a 8B parámetros en el régimen óptimo de cómputo (compute-optimal). Según la Figura 6, BLT con parches por entropía iguala o mejora el BPB de sus contrapartes BPE en todo ese rango. Con parches más largos, de 6 y hasta 8 bytes (frente a 3.7 y 4.4 bytes por token de Llama 2 y Llama 3), sus curvas quedan entre las de Llama 2 y Llama 3; el de 8 bytes empieza peor que Llama 2 a 1B y termina mejor a 7B. Como los FLOPs de inferencia bajan en proporción inversa al tamaño de parche, los autores estiman que parches de 8 bytes ahorran casi 50% de los FLOPs de inferencia. Es una estimación teórica, no un tiempo medido.
Mismo costo de inferencia, modelo más grande
El título del paper viene de este experimento. Con el costo de inferencia fijo, BLT puede gastar el ahorro de los parches largos en un Transformer latente más grande. En la Figura 1, los BLT con parches de 6 y 8 bytes empiezan peor que los modelos BPE del mismo costo, pero los rebasan pasado un punto de cruce: 150B bytes de entrenamiento en la clase pequeña, donde el óptimo BPE es 50B, y 1T bytes en la grande, donde el óptimo es 400B. Según los autores, eso favorece a BLT cuando se entrena con más datos que el óptimo, algo común en los modelos actuales.
Tareas con un modelo de 8B
Para medir tareas entrenaron tres modelos de 8B en un dataset nuevo, BLT-1T, con el mismo presupuesto: un Llama 3 con tokenizador, BLT-Space (corta en espacios) y BLT-Entropy (corta por entropía). En promedio de siete tareas, BLT-Entropy saca 61.1, Llama 3 60.0 y BLT-Space 58.0. BLT-Entropy gana en 4 de 7 tareas; por ejemplo, HumanEval sube de 31.1 a 35.4, pero MMLU baja un poco, de 58.1 a 57.4.
El matiz importante: BLT-Entropy tiene 4.5 bytes por parche, casi lo mismo que los 4.4 de Llama 3, así que en esta tabla no ahorra cómputo de inferencia. Además, en inferencia bajaron el umbral de entropía de 0.6 a 0.1, lo que según el paper mejora las tareas a cambio de más pasos. BLT-Space sí usa parches de 6.1 bytes y pierde dos puntos de promedio.
Robustez, caracteres y traducción
Donde BLT se separa es en tareas que necesitan ver letras. En HellaSwag con ruido (texto en mayúsculas, con letras borradas o repetidas), BLT promedia 64.3 frente a 56.9 del Llama 3 entrenado con los mismos datos; Llama 3.1, entrenado con 16T tokens, también llega a 64.3. En CUTE, un benchmark de manipular caracteres, BLT saca 54.1 frente a 27.5 de Llama 3 y 20.0 de Llama 3.1, con 99.9 en las tareas de deletreo.
No todo es ventaja: en fonología (G2P) Llama 3.1 gana con 18.9 frente a 13.0, y en CUTE los modelos con tokenizador ganan en borrar e insertar palabras. En traducción con FLORES-101, BLT promedia 14.0 BLEU traduciendo hacia el inglés frente a 12.1 de Llama 3, y 6.4 frente a 5.9 desde el inglés, con las mayores diferencias en idiomas con pocos datos.
Por último, probaron convertir un modelo con tokenizador en BLT: inicializar el Transformer latente con los pesos de Llama 3.1. Con el mismo cómputo, ese BLT saca 63.7 en MMLU, muy arriba de los modelos entrenados desde cero, aunque abajo del Llama 3.1 original (66.3).
Limitaciones de BLT: qué no prueba el paper
- FLOPs teóricos, no tiempo real. Todas las comparaciones de costo son FLOPs calculados. Los propios autores dicen que su implementación puede no estar a la par de los modelos con tokenizador en tiempo de reloj (wall-clock).
- El ahorro y la calidad no vienen del mismo modelo. El "hasta 50% menos FLOPs" sale de parches de 8 bytes en curvas de BPB. El BLT que empata o gana a Llama 3 en tareas usa parches de 4.5 bytes y un umbral más bajo en inferencia, que agrega pasos que el paper no cuantifica.
- Escala y recetas prestadas. Usaron las proporciones de datos y parámetros óptimas para BPE, y muchas pruebas de arquitectura se hicieron hasta 1B parámetros. Los autores reconocen que lo óptimo podría cambiar a 8B o más.
- El modelo grande con tokenizador sigue arriba. Llama 3.1 gana en fonología y en varias tareas de palabras, y el BLT convertido desde Llama 3.1 queda abajo del original en todas las tareas de la Tabla 5. Además, el modelo de entropía se entrena aparte, no de punta a punta.
Qué significa para ti el Byte Latent Transformer si trabajas con LLM
Hoy no vas a cambiar tu LLM de producción por BLT. El paper publica el código de entrenamiento e inferencia en github.com/facebookresearch/blt, pero es investigación: las bibliotecas de inferencia están optimizadas para modelos con tokenizador, y los autores no midieron velocidad real.
Lo que sí puedes llevarte son tres ideas prácticas. Primero, muchos errores raros de un LLM vienen del tokenizador: contar letras, invertir palabras o leer texto con errores de captura. Si tu aplicación depende de eso (nombres propios mal escritos, OCR, códigos de producto), pruébalo explícitamente; en las pruebas de ruido y de caracteres del paper, el modelo que ve bytes falló bastante menos.
Segundo, la entropía del siguiente byte es una señal útil y fácil de calcular con cualquier modelo de bytes. Este es el corte de la regla global en Python, con las mismas entropías inventadas de la gráfica:
def parches_por_entropia(texto, entropias, umbral):
"""Corta el texto donde la entropia del byte supera el umbral global."""
parches, actual = [], ""
for byte, h in zip(texto, entropias):
if actual and h > umbral: # H(x_t) > theta_g: empieza un parche nuevo
parches.append(actual)
actual = ""
actual += byte
if actual:
parches.append(actual)
return parches
entropias = [3.2, 1.4, 0.6, 0.3, 0.2, 0.1, 0.4, 2.8,
1.2, 0.3, 3.0, 1.1, 0.7, 0.4, 0.2, 0.1] # inventadas
print(parches_por_entropia("Python es genial", entropias, umbral=1.5))
# ['Python ', 'es ', 'genial']
Tercero, si trabajas con español, no asumas que los resultados se trasladan tal cual. El paper evalúa traducción en seis idiomas muy usados y veintiún idiomas con pocos recursos, pero el español no está entre ellos; los beneficios más grandes aparecen en idiomas con escrituras distintas y pocos datos. Lo razonable es medir con tus propios textos antes de decidir.