Brief IA : Transformers.js : le NLP révolutionné dans votre navigateur

Transformers.js : le NLP révolutionné dans votre navigateur

Brief IA
Tom Levy·9 min·4 vues

Le tutoriel présente trois tâches de traitement du langage naturel (NLP) utilisant l'API pipeline() de Transformers.js : la classification de texte, le labelling zéro-shot et la réponse à des questions. L'utilisation de Transformers.js permet d'exécuter ces tâches directement dans le navigateur, rendant l'IA accessible sans nécessiter d'infrastructure serveur complexe. Cela facilite l'intégration de l'IA dans des applications web, améliorant ainsi l'expérience utilisateur.

En bref
1Transformers.js permet d'exécuter des modèles NLP avancés directement dans le navigateur, éliminant le besoin de serveurs.
2La bibliothèque utilise ONNX Runtime pour exécuter des modèles pré-entraînés en JavaScript, avec une mise en cache locale pour des performances optimisées.
3Les utilisateurs peuvent réaliser des tâches comme la classification de texte et la classification zéro-shot sans quitter leur appareil.
💡Pourquoi c'est importantCette technologie démocratise l'accès au NLP avancé, réduisant les coûts et améliorant la confidentialité des utilisateurs.
Le brief IA que lisent les pros

Tu veux les meilleurs outils IA avant les autres ?

On teste et on décrypte les nouveaux outils IA chaque soir, en 5 min. Gratuit.

Inclus dès l'inscription : notre sélection des meilleurs guides & comparatifs IA.

Choisis ton rythme

Gratuit · Pas de spam · Désabonnement en 1 clic

📄
L'analyse en français

Une nouvelle ère pour le traitement du langage naturel avec Transformers.js

Pendant longtemps, l'exécution de modèles de transformateurs pour le traitement du langage naturel (NLP) nécessitait une infrastructure complexe. Les utilisateurs devaient souvent maintenir un serveur Python, investir dans du temps GPU coûteux et gérer les requêtes d'inférence via une API. Cela impliquait que chaque saisie utilisateur quittait son appareil, transitait par une infrastructure distante, avant de revenir sous forme de prédiction. Cette approche était justifiée à l'époque où les modèles étaient trop volumineux pour être exécutés localement. Cependant, cette époque touche à sa fin.

Transformers.js marque un tournant décisif. Cette bibliothèque permet d'exécuter des modèles NLP de pointe directement dans le navigateur de l'utilisateur, sans nécessiter de serveur. Les modèles sont téléchargés une seule fois, mis en cache localement, et peuvent ensuite fonctionner hors ligne. La conversion du code Python en JavaScript est presque directe :

import { pipeline } from '@huggingface/transformers';
const classifier = await pipeline('sentiment-analysis');
const result = await classifier('J’adore les transformateurs !');

Ce tutoriel explore trois tâches NLP : la classification de texte, l'étiquetage zéro-shot et la réponse à des questions, en utilisant l'API pipeline() de Transformers.js. Pour chaque tâche, nous verrons comment initialiser le pipeline, interpréter la structure de sortie, et un exemple HTML fonctionnel que vous pouvez tester directement dans votre navigateur. Le tutoriel se conclut par une application complète de routage de tickets de support, intégrant les trois pipelines en un outil pratique.

Chaque exemple de code utilise le chemin d'importation CDN, éliminant ainsi le besoin de toute étape de construction. Il suffit d'ouvrir un éditeur de texte, de coller le code et de l'exécuter.

Qu'est-ce que Transformers.js ?

La bibliothèque Transformers.js vise à être fonctionnellement équivalente à la bibliothèque de transformateurs Python de Hugging Face. Cela signifie qu'elle utilise les mêmes modèles pré-entraînés, les mêmes noms de tâches et la même API de pipeline, mais en JavaScript. Le secret de cette compatibilité réside dans ONNX Runtime.

Les modèles initialement entraînés dans PyTorch, TensorFlow ou JAX sont convertis au format ONNX grâce à Hugging Face Optimum. ONNX Runtime exécute ensuite ces modèles dans le navigateur. Par défaut, il fonctionne sur le CPU via WebAssembly (WASM), compatible avec tous les navigateurs modernes. Pour ceux qui souhaitent une accélération via GPU, le paramètre device: 'webgpu' permet d'utiliser l'API WebGPU du navigateur, offrant une vitesse d'exécution significativement accrue là où cela est possible, bien que cette fonctionnalité reste expérimentale dans certains environnements.

