Cursus
La tokenisation est une partie du pile HuggingFace Transformer que nous remarquons à peine, jusqu'à ce qu'elle commence à se refléter dans vos résultats. Un seul espace blanc peut modifier les limites des jetons, le décodage peut produire des chaînes inattendues et les invites de chat peuvent se rompre silencieusement lors de la création de modèles.
Transformers v5 résout ces problèmes grâce à une refonte de la tokenisation qui uniformise le comportement entre les différentes implémentations, simplifie l'interface API et facilite l'inspection des composants internes du tokeniseur lorsque le débogage est nécessaire.
Dans ce tutoriel, je commencerai par expliquer les principes fondamentaux de la tokenisation et le fonctionnement du pipeline, puis je vous présenterai les changements concrets apportés par la version 5 d'un point de vue pratique, axé sur la migration. Vous trouverez des comparaisons côte à côte des modèles de code v4 et v5 pour l'encodage, le décodage, les modèles de chat et la sérialisation, afin que vous puissiez mettre à jour vos bases de code.
Si vous débutez dans le domaine de la tokenisation, je vous recommande de consulter le cours cours Introduction au traitement du langage naturel en Python.
Qu'est-ce que la tokenisation ?
Une définition très courante de la tokenisation est qu'elle consiste à convertir du texte en identifiants de jetons, ce qui est exact mais incomplet. Dans le domaine de la production, la tokenisation est mieux comprise comme un contrat. À partir d'un texte brut, le tokeniseur doit produire un encodage structuré que le modèle peut utiliser en toute sécurité.
Ce contrat comprend au minimum :
input_ids, qui sont des identifiants de jetons entiers qui indexent la table d'intégration du modèle.- Il comprend également l'
attention_mask, qui indique quelles positions correspondent à des jetons réels par opposition au remplissage. - Les décalages/alignements (si disponibles) permettent de relier les segments de jetons de carte aux segments de caractères ou de mots dans le texte original, ce qui est nécessaire pour la mise en évidence, la reconnaissance de noms propres (NER) et l'attribution.
- La sémantique des jetons spéciaux doit être préservée, ce qui signifie que l'emplacement et les identifiants
BOS/EOS/PAD/UNKdoivent correspondre aux conventions utilisées lors de l'entraînement du modèle. - Pour les modèles de chat, le formatage du chat fait partie du contrat. Par conséquent, nous appliquons généralement le modèle de chat du modèle avant de procéder à la tokenisation.
Dans Transformers, ces responsabilités se trouvent au niveau de la couche de tokenisation (et non dans le passage avant du modèle), c'est pourquoi AutoTokenizer est le point d'entrée standard. Voici un exemple simple :
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"]))
Voici le résultat attendu :
[9906, 1917]
['Hello', 'Ġworld']
Ici, enc est un objet BatchEncoding (un conteneur de type dict) qui contient les champs prêts à être modélisés produits par le tokenizer (tels que input_ids et souvent attention_mask). [9906, 1917] ['Hello', 'Ġworld']La sortie renvoie les identifiants de jetons entiers pour la chaîne d'entrée, ainsi que les chaînes de jetons correspondantes.
Remarque : Le préfixe Ġ est une convention courante qui indique que le token comprend un espace initial. Ainsi, Ġworld représente « world » plutôt que « world » sans espace.
La tokenisation en tant que pipeline : Comment la version 5 facilite le débogage
Les problèmes de tokenisation se manifestent généralement sous la forme de petits problèmes tels que des espaces supplémentaires, des divisions Unicode inhabituelles, une augmentation soudaine du nombre de tokens ou des invites de chat qui ne respectent pas correctement les rôles.
La manière la plus simple de résoudre ces problèmes consiste à considérer la tokenisation comme une série d'étapes. Une fois que vous identifiez quelle étape est responsable de quoi, vous pouvez isoler rapidement les problèmes au lieu de procéder par conjecture. Voici quelques points à garder à l'esprit :
La tokenisation est un pipeline modulable.
Le premier objectif est de dissiper l'idée fausse selon laquelle un tokenizer n'est qu'un WordPiece. Il s'agit plutôt d'une séquence d'étapes de transformation distinctes, comprenant la normalisation, la pré-tokenisation, la modélisation des sous-mots, le post-traitement et le décodage. Chaque étape contrôle une partie différente du comportement final.
Modèle mental pouvant être débogué
La division de la tokenisation en étapes nous fournit une feuille de route fiable pour le dépannage :
- Les anomalies liées aux espaces blancs proviennent généralement du pré-tokeniseur ou du décodeur.
- Unicode provient généralement du normalisateur.
- Les explosions de jetons sont souvent causées par le modèle de sous-mots, ainsi que par son vocabulaire/ses fusions.
- Les erreurs de formatage dans les discussions proviennent principalement des modèles ou du post-traitement.
Conçu pour être explicite et vérifiable
Transformers v5 facilite l'inspection des tokeniseurs, en particulier ceux qui sont pris en charge par le moteur de tokenisation Rust.
Lorsque le backend Rust est utilisé, nous pouvons examiner les composants sous-jacents via l'interface tokenizer._tokenizer (normaliseur, pré-tokeniseur, modèle, post-processeur, décodeur). Nous n'utilisons pas quotidiennement _tokenizer, mais cet outil s'avère utile avec la version v5, qui rend les composants internes visibles lorsque nous devons procéder au débogage.
Cela conduit naturellement à la distinction entre moteur et wrapper :
- Moteur (
tokenizers): L'implémentation Rust de bas niveau qui exécute les mécanismes fondamentaux tels que la normalisation, le fractionnement, la segmentation des sous-mots et la production d'identifiants de jetons (et de décalages lorsqu'ils sont disponibles). - Wrapper (
transformers) : Il s'agit de la couche orientée modèle qui transforme ces mécanismes enentrées d's prêtes à être utilisées par le modèle, en appliquant des conventions telles que la gestion des jetons spéciaux, les modèles de chat, les règles de remplissage/troncature et les sorties de tenseurs spécifiques au cadre.
Quels sont les changements apportés à Transformers v5 ?
Transformers v5 est une version standardisée majeure, et la tokenisation est l'un des domaines présentant des changements visibles pour l'utilisateur. Cette version réduit les implémentations dupliquées, rend le comportement des tokeniseurs plus cohérent d'un modèle à l'autre et facilite l'inspection et (dans certains cas) l'apprentissage à partir de zéro des tokeniseurs. Vous trouverez ci-dessous les modifications qui ont le plus d'impact sur les utilisateurs quotidiens.
Une implémentation de tokeniseur par modèle
Dans les versions précédentes, de nombreux modèles comportaient :
- un tokeniseur Python lent
- Une implémentation rapide du tokenizer basée sur Rust
Dans la version 5, Transformers regroupe tous les fichiers de tokenisation en un seul fichier par modèle et privilégie le chemin d'accès soutenu par Rust. Voici pourquoi le tokenizer soutenu par Rust fonctionne :
- Il élimine les implémentations lentes et rapides en double.
- Cela réduit les erreurs de parité causées par de légères divergences de comportement entre ces implémentations.
- Cette implémentation du tokenizer réduit et simplifie la surface de test, car il n'y a qu'un seul chemin de code principal à valider.
- Il établit également une « source de vérité » unique pour le comportement du tokeniseur dans tous les modèles.
Transition de l'API d'encodage
L'API v4 encode_plus() est désormais obsolète, il est préférable d'appeler directement le tokenizer. Voici les différences entre les versions v4 et v5 :
version v4
enc = tokenizer.encode_plus(
text,
truncation=True,
padding="max_length",
max_length=128,
return_tensors="pt",
)
version v5
enc = tokenizer(
text,
truncation=True,
padding="max_length",
max_length=128,
return_tensors="pt",
)
Le passage d'encode_plus() s à un point d'entrée unique tokenizer() réduit les modes de défaillance réels qui apparaissent dans le code de production.
Dans la version 4, l'existence de plusieurs méthodes d'encodage entraînait des différences subtiles au niveau du remplissage, de la troncature, du traitement par lots ou de la conversion tensorielle selon le chemin utilisé, qui n'apparaissaient souvent que lors du passage d'entrées uniques à des charges de travail par lots.
La version 5 normalise tous les éléments sur un seul chemin d'encodage qui renvoie systématiquement un objet « BatchEncoding », ce qui rend le comportement plus prévisible et réduit à la fois les bogues marginaux et la quantité de code nécessaire pour assurer la cohérence des pipelines de tokenisation.
Décodage de la migration de l'API
La version 5 unifie le décodage afin que decode() puisse traiter à la fois les entrées individuelles et groupées, alignant ainsi le comportement de décodage sur celui du codage.
version v4
texts = tokenizer.batch_decode(batch_ids, skip_special_tokens=True)
version v5
texts = tokenizer.decode(batch_ids, skip_special_tokens=True)
Dans la version 5, le décodage est conçu pour refléter le codage. Tout comme tokenizer() peut accepter une seule chaîne ou un lot de chaînes, decode() peut accepter une seule séquence d'identifiants de jetons ou un lot de séquences.
L'élément principal ici est le type de retour, c'est-à-dire que si vous transmettez une séquence, vous obtiendrez une seule chaîne, mais si vous transmettez un lot (comme list[list[int]]), vous obtiendrez une liste de chaînes. Cela rend l'API plus claire dans l'ensemble, mais cela signifie également que tout code qui suppose qu'decode() renvoie toujours une chaîne doit être mis à jour pour gérer les deux cas.
Modèles de chat
input_ids Dans la version 4, la méthode ` apply_chat_template ` renvoyait des données brutes à des fins de compatibilité ascendante. Dans la version 5, il renvoie un objet de type « BatchEncoding », à l'instar des autres méthodes de tokenisation.
version v4
input_ids = tokenizer.apply_chat_template(messages, return_tensors="pt")
version v5
enc = tokenizer.apply_chat_template(messages, return_tensors="pt")
input_ids = enc["input_ids"]
attention_mask = enc["attention_mask"]
Dans la version 5, apply_chat_template() est considéré comme un point d'entrée de tokenizer à part entière plutôt que comme une aide spéciale. Au lieu de renvoyer uniquement input_ids, il renvoie un objet BatchEncoding complet (avec des champs tels que input_ids et attention_mask).
Ceci est important car les entrées au format chat s'intègrent désormais dans le même flux de travail de traitement par lots, de remplissage, de troncature et de retour de tenseur que la tokenisation classique. Nous n'avons donc pas besoin de code supplémentaire pour reconstruire les masques ou aligner manuellement les formats avant d'envoyer les entrées au modèle.
Sérialisation du tokeniseur
Dans la version 5, la sérialisation du tokenizer est simplifiée grâce à la consolidation des métadonnées des tokens spéciaux et des tokens ajoutés en un nombre réduit d'artefacts, tout en continuant à prendre en charge les fichiers hérités pour assurer la rétrocompatibilité. Cela réduit le risque de désynchronisation de plusieurs fichiers « source de vérité » et facilite le chargement et la réutilisation des ressources du tokenizer dans les outils en aval qui fonctionnent en dehors de la bibliothèque Transformers.
Les tokeniseurs en tant qu'architectures configurables
Dans la version 5, le changement majeur réside dans le fait qu'un tokenizer est désormais considéré comme un pipeline défini avec des artefacts appris, au lieu d'être simplement un élément que nous chargeons à partir de fichiers sérialisés.
- La classe tokenizer définit la manière dont le texte est normalisé, divisé en segments, converti en tokens de sous-mots, puis finalement décodé pour redevenir du texte.
- Le vocabulaire et les règles de fusion sont des artefacts appris, c'est-à-dire qu'ils constituent les éléments entraînés qui déterminent quels tokens existent et comment le texte est compressé en identifiants de tokens.
- Cette séparation permet de mettre en place des workflows axés sur l'architecture. Pour les tokeniseurs pris en charge, il est possible d'instancier un tokeniseur qui suit la conception d'un modèle, puis de charger ou d'entraîner le vocabulaire/les fusions séparément, ce qui simplifie considérablement la personnalisation et le réentraînement.
Conclusions finales
La tokenisation Transformers v5 représente une avancée significative vers la standardisation et la simplification. Il existe désormais un chemin de comportement plus canonique (réduisant la divergence lente/rapide), une interface API simplifiée, des modèles de chat qui renvoient le même objet d'BatchEncoding s structuré que la tokenisation normale, et une sérialisation consolidée qui réduit les hypothèses fragiles au niveau des fichiers.
Il favorise également un modèle mental axé sur l'architecture, dans lequel les tokeniseurs sont plus faciles à inspecter et, dans les cas pris en charge, à former à partir de zéro. Pour migrer en douceur depuis la version 4, veuillez remplacer encode_plus() par tokenizer(), remplacer batch_decode() par decode(), mettre à jour les sites d'appel apply_chat_template() pour qu'ils fonctionnent avec BatchEncoding, éviter de coder en dur les noms de fichiers des tokeniseurs hérités lors de l'enregistrement, et s'attendre à ce que les éventuelles anomalies de lenteur des tokeniseurs convergent vers le comportement soutenu par les tokeniseurs.
Si vous souhaitez en savoir plus sur les dernières versions, voici les notes de mise à jour. Je recommande également le cursus Hugging Face Fundamentals pour acquérir une expérience pratique.
FAQ sur la tokenisation v5
Dois-je toujours choisir entre les classes de tokenisation « Rapide » (Rust) et « Lente » (Python) ?
Non. Transformers v5 regroupe ces éléments en une seule implémentation par modèle. La bibliothèque utilise désormais par défaut le backend Rust hautement optimisé (bibliothèquetokenizers ) pour tous les modèles pris en charge, ce qui évite d'avoir à sélectionner manuellement LlamaTokenizerFast ou LlamaTokenizer.
Mon code encode_plus actuel cessera-t-il de fonctionner immédiatement ?
Pas immédiatement, mais cette fonctionnalité est dépréciée. Bien que la version 5 prenne actuellement en charge encode_plus avec un avertissement, il est fortement recommandé de passer à la méthode directe tokenizer(__call__). Cela vous garantit de bénéficier des nouveaux comportements de traitement par lots unifiés et assure la pérennité de votre base de code.
Pourquoi apply_chat_template renvoie-t-il désormais un dictionnaire BatchEncoding au lieu d'une chaîne de caractères ?
Traiter les entrées de chat comme n'importe quelle autre entrée de modèle. En renvoyant un dictionnaire (contenant input_ids et attention_mask), la version 5 permet de regrouper, de compléter et de tronquer instantanément les données au format chat sans nécessiter une deuxième étape de tokenisation.
Puis-je toujours utiliser return_tensors="tf" ou return_tensors="jax" ?
Non. Dans le cadre des modifications apportées à l'architecture v5, Transformers a cessé de prendre officiellement en charge les backends TensorFlow et Flax/JAX afin de se concentrer entièrement sur PyTorch. Il sera nécessaire d'utiliser le backend PyTorch ou d'exporter les modèles vers des formats tels que ONNX/GGUF pour d'autres frameworks.
Comment puis-je corriger les erreurs de tokenisation « silencieuses » dans la version 5 ?
Veuillez utiliser les composants internes inspectables. Dans la version 5, vous pouvez accéder au pipeline Rust sous-jacent via tokenizer._tokenizer. Cela vous permet de vérifier certaines étapes spécifiques, telles que le normaliseur ou le pré-tokeniseur, de manière isolée afin de déterminer précisément où une chaîne est divisée ou modifiée de manière inattendue.

Je suis experte Google Developers en ML (Gen AI), triple experte Kaggle et ambassadrice Women Techmakers, avec plus de trois ans d’expérience dans la tech. J’ai cofondé une startup dans le domaine de la santé en 2020 et je poursuis actuellement un master en informatique à Georgia Tech, avec une spécialisation en apprentissage automatique.