programa
La tokenización es la parte del pila de HuggingFace Transformer que apenas notamos, hasta que empieza a filtrarse en tus resultados. Un solo espacio en blanco puede cambiar los límites de los tokens, la decodificación puede producir cadenas inesperadas y las indicaciones de chat pueden romperse silenciosamente al crear plantillas.
Transformers v5 aborda estos puntos débiles con un rediseño de la tokenización que estandariza el comportamiento en todas las implementaciones, simplifica la superficie de la API y facilita la inspección de los componentes internos del tokenizador cuando necesitamos depurar.
En este tutorial, comenzaré explicando los aspectos esenciales de lo que produce la tokenización y cómo funciona el proceso, y luego te guiaré a través de los cambios reales que se producen en la versión 5 desde una perspectiva práctica y centrada en la migración. Verás patrones de código v4 frente a v5 para codificación, decodificación, plantillas de chat y serialización, para que puedas actualizar tus bases de código.
Si eres nuevo en la tokenización, te recomiendo que eches un vistazo al curso curso Introducción al procesamiento del lenguaje natural en Python.
¿Qué es la tokenización?
Una definición muy común de tokenización es que convierte el texto en identificadores de tokens, lo cual es correcto, pero incompleto. En producción, la tokenización se entiende mejor como un contrato. A partir del texto sin procesar, el tokenizador debe producir una codificación estructurada que el modelo pueda consumir de forma segura.
Como mínimo, ese contrato incluye:
input_ids, que son identificadores de token enteros que indexan la tabla de incrustación del modelo.- También incluye la tabla de relleno (
attention_mask), que indica qué posiciones corresponden a tokens reales y cuáles a relleno. - Las compensaciones/alineaciones (si están disponibles) del token del mapa se remontan a los intervalos a nivel de carácter o palabra del texto original, lo cual es necesario para el resaltado, el NER y la atribución.
- Se debe conservar la semántica especial de los tokens, lo que significa que la ubicación y los ID de
BOS/EOS/PAD/UNKdeben coincidir con las convenciones utilizadas durante el entrenamiento del modelo. - En el caso de los modelos de chat, el formato del chat forma parte del contrato, por lo que normalmente aplicamos la plantilla de chat del modelo antes de ejecutar la tokenización.
En Transformers, estas responsabilidades residen en la capa del tokenizador (no dentro del paso hacia adelante del modelo), por lo que AutoTokenizer es el punto de entrada estándar. Aquí tienes un ejemplo sencillo:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM3-3B")
enc = tokenizer("Hello world")
print(enc["input_ids"])
print(tokenizer.convert_ids_to_tokens(enc["input_ids"]))
Este es el resultado esperado:
[9906, 1917]
['Hello', 'Ġworld']
Aquí, enc es un objeto BatchEncoding (un contenedor similar a un diccionario) que contiene los campos listos para el modelo producidos por el tokenizador (como input_ids y, a menudo, attention_mask). La salida devuelve [9906, 1917], que son los ID de token enteros para la cadena de entrada, junto con ['Hello', 'Ġworld'], que muestra las cadenas de token correspondientes.
Nota: El prefijo Ġ es una convención común que indica que el token incluye un espacio inicial, por lo que Ġworld representa «world» en lugar de «world» sin espacios en blanco.
La tokenización como canalización: Cómo la versión 5 lo hace depurable
Los problemas de tokenización suelen manifestarse como pequeños inconvenientes, como espacios adicionales, divisiones Unicode extrañas, un aumento repentino en el recuento de tokens o indicaciones de chat que no siguen correctamente las funciones.
La forma más sencilla de depurar estos problemas es tratar la tokenización como una cadena de etapas. Una vez que sepas qué etapa es responsable de qué, podrás aislar los problemas rápidamente en lugar de tener que adivinar. Aquí hay algunos consejos que debes tener en cuenta:
La tokenización es un proceso modulable.
El primer objetivo es acabar con la idea errónea de que un tokenizador es simplemente un WordPiece. En cambio, se trata de una secuencia de etapas de transformación distintas, que incluyen la normalización, la pre-tokenización, el modelado de subpalabras, el posprocesamiento y la decodificación. Cada etapa controla una parte diferente del comportamiento final.
Modelo mental depurable
Dividir la tokenización en etapas nos proporciona un mapa fiable para la resolución de problemas:
- Las peculiaridades de los espacios en blanco suelen provenir del pre-tokenizador o del decodificador.
- Unicode suele tener su origen en el normalizador.
- Las explosiones de tokens suelen estar causadas por el modelo de subpalabras, junto con tu vocabulario/fusiones.
- Los errores de formato en los chats provienen principalmente de las plantillas o del posprocesamiento.
Explícito e inspeccionable por diseño
Transformers v5 facilita la inspección de los tokenizadores, especialmente los que están respaldados por el motor de tokenizadores Rust.
Cuando se utiliza el backend Rust, podemos inspeccionar los componentes subyacentes a través de la interfaz de normalización ( tokenizer._tokenizer ) (normalizador, pretokenizador, modelo, posprocesador, decodificador). No usamos _tokenizer todos los días, pero resulta muy útil con la versión v5, que permite ver el funcionamiento interno cuando necesitamos depurar.
Esto lleva naturalmente a la distinción entre motor y envoltura:
- Motor (
tokenizers): La implementación de bajo nivel en Rust que realiza las mecánicas básicas, como la normalización, la división, la segmentación de subpalabras y la generación de ID de tokens (y desplazamientos, cuando estén disponibles). - Envoltorio (
transformers): Esta es la capa orientada al modelo que convierte esas mecánicas enentradas listas para el modelo, aplicando convenciones como el manejo de tokens especiales, plantillas de chat, reglas de relleno/truncamiento y salidas de tensores específicas del marco.
¿Qué ha cambiado en Transformers v5?
Transformers v5 es una versión estandarizada importante, y la tokenización es una de las áreas con cambios visibles para los usuarios. La versión reduce las implementaciones duplicadas, hace que el comportamiento del tokenizador sea más coherente entre los modelos y facilita la inspección y (en algunos casos) el entrenamiento de los tokenizadores desde cero. A continuación se detallan los cambios que más afectan a los usuarios habituales.
Una implementación de tokenizador por modelo
En versiones anteriores, muchos modelos tenían:
- un tokenizador Python lento
- Una implementación rápida del tokenizador respaldada por Rust.
En la versión 5, Transformers se consolida en un único archivo tokenizador por modelo y prefiere la ruta respaldada por Rust. He aquí por qué funciona el tokenizador respaldado por Rust:
- Elimina las implementaciones duplicadas lentas frente a las rápidas.
- Reduce los errores de paridad causados por sutiles discrepancias de comportamiento entre esas implementaciones.
- Esta implementación del tokenizador reduce y simplifica la superficie de prueba, ya que solo hay una ruta de código principal que validar.
- También establece una única «fuente de verdad» para el comportamiento del tokenizador en todos los modelos.
Migración de la API de codificación
La API v4 encode_plus() ha quedado obsoleta y se recomienda llamar directamente al tokenizador. Aquí está la diferencia entre la versión v4 y la v5:
Versión v4
enc = tokenizer.encode_plus(
text,
truncation=True,
padding="max_length",
max_length=128,
return_tensors="pt",
)
Versión v5
enc = tokenizer(
text,
truncation=True,
padding="max_length",
max_length=128,
return_tensors="pt",
)
Pasar de encode_plus() a un único punto de entrada tokenizer() reduce los modos de fallo reales que aparecen en el código de producción.
En la versión 4, disponer de varios métodos de codificación significaba que podían aparecer diferencias sutiles en el relleno, el truncamiento, el procesamiento por lotes o la conversión de tensores, dependiendo de la ruta que se utilizara, y que a menudo solo se manifestaban al pasar de entradas individuales a cargas de trabajo por lotes.
La versión 5 estandariza todo en una ruta de codificación que siempre devuelve un BatchEncoding, lo que hace que el comportamiento sea más predecible y reduce tanto los errores en casos extremos como la cantidad de código necesario para mantener la coherencia de los procesos de tokenización.
Descifrando la migración de la API
La versión 5 unifica la decodificación, de modo que decode() gestiona tanto entradas individuales como por lotes, alineando el comportamiento de la decodificación con el de la codificación.
Versión v4
texts = tokenizer.batch_decode(batch_ids, skip_special_tokens=True)
Versión v5
texts = tokenizer.decode(batch_ids, skip_special_tokens=True)
En la versión 5, la decodificación está diseñada para reflejar la codificación. Al igual que tokenizer() puede aceptar una sola cadena o un lote de cadenas, decode() puede aceptar una sola secuencia de ID de tokens o un lote de secuencias.
Lo más importante aquí es el tipo de retorno, es decir, si pasas una secuencia, obtendrás una sola cadena, pero si pasas un lote (como list[list[int]]), obtendrás una lista de cadenas. Esto hace que la API sea más limpia en general, pero también significa que cualquier código que asuma que decode() siempre devuelve una cadena debe actualizarse para manejar ambos casos.
Plantillas de chat
En la versión 4, apply_chat_template devolvía input_ids sin procesar para garantizar la compatibilidad con versiones anteriores. En la versión 5, devuelve un objeto « BatchEncoding », al igual que otros métodos tokenizadores.
Versión v4
input_ids = tokenizer.apply_chat_template(messages, return_tensors="pt")
Versión v5
enc = tokenizer.apply_chat_template(messages, return_tensors="pt")
input_ids = enc["input_ids"]
attention_mask = enc["attention_mask"]
En la versión 5, apply_chat_template() se trata como un punto de entrada del tokenizador adecuado, en lugar de como un ayudante para casos especiales. En lugar de devolver solo input_ids, devuelve un objeto BatchEncoding completo (con campos como input_ids y attention_mask).
Esto es importante porque las entradas con formato de chat ahora se integran en el mismo flujo de trabajo de procesamiento por lotes, relleno, truncamiento y retorno de tensores que la tokenización normal. Por lo tanto, no necesitamos código adicional para reconstruir máscaras o alinear manualmente los formatos antes de enviar entradas al modelo.
Serialización del tokenizador
En la versión 5, la serialización del tokenizador se simplifica al consolidar los metadatos de tokens especiales y tokens añadidos en menos artefactos, al tiempo que se sigue admitiendo los archivos heredados para garantizar la compatibilidad con versiones anteriores. Esto reduce el riesgo de que múltiples archivos «fuente de verdad» se desincronicen y facilita la carga y reutilización de los activos del tokenizador en herramientas posteriores que operan fuera de la biblioteca Transformers.
Tokenizadores como arquitecturas configurables
En la versión 5, el cambio clave es que un tokenizador se trata como un canal definido junto con los artefactos aprendidos, en lugar de ser solo algo que cargamos desde archivos serializados.
- La clase tokenizer especifica cómo se normaliza el texto, se divide en fragmentos, se convierte en tokens de subpalabras y, finalmente, se decodifica de nuevo en texto.
- El vocabulario y las reglas de fusión son artefactos aprendidos, es decir, son los elementos entrenados que determinan qué tokens existen y cómo se comprime el texto en ID de tokens.
- Esta separación permite flujos de trabajo que dan prioridad a la arquitectura. Para los tokenizadores compatibles, puedes instanciar un tokenizador que siga el diseño de un modelo y, a continuación, cargar o entrenar el vocabulario/las fusiones por separado, lo que facilita mucho la personalización y el reentrenamiento.
Reflexiones finales
La tokenización de Transformers v5 supone un gran paso hacia la estandarización y la simplificación. Ahora hay una ruta de comportamiento más canónica (que reduce la divergencia lenta/rápida), una superficie API simplificada, plantillas de chat que devuelven el mismo objeto estructurado BatchEncoding que la tokenización normal y una serialización consolidada que reduce las suposiciones frágiles a nivel de archivo.
También impulsa un modelo mental que da prioridad a la arquitectura, en el que los tokenizadores son más fáciles de inspeccionar y, en los casos compatibles, de entrenar desde cero. Para migrar sin problemas desde la versión 4, sustituye encode_plus() por tokenizer(), sustituye batch_decode() por decode(), actualiza los sitios de llamada apply_chat_template() para que funcionen con BatchEncoding, evita codificar de forma rígida los nombres de archivo del tokenizador heredado al guardar y espera que cualquier peculiaridad del tokenizador lento converja hacia el comportamiento respaldado por los tokenizadores.
Si deseas obtener más información sobre las últimas versiones, aquí tienes las notas de la versión. También recomiendo el programa Hugging Face Fundamentals para adquirir práctica.
Preguntas frecuentes sobre la tokenización v5
¿Todavía tienes que elegir entre las clases de tokenizador «rápido» (Rust) y «lento» (Python)?
No. Transformers v5 los consolida en una única implementación por modelo. La biblioteca ahora utiliza de forma predeterminada el backend Rust altamente optimizado (bibliotecatokenizers ) para todos los modelos compatibles, lo que elimina la necesidad de seleccionar manualmente LlamaTokenizerFast frente a LlamaTokenizer.
¿Tu código encode_plus actual dejará de funcionar inmediatamente?
No inmediatamente, pero está en desuso. Aunque actualmente la versión 5 admite encode_plus con una advertencia, se recomienda encarecidamente cambiar al método directo tokenizer(__call__). Esto garantiza que obtengas los nuevos comportamientos de procesamiento por lotes unificados y prepara tu código base para el futuro.
¿Por qué apply_chat_template ahora devuelve un diccionario BatchEncoding en lugar de una cadena?
Tratar las entradas del chat como cualquier otra entrada del modelo. Al devolver un diccionario (que contiene input_ids y attention_mask), v5 permite que los datos con formato de chat se agrupen, rellenen y trunquen instantáneamente sin necesidad de un segundo paso de tokenización.
¿Puedes seguir utilizando return_tensors="tf" o return_tensors="jax"?
No. Como parte de los cambios en la arquitectura v5, Transformers ha dejado de ofrecer soporte oficial para los backends TensorFlow y Flax/JAX para centrarse por completo en PyTorch. Tendrás que utilizar el backend de PyTorch o exportar los modelos a formatos como ONNX/GGUF para otros marcos.
¿Cómo se depuran los errores de tokenización «silenciosos» en la versión 5?
Utiliza los componentes internos inspeccionables. En la versión 5, puedes acceder al canal subyacente de Rust a través de tokenizer._tokenizer. Esto te permite comprobar etapas específicas, como el normalizador o el pretokenizador, de forma aislada para ver exactamente dónde se divide o modifica una cadena de forma inesperada.

Soy experta Google Developers en ML (Gen AI), triple experta en Kaggle y embajadora de Women Techmakers, con más de tres años de experiencia en el sector tecnológico. Cofundé una startup de salud en 2020 y actualmente curso un máster en informática en Georgia Tech, con especialización en aprendizaje automático.