Mise en cache des modèles. Lors de la première exécution d'un pipeline, les poids du modèle sont téléchargés depuis Hugging Face Hub et mis en cache dans IndexedDB du navigateur ou dans le système de fichiers en Node.js. Les tests montrent que le pipeline d'analyse de sentiment télécharge environ 111 Mo lors du premier chargement. Les exécutions suivantes se font directement depuis le cache, rendant le processus rapide et fonctionnel hors ligne.

Quantification. L'option dtype contrôle la précision du modèle. q8 (quantification 8 bits) est la valeur par défaut pour WASM, offrant un bon équilibre entre taille et précision. q4 réduit la taille du fichier d'environ moitié, avec une perte de précision de 1 à 3 % sur la plupart des tâches, ce qui est idéal pour les connexions mobiles ou lentes. Pour une utilisation côté serveur en Node.js, fp32 assure une pleine précision sans contrainte de taille.

// Exécution WASM par défaut -- fonctionne partout
const pipe = await pipeline('sentiment-analysis');

// WebGPU pour une inférence plus rapide sur le matériel compatible
const pipe = await pipeline('sentiment-analysis', null, { device: 'webgpu' });

// Quantification 4 bits pour des téléchargements de modèles plus petits
const pipe = await pipeline('sentiment-analysis', 'Xenova/distilbert-base-uncased-finetuned-sst-2-english');

L'API pipeline()

La fonction pipeline est l'interface principale pour la plupart des cas d'utilisation. Elle combine un modèle pré-entraîné, un tokenizer et une logique de post-traitement en un seul objet appelable. Vous n'avez pas besoin de manipuler directement le tokenizer ou les poids du modèle. Vous appelez simplement le pipeline avec du texte et recevez une sortie structurée.

La signature de la fonction comporte trois parties :

const pipe = await pipeline(task, model?, options?);
const result = await pipe(input, inferenceOptions?);
  • task est un identifiant de chaîne qui indique à la bibliothèque quel type de modèle charger et comment gérer l'entrée et la sortie.
  • model est optionnel ; si vous l'omettez, la bibliothèque charge le modèle par défaut pour cette tâche. Si vous spécifiez un ID de modèle (comme 'Xenova/distilbert-base-uncased-finetuned-sst-2-english'), ce modèle est chargé depuis le Hub.
  • options est l'endroit où vous définissez device, dtype et progress_callback.

Les deux étapes sont asynchrones. pipeline() télécharge et charge le modèle en mémoire, ce qui constitue la partie lente lors de la première exécution. L'appel pipe est généralement rapide une fois le modèle chargé. Les deux renvoient des Promesses, ce qui signifie que votre interface utilisateur doit gérer l'état de chargement.

Un progress_callback vous permet de suivre le téléchargement et d'afficher les progrès à l'utilisateur :

// progress_callback se déclenche lors du téléchargement du modèle avec des mises à jour de statut
const pipe = await pipeline(
  'sentiment-analysis',
  'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
  progress_callback: (progress) => {
    // progress.status peut être : 'initiate', 'download', 'progress', 'done'
    if (progress.status === 'progress') {
      const pct = Math.round(progress.progress);
      document.getElementById('progress').textContent =
      `Chargement du modèle : ${pct}%`;
    }
    if (progress.status === 'ready') {
      document.getElementById('progress').textContent = 'Modèle prêt';
    }
  }
);

Il est important de noter que Transformers.js est une bibliothèque uniquement d'inférence. Vous ne pouvez pas affiner ou entraîner des modèles avec elle. Si votre tâche nécessite un modèle personnalisé, l'entraînement doit être effectué ailleurs (Python, cloud), et l'export ONNX résultant s'exécute dans le navigateur.

Tâche 1 : Classification de texte

La classification de texte attribue une étiquette et un score de confiance au texte d'entrée. La forme la plus courante est l'analyse de sentiment, positif contre négatif, mais la même architecture de pipeline gère tout ensemble fixe de catégories sur lesquelles le modèle a été entraîné.

À quoi ressemble la sortie :

const result = await classifier('Ce produit a complètement dépassé mes attentes.');
// [{ label: 'POSITIVE', score: 0.9997 }]

La sortie est un tableau d'objets. Chaque objet a label (la classe prédite sous forme de chaîne) et score (un float entre 0 et 1 représentant la confiance du modèle). Un score de 0.9997 signifie que le modèle est très confiant. Un score de 0.52 signifie qu'il est à peine au-dessus du seuil de décision ; considérez cela comme incertain et gérez-le en conséquence dans votre logique d'application.

La sortie est toujours un tableau, même pour une seule entrée, car le même appel de pipeline gère des lots :

const results = await classifier([
  'C’est génial !',
  'Complètement cassé, perte d’argent.'
]);
//   { label: 'POSITIVE', score: 0.9998 },
//   { label: 'NEGATIVE', score: 0.9991 }

Exemple complet fonctionnel

L'exemple ci-dessous est un fichier HTML complet et autonome. Ouvrez-le dans n'importe quel navigateur moderne. Le modèle se télécharge lors de la première exécution et met en cache les chargements suivants, qui sont instantanés.

<html lang="en">
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Classification de texte avec Transformers.js</title>
  <body style="font-family: system-ui, sans-serif; max-width: 680px; margin: 2rem auto; padding: 0 1rem;">
    <textarea id="input" placeholder="Entrez le texte à classifier..."></textarea>
    <button id="classify-btn" disabled>Chargement du modèle...</button>
    <div id="status">Téléchargement du modèle lors de la première exécution (cela peut prendre un moment)...</div>
    <div id="result"></div>
    <script type="module">
      import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.0.2';
      const statusEl = document.getElementById('status');
      const resultEl = document.getElementById('result');
      const btn = document.getElementById('classify-btn');
      const inputEl = document.getElementById('input');

      async function loadModel() {
        classifier = await pipeline(
          'text-classification',
          'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
          progress_callback: (p) => {
            if (p.status === 'progress') {
              const pct = Math.round(p.progress ?? 0);
              statusEl.textContent = `Téléchargement du modèle : ${pct}%`;
              btn.textContent = 'Classifier';
              btn.disabled = false;
              statusEl.textContent = 'Modèle chargé et mis en cache. Les chargements suivants sont instantanés.';
            }
          }
        );
      }

      async function classify() {
        const text = inputEl.value.trim();
        if (!text) return;
        btn.disabled = true;
        btn.textContent = 'Classification...';
        resultEl.textContent = '';
        const results = await classifier(text);
        const { label, score } = results[0];
        const pct = (score * 100).toFixed(1);
        const cssClass = label === 'POSITIVE' ? 'positive' : 'negative';
        resultEl.innerHTML = `<span class="${cssClass}">${label}</span> -- ${pct}% de confiance`;
        btn.disabled = false;
        btn.textContent = 'Classifier';
      }

      btn.addEventListener('click', classify);
      loadModel().catch(err => {
        statusEl.textContent = `Erreur lors du chargement du modèle : ${err.message}`;
      });
    </script>
  </body>
</html>

La fonction loadModel appelle pipeline() avec le nom de la tâche, l'ID du modèle et les options. Le progress_callback se déclenche plusieurs fois pendant le téléchargement et met à jour le texte de statut afin que l'utilisateur ne regarde pas un écran figé. Une fois le modèle chargé, le bouton est activé. Lorsque l'utilisateur clique sur Classifier, classifier(text) exécute l'inférence de manière synchrone depuis le cache, généralement en moins de 200 ms sur un ordinateur portable moderne. Le résultat déstructure label et score du premier élément du tableau, formate la confiance en pourcentage et applique une classe CSS pour le codage couleur.

Tâche 2 : Classification zéro-shot

La classification zéro-shot fait quelque chose que la classification de texte régulière ne peut pas faire : elle classe le texte dans des catégories que vous définissez à l'exécution, sans données d'entraînement requises. Vous passez le texte et une liste de labels possibles, et le modèle prédit la probabilité que chaque label soit correct. Cela permet une flexibilité énorme, notamment pour les applications où les catégories peuvent varier fréquemment ou ne sont pas connues à l'avance.

La sortie pour une classification zéro-shot est similaire à celle de la classification de texte, mais elle inclut des scores pour chaque label proposé, permettant de déterminer lequel est le plus probable. Cette capacité à s'adapter à des catégories dynamiques sans nécessiter de réentraînement est un atout majeur pour les développeurs cherchant à intégrer des fonctionnalités NLP avancées dans leurs applications sans lourdes contraintes de maintenance.

Suivez Brief IA

L'actu IA du jour, aussi dans votre fil.

Commentaires