Une bibliothèque JavaScript révolutionnaire permet d'exécuter des modèles d'IA directement dans votre navigateur. Trois exemples concrets à tester dès aujourd'hui.

TRANSFORMERS.JS : L'IA QUI TRAVAILLE SANS SERVEUR

Imaginez un modèle de langage qui tourne sur votre ordinateur, votre téléphone ou même votre tablette, sans avoir besoin de connexion internet ni de serveur distant. C'est exactement ce que propose Transformers.js, une bibliothèque JavaScript qui exécute des modèles d'intelligence artificielle directement dans le navigateur. Plus besoin d'attendre des secondes pour une réponse : tout se passe en local, en quelques millisecondes.

Cette technologie s'appuie sur des réseaux de neurones profonds (des algorithmes inspirés du cerveau humain) optimisés pour fonctionner sur du Matériel grand public. Le résultat ? Des outils d'IA accessibles à tous, sans frais, sans inscription, et sans dépendre d'une entreprise extérieure.

« Votre navigateur devient une plateforme d'IA complète, capable de comprendre le texte, de répondre à des questions, et même de classer des messages en temps réel. »

COMMENT ÇA MARCHE : 3 LIGNES DE CODE POUR DÉBUTER

Le principe est simple : on importe la fonction pipeline depuis la bibliothèque Transformers.js, puis on charge un modèle adapté à la tâche souhaitée. Par exemple, pour analyser le sentiment d'un texte, il suffit de trois lignes :

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

Dans cet exemple, le modèle va attribuer une étiquette (« POSITIF » ou « NÉGATIF ») et un score de confiance à la phrase. Le tout s'exécute en arrière-plan, sans que vous ayez besoin de comprendre comment fonctionne le modèle.

Les modèles utilisés sont des versions allégées de grands modèles de langage, comme DistilBERT (un cousin simplifié de BERT), qui consomment moins de mémoire et de puissance de calcul. Ils sont téléchargés une seule fois puis stockés dans le cache du navigateur, ce qui accélère les futures exécutions.

PERSONNALISER SON MODÈLE : VITESSE, TAILLE ET PRÉCISION

Transformers.js offre plusieurs options pour adapter le modèle à vos besoins. Par exemple, vous pouvez choisir entre trois modes d'exécution :

  • WASM (WebAssembly) : fonctionne sur tous les navigateurs, même les plus anciens.
  • WebGPU : utilise la carte graphique pour des calculs plus rapides, mais uniquement sur les appareils compatibles.
  • Quantification : réduit la taille du modèle pour un téléchargement plus rapide. Par exemple, la quantification sur 4 bits (dtype: 'q4') divise par deux la taille du modèle, au prix d'une légère baisse de précision.

Voici comment spécifier ces options lors du chargement du modèle :

// Mode par défaut (WASM)
const pipe = await pipeline('sentiment-analysis');

// Mode WebGPU pour une exécution plus rapide
const pipe = await pipeline('sentiment-analysis', null, { device: 'webgpu' });

// Modèle quantifié sur 4 bits pour un téléchargement plus rapide
const pipe = await pipeline('sentiment-analysis',
  'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
  { dtype: 'q4' }
);

Le choix dépend de votre matériel et de l'usage que vous souhaitez en faire. Pour un site web grand public, le mode WASM est le plus fiable. Pour une application interne nécessitant des réponses rapides, WebGPU peut faire la différence.

SUIVRE LA PROGRESSION : UNE EXPÉRIENCE UTILISATEUR OPTIMALE

Rien de plus frustrant pour un utilisateur que de ne pas savoir si quelque chose se charge. Transformers.js permet d'afficher une barre de progression pendant le téléchargement du modèle. Voici comment l'implémenter :

const pipe = await pipeline(
  'sentiment-analysis',
  'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
  {
    dtype: 'q8',
    progress_callback: (progress) => {
      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 .';
      }
    }
  }
);

Ce code affiche un message comme « Chargement du modèle : 67% » pendant le téléchargement, puis « Modèle prêt . » une fois terminé. C'est une fonctionnalité essentielle pour éviter que les utilisateurs ne pensent que l'application est bloquée.

EXEMPLE 1 : CLASSER DES TEXTES PAR SENTIMENT

Première application concrète : un classifieur de sentiment. Cet outil analyse un texte pour déterminer s'il est positif, négatif ou neutre. Parfait pour les avis clients, les commentaires sur les réseaux sociaux, ou les retours d'expérience.

Voici comment utiliser le modèle pour analyser une seule phrase :

const classifier = await pipeline('sentiment-analysis');
const result = await classifier('Ce produit a complètement dépassé mes attentes.');
// Résultat : [{ label: 'POSITIF', score: 0.9997 }]

Et pour analyser plusieurs phrases en une seule fois :

const results = await classifier([
  'C’est génial .',
  'Totalement cassé, une perte d’argent.'
]);
// Résultat : [
//   { label: 'POSITIF', score: 0.9998 },
//   { label: 'NÉGATIF', score: 0.9991 }
// ]

Le score représente la confiance du modèle dans son analyse. Plus il est proche de 1, plus la prédiction est fiable. Dans cet exemple, le modèle est sûr à 99,97% que la première phrase est positive.

CRÉER UNE INTERFACE WEB POUR LE CLASSIFIEUR

Voici un exemple complet d'interface web pour analyser le sentiment d'un texte. Cette page HTML permet à l'utilisateur de coller un texte, puis de cliquer sur un bouton pour obtenir une analyse instantanée.

<.DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Classifieur de sentiment avec Transformers.js</title>
  <style>
    body { font-family: system-ui, sans-serif; max-width: 680px;
           margin: 2rem auto; padding: 0 1rem; }
    textarea { width: 100%; height: 100px; padding: 0.5rem;
               font-size: 1rem; margin-bottom: 0.5rem; }
    button { padding: 0.5rem 1.5rem; font-size: 1rem; cursor: pointer; }
    button:disabled { opacity: 0.5; cursor: not-allowed; }
    #status { color: #666; font-size: 0.9rem; margin: 0.5rem 0; }
    #result { margin-top: 1rem; font-size: 1.1rem; font-weight: bold; }
    .positive { color: #16a34a; }
    .negative { color: #dc2626; }
  </style>
</head>
<body>
  <h1>Analyseur de sentiment</h1>
  <p>Exécute entièrement dans votre navigateur -- aucun serveur, aucun appel API.</p>

  <textarea id="input" placeholder="Entrez un texte à analyser.">
J’ai vraiment adoré utiliser ce produit. La mise en place était simple et tout fonctionne parfaitement.
  </textarea>

  <button id="classify-btn" disabled>Chargement du modèle.</button>
  <div id="status">Téléchargement du modèle en cours (cela peut prendre quelques instants).</div>
  <div id="result"></div>

  <script type="module">
    import { pipeline } from
      'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]';

    const statusEl  = document.getElementById('status');
    const resultEl  = document.getElementById('result');
    const btn       = document.getElementById('classify-btn');
    const inputEl   = document.getElementById('input');

    let classifier;

    async function loadModel() {
      classifier = await pipeline(
        'text-classification',
        'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
        {
          dtype: 'q8',
          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  = 'Analyser';
      btn.disabled     = false;
      statusEl.textContent = 'Modèle chargé et mis en cache. Les prochaines analyses seront instantanées.';
    }

    async function classify() {
      const text = inputEl.value.trim();
      if (.text) return;

      btn.disabled         = true;
      btn.textContent      = 'Analyse en cours.';
      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 = 
        `${label} -- ${pct}% de confiance;

      btn.disabled    = false;
      btn.textContent = 'Analyser';
    }

    btn.addEventListener('click', classify);

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

Cette page affiche un champ de texte où l'utilisateur peut coller un avis ou un commentaire. Un bouton « Analyser » déclenche le traitement, et le résultat s'affiche avec une couleur verte pour positif ou rouge pour négatif. Le modèle est téléchargé une seule fois, puis réutilisé pour les analyses suivantes.

EXEMPLE 2 : CLASSER DES MESSAGES SANS ENTRAÎNEMENT

Deuxième application : un classifieur zéro-exemple. Contrairement à un classifieur classique qui nécessite des données d'entraînement, ce modèle peut attribuer une catégorie à un texte sans avoir jamais vu d'exemple auparavant. Parfait pour router des tickets de support ou trier des messages automatiquement.

Voici comment l'utiliser pour attribuer un ticket à un service :

const classifier = await pipeline('zero-shot-classification',
  'Xenova/bart-large-mnli');

const result = await classifier(
  'Ma facture est erronée et j’ai été débité deux fois.',
  ['facturation', 'support technique', 'livraison', 'retours', 'accès compte']
);

// Résultat : {
//   sequence: 'Ma facture est erronée et j’ai été débité deux fois.',
//   labels:   ['facturation', 'retours', 'accès compte', 'support technique', 'livraison'],
//   scores:   [0.871,      0.063,     0.031,             0.022,               0.013]
// }

Le modèle attribue un score à chaque catégorie, indiquant sa confiance dans l'affectation. Dans cet exemple, il est sûr à 87,1% que le ticket concerne la facturation. Cette technologie s'appuie sur un modèle nommé BART (un autre type de réseau de neurones), spécialisé dans la compréhension du langage naturel.

CRÉER UN ROUTEUR DE TICKETS DE SUPPORT

Voici une interface web qui permet de router automatiquement un ticket de support vers le bon service. L'utilisateur colle un message, et le modèle détermine si c'est un problème de facturation, de livraison, de support technique, etc.

<.DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Routeur de tickets de support</title>
  <style>
    body { font-family: system-ui, sans-serif; max-width: 720px;
           margin: 2rem auto; padding: 0 1rem; }
    textarea { width: 100%; height: 120px; padding: 0.5rem; font-size: 1rem; }
    button { margin-top: 0.5rem; padding: 0.5rem 1.5rem;
             font-size: 1rem; cursor: pointer; }
    button:disabled { opacity: 0.5; cursor: not-allowed; }
    #status  { color: #666; font-size: 0.9rem; margin: 0.5rem 0; }
    .result-row { display: flex; justify-content: space-between;
                  padding: 0.4rem 0; border-bottom: 1px solid #eee; }
    .bar-container { width: 60%; background: #f0f0f0;
                     border-radius: 4px; height: 18px; }
    .bar { background: #2563eb; height: 100%;
           border-radius: 4px; transition: width 0.3s; }
    .label-name { min-width: 160px; font-weight: 500; }
    .score-text { min-width: 50px; text-align: right; color: #555; }
  </style>
</head>
<body>
  <h1>Routeur de tickets</h1>
  <p>Collez un ticket de support. Le modèle l’achemine vers le bon service sans besoin de données d’entraînement.</p>

  <textarea id="ticket">
J’ai passé une commande il y a trois jours mais elle n’a toujours pas été expédiée. J’ai un événement ce week-end et j’ai vraiment besoin que ça arrive à temps. Mon numéro de commande est #48821.
  </textarea>

  <button id="route-btn" disabled>Chargement du modèle.</button>
  <div id="status">Téléchargement du modèle en cours.</div>
  <div id="results"></div>

  <script type="module">
    import { pipeline } from
      'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]';

    const statusEl  = document.getElementById('status');
    const resultsEl = document.getElementById('results');
    const btn       = document.getElementById('route-btn');
    const ticketEl  = document.getElementById('ticket');

    const DEPARTEMENTS = [
      'livraison et expédition',
      'facturation et paiement',
      'support technique',
      'retours et remboursements',
      'compte et connexion'
    ];

    let classifier;

    async function loadModel() {
      classifier = await pipeline(
        'zero-shot-classification',
        'Xenova/bart-large-mnli',
        {
          dtype: 'q8',
          progress_callback: (p) => {
            if (p.status === 'progress') {
              statusEl.textContent =
                Téléchargement du modèle : ${Math.round(p.progress ?? 0)}%;
            }
          }
        }
      );

      btn.disabled    = false;
      btn.textContent = 'Router le ticket';
      statusEl.textContent = 'Modèle prêt.';
    }

    async function routeTicket() {
      const text = ticketEl.value.trim();
      if (.text) return;

      btn.disabled         = true;
      btn.textContent      = 'Aiguillage en cours.';
      resultsEl.innerHTML  = '';

      const output = await classifier(text, DEPARTEMENTS, {
        multi_label: false
      });

      const winner = output.labels[0];
      const confidence = (output.scores[0] * 100).toFixed(1);

      let html = ` {
        const pct = (output.scores[i] * 100).toFixed(1);
        const barWidth = (output.scores[i] * 100).toFixed(0);
        html += 
        <div class="result-row">
          <span class="label-name">${label}</span>
          <div class="bar-container">
            <div class="bar"></div>
          </div>
          <span class="score-text">${pct}%</span>
        </div>;
      });

      resultsEl.innerHTML  = html;
      btn.disabled         = false;
      btn.textContent      = 'Router le ticket';
    }

    btn.addEventListener('click', routeTicket);
    loadModel().catch(err => {
      statusEl.textContent = Erreur : ${err.message};
    });
  </script>
</body>
</html>

Cette interface affiche un champ de texte où l'utilisateur peut coller un ticket de support. Après avoir cliqué sur le bouton, le modèle détermine le service le plus adapté et affiche un graphique en barres montrant la confiance pour chaque catégorie. Par exemple, un ticket concernant une commande non expédiée sera automatiquement aiguillé vers le service « livraison et expédition » avec un score élevé.

EXEMPLE 3 : RÉPONDRE À DES QUESTIONS SUR UN DOCUMENT

Troisième application : un système de réponse aux questions. Cet outil permet de poser une question sur un texte long (comme une politique de retour ou un contrat) et d'obtenir une réponse précise extraite directement du document. Idéal pour les FAQ, les guides utilisateurs ou les documents internes.

Voici comment l'utiliser pour trouver une information dans un texte :

const qa = await pipeline('question-answering', 
  'Xenova/distilbert-base-uncased-distilled-squad');

const result = await qa({
  question: 'Quel est le délai de retour pour les produits électroniques ?',
  context: Notre politique de retour permet aux clients de retourner la plupart des articles dans les 30 jours suivant l'achat. Les produits électroniques doivent être retournés dans les 15 jours et doivent être dans leur emballage d'origine. Les logiciels et téléchargements numériques ne sont pas remboursables.
});

// Résultat : {
//   answer: '15 jours',
//   score:  0.9823,
//   start:  97,    // indice de caractère du début de la réponse
//   end:    104    // indice de caractère de la fin de la réponse
// }

Le modèle extrait la réponse « 15 jours » directement du texte, avec un score de confiance de 98,23%. Les indices start et end permettent de localiser la réponse dans le document original, ce qui est utile pour afficher un extrait mis en évidence.

CRÉER UNE INTERFACE DE QUESTION-RÉPONSE SUR UN DOCUMENT

Voici une interface web qui permet de poser des questions sur un document. L'utilisateur colle un texte (par exemple, une politique de retour), puis pose une question pour en extraire l'information pertinente.

<.DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Réponses aux questions sur un document</title>
  <style>
    body { font-family: system-ui, sans-serif; max-width: 720px;
           margin: 2rem auto; padding: 0 1rem; }
    label { font-weight: 600; display: block; margin-top: 1rem; }
    textarea { width: 100%; padding: 0.5rem; font-size: 0.95rem; }
    input[type="text"] { width: 100%; padding: 0.5rem;
                         font-size: 0.95rem; box-sizing: border-box; }
    button { margin-top: 0.75rem; padding: 0.5rem 1.5rem;
             font-size: 1rem; cursor: pointer; }
    button:disabled { opacity: 0.5; cursor: not-allowed; }
    #status { color: #666; font-size: 0.9rem; margin: 0.5rem 0; }
    #answer-box { margin-top: 1rem; padding: 1rem;
                  background: #f8fafc; border-left: 3px solid #2563eb; }
    .highlight { background: #fef08a; border-radius: 2px; }
    .confidence { color: #666; font-size: 0.85rem; margin-top: 0.5rem; }
  </style>
</head>
<body>
  <h1>Réponses aux questions sur un document</h1>
  <p>Collez n’importe quel document, puis posez des questions à son sujet. Les réponses sont extraites directement du texte.</p>

  <label for="context">Document / Contexte</label>
  <textarea id="context" rows="8">
Politique de retour de Acme Corp (mise à jour mars 2025)

Les clients peuvent retourner la plupart des articles standard dans les 30 jours suivant la date d’achat pour un remboursement intégral. Les produits électroniques et périphériques ont une fenêtre de retour plus courte de 15 jours et doivent être retournés dans leur emballage d’origine, non ouvert, pour être éligibles.

Les remboursements sont traités dans les 3-5 jours ouvrés après réception de l’article retourné. Les frais de port initiaux ne sont pas remboursables. Pour les articles d’une valeur supérieure à 200 €, les clients doivent contacter le support à l’adresse [email protected] avant d’initier un retour.

Les licences logicielles et les téléchargements numériques ne sont pas remboursables dans aucune circonstance. Les cartes cadeaux ne peuvent pas être retournées ni échangées contre de l’argent.
  </textarea>

  <label for="question">Votre question</label>
  <input type="text" id="question"
         value="Combien de temps faut-il pour traiter un remboursement ?" />

  <button id="ask-btn" disabled>Chargement du modèle.</button>
  <div id="status">Téléchargement du modèle en cours.</div>
  <div id="answer-box"></div>

  <script type="module">
    import { pipeline } from
      'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]';

    const contextEl   = document.getElementById('context');
    const questionEl  = document.getElementById('question');
    const statusEl    = document.getElementById('status');
    const answerBox   = document.getElementById('answer-box');
    const btn         = document.getElementById('ask-btn');

    const SEUIL_CONFIANCE = 0.1;

    let qaModel;

    async function loadModel() {
      qaModel = await pipeline(
        'question-answering',
        'Xenova/distilbert-base-uncased-distilled-squad',
        {
          dtype: 'q8',
          progress_callback: (p) => {
            if (p.status === 'progress') {
              statusEl.textContent = 
                Téléchargement du modèle : ${Math.round(p.progress ?? 0)}%;
            }
          }
        }
      );

      btn.disabled    = false;
      btn.textContent = 'Poser la question';
      statusEl.textContent = 'Modèle prêt.';
    }

    async function askQuestion() {
      const context  = contextEl.value.trim();
      const question = questionEl.value.trim();
      if (.context || .question) return;

      btn.disabled         = true;
      btn.textContent      = 'Réflexion en cours.';
      answerBox.style.display = 'none';

      const result = await qaModel({ question, context });

      answerBox.style.display = 'block';

      if (result.score < SEUIL_CONFIANCE) {
        answerBox.innerHTML = 
          <strong>Réponse non trouvée</strong>
          <p class="confidence">Le modèle n’a pas pu trouver de réponse claire à cette question dans le texte fourni.</p>;
      } else {
        const before    = context.slice(0, result.start);
        const answer    = context.slice(result.start, result.end);
        const after     = context.slice(result.end);
        const highlight = ${before}<mark class="highlight">${answer}</mark>${after};

        const confiance = (result.score * 100).toFixed(1);
        answerBox.innerHTML = 
          <strong>Réponse :</strong> ${result.answer}
          <p class="confidence">Confiance : ${confiance}%</p>
          <details>
            <summary style="color: #2563eb">
              Afficher la réponse mise en évidence dans le document
            </summary>
            <pre style="white-space:pre-wrap; font-size:0.85rem;
                        margin-top:0.5rem">${highlight}</pre>
          </details>;
      }

      btn.disabled    = false;
      btn.textContent = 'Poser la question';
    }

    btn.addEventListener('click', askQuestion);

    questionEl.addEventListener('keydown', (e) => {
      if (e.key === 'Enter' && .btn.disabled) askQuestion();
    });

    loadModel().catch(err => {
      statusEl.textContent = Erreur : ${err.message};
    });
  </script>
</body>
</html>

Cette interface permet à l'utilisateur de coller un document (comme une politique de retour) puis de poser une question. Le modèle extrait la réponse et l'affiche avec un niveau de confiance. Si la confiance est trop faible, il indique que la réponse n'a pas été trouvée. Un bouton « Afficher la réponse mise en évidence » permet de visualiser l'extrait du document où se trouve la réponse.

ANALYSER UN TICKET DE SUPPORT EN UN CLIN D'ŒIL

Pour aller plus loin, voici un exemple d'interface qui combine les trois outils précédents : un analyseur de tickets de support complet. Cette page analyse un ticket en temps réel et affiche trois informations clés :

  • Le sentiment (positif, négatif ou neutre).
  • Le service concerné (livraison, facturation, etc.).
  • Les informations clés extraites du texte (numéro de commande, problème, etc.).

Voici le code complet de cette interface :

<.DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Analyseur de tickets de support</title>
  <style>
    * { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; max-width: 800px;
           margin: 2rem auto; padding: 0 1rem; background: #f9fafb; }
    h1   { margin-bottom: 0.25rem; }
    .subtitle { color: #666; margin-bottom: 1.5rem; }

    textarea { width: 100%; height: 130px; padding: 0.75rem;
               font-size: 0.95rem; border: 1px solid #d1d5db;
               border-radius: 6px; resize: vertical; }
    button { padding: 0.6rem 1.8rem; font-size: 1rem;
             background: #2563eb; color: white; border: none;
             border-radius: 6px; cursor: pointer; margin-top: 0.5rem; }
    button:disabled { background: #93c5fd; cursor: not-allowed; }

    #status { font-size: 0.85rem; color: #666; margin: 0.5rem 0; }

    .cards { display: grid; grid-template-columns: repeat(3, 1fr);
             gap: 1rem; margin-top: 1.5rem; }
    .card  { background: white; border-radius: 8px; padding: 1rem;
             border: 1px solid #e5e7eb; }
    .card h3 { margin: 0 0 0.75rem; font-size: 0.9rem;
               text-transform: uppercase; letter-spacing: 0.05em;
               color: #6b7280; }
    .card .value { font-size: 1.15rem; font-weight: 600; }
    .card .sub   { font-size: 0.85rem; color: #666; margin-top: 0.25rem; }

    .positive { color: #16a34a; }
    .negative { color: #dc2626; }
    .neutral  { color: #d97706; }

    .dept-bar { display: flex; align-items: center; gap: 0.5rem;
                margin-top: 0.4rem; font-size: 0.85rem; }
    .bar-bg   { flex: 1; background: #f0f0f0; border-radius: 3px; height: 8px; }
    .bar-fill { background: #2563eb; height: 100%;
                border-radius: 3px; transition: width 0.4s; }

    .qa-item  { margin-top: 0.6rem; font-size: 0.9rem; }
    .qa-label { font-weight: 600; color: #374151; }
    .qa-ans   { color: #111; }
    .qa-low   { color: #9ca3af; font-style: italic; }

    @media (max-width: 600px) {
      .cards { grid-template-columns: 1fr; }
    }
  </style>
</head>
<body>
  <h1>Analyseur de tickets de support</h1>
  <p class="subtitle">Powered by Transformers.js -- exécute entièrement dans votre navigateur</p>

  <textarea id="ticket">
Bonjour, j’ai commandé un support pour ordinateur portable mardi dernier (commande n°73021) mais il est arrivé complètement cassé -- un des bras s’est brisé dès l’ouverture de la boîte. Je suis client depuis trois ans et c’est vraiment très décevant. J’ai besoin qu’un remplacement soit envoyé le plus rapidement possible ou que je sois remboursé intégralement. Merci de me faire savoir ce que vous proposez.
  </textarea>

  <button id="analyze-btn" disabled>Chargement des modèles.</button>
  <div id="status">Initialisation -- téléchargement des modèles en cours.</div>

  <div class="cards" id="cards">
    <div class="card" id="card-sentiment">
      <h3>Sentiment</h3>
      <div class="value" id="sent-label">--</div>
      <div class="sub"   id="sent-score">--</div>
    </div>

    <div class="card" id="card-route">
      <h3>Service concerné</h3>
      <div id="dept-results"></div>
    </div>

    <div class="card" id="card-qa">
      <h3>Informations clés</h3>
      <div id="qa-results"></div>
    </div>
  </div>

  <script type="module">
    import { pipeline } from
      'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]';

    const ticketEl  = document.getElementById('ticket');
    const btn       = document.getElementById('analyze-btn');
    const statusEl  = document.getElementById('status');
    const cardsEl   = document.getElementById('cards');

    const DEPARTEMENTS = [
      'retours et remboursements',
      'livraison et expédition',
      'facturation et paiement',
      'support technique',
      'gestion de compte'
    ];

    const QUESTIONS_QA = [
      { label: 'Numéro de commande',  question: 'Quel est le numéro de commande ?' },
      { label: 'Problème',         question: 'Quel est le problème rencontré ?' }
    ];

    let sentimentModel;
    let routeurModel;
    let qaModel;

    async function loadModels() {
      // Chargement du modèle de sentiment
      sentimentModel = await pipeline(
        'text-classification',
        'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
        { dtype: 'q8', progress_callback: updateStatus }
      );

      // Chargement du modèle de routage
      routeurModel = await pipeline(
        'zero-shot-classification',
        'Xenova/bart-large-mnli',
        { dtype: 'q8', progress_callback: updateStatus }
      );

      // Chargement du modèle de réponse aux questions
      qaModel = await pipeline(
        'question-answering',
        'Xenova/distilbert-base-uncased-distilled-squad',
        { dtype: 'q8', progress_callback: updateStatus }
      );

      btn.textContent = 'Analyser le ticket';
      btn.disabled    = false;
      statusEl.textContent = 'Tous les modèles sont prêts.';
    }

    function updateStatus(progress) {
      if (progress.status === 'progress') {
        statusEl.textContent = Téléchargement des modèles : ${Math.round(progress.progress ?? 0)}%;
      }
    }

    async function analyzeTicket() {
      const text = ticketEl.value.trim();
      if (.text) return;

      btn.disabled         = true;
      btn.textContent      = 'Analyse en cours.';
      cardsEl.style.display = 'none';

      // Analyse du sentiment
      const sentimentResult = await sentimentModel(text);
      const sentimentLabel = sentimentResult[0].label;
      const sentimentScore = (sentimentResult[0].score * 100).toFixed(1);
      const sentimentClass = sentimentLabel === 'POSITIVE' ? 'positive' : 
                            sentimentLabel === 'NEGATIVE' ? 'negative' : 'neutral';
      document.getElementById('sent-label').innerHTML = 
        `${sentimentLabel};
      document.getElementById('sent-score').textContent = ${sentimentScore}% de confiance;

      // Routage du ticket
      const routeResult = await routeurModel(text, DEPARTEMENTS, { multi_label: false });
      const deptWinner = routeResult.labels[0];
      const deptScore = (routeResult.scores[0] * 100).toFixed(1);

      let deptHtml = 
<strong>${deptWinner}</strong> <div class="bar-bg"> <div class="bar-fill"></div> </div> <span>${deptScore}%</span> </div>; document.getElementById('dept-results').innerHTML = deptHtml; // Extraction des informations clés let qaHtml = ''; for (const qa of QUESTIONS_QA) { const result = await qaModel({ question: qa.question, context: text }); const confidence = (result.score * 100).toFixed(1); const answerClass = confidence > 30 ? 'qa-ans' : 'qa-low'; qaHtml += <div class="qa-item"> <div class="qa-label">${qa.label}</div> <div class="${answerClass}">${result.answer || 'Non trouvé'} <span class="confidence">(${confidence}% de confiance)</span></div> </div>; } document.getElementById('qa-results').innerHTML = qaHtml; cardsEl.style.display = 'grid'; btn.disabled = false; btn.textContent = 'Analyser le ticket'; } btn.addEventListener('click', analyzeTicket); loadModels().catch(err => { statusEl.textContent = Erreur : ${err.message}`; }); </script> </body> </html>

Cette interface combine les trois modèles en un seul outil. Lorsqu'un utilisateur colle un ticket de support et clique sur le bouton, l'analyseur détermine :

  • Le sentiment du message (positif, négatif ou neutre).
  • Le service concerné (par exemple, « retours et remboursements »).
  • Les informations clés comme le numéro de commande ou le problème rencontré.

Les résultats sont affichés sous forme de cartes colorées, avec des indicateurs visuels pour faciliter la lecture. Par exemple, un ticket avec un sentiment négatif et un problème de livraison sera automatiquement identifié et aiguillé vers le bon service.

POURQUOI TRANSFORMERS.JS VA BOULEVERSER VOTRE UTILISATION DE L'IA

Transformers.js n'est pas qu'une bibliothèque technique : c'est une révolution dans la façon d'utiliser l'IA. Voici pourquoi elle va changer la donne :

« Plus besoin de dépendre des serveurs distants, des API payantes ou des connexions internet lentes. L'IA devient accessible, instantanée et respectueuse de la vie privée. »

Confidentialité : Vos données restent sur votre appareil. Aucun texte n'est envoyé à un serveur distant, ce qui garantit une protection totale de votre vie privée. Idéal pour les entreprises ou les utilisateurs soucieux de la confidentialité.

Performance : Une fois le modèle téléchargé, les réponses sont instantanées. Pas de latence, pas d'attente, pas de dépendance à une connexion internet. Parfait pour les applications en temps réel.

Accessibilité : Aucune installation complexe, aucune configuration. Il suffit d'un navigateur moderne pour utiliser l'IA. Même sur un smartphone ou une tablette, l'outil fonctionne sans problème.

Coût : Gratuit et open source. Pas de frais d'abonnement, pas de limite d'usage. Vous pouvez l'utiliser autant que vous voulez, sans restriction.

Avec Transformers.js, l'IA devient un outil comme un autre : simple, rapide et disponible partout. Que vous soyez un développeur, un entrepreneur ou un utilisateur lambda, cette technologie ouvre des possibilités infinies.

COMMENT DÉBUTER AVEC TRANSFORMERS.JS : LE GUIDE PRATIQUE

Vous voulez essayer par vous-même ? Voici les étapes à suivre pour intégrer Transformers.js dans votre projet :

  1. Installer la bibliothèque : Ajoutez la ligne suivante dans votre fichier HTML pour importer Transformers.js depuis un CDN :
    <script type="module">
      import { pipeline } from
        'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]';
    </script>
  2. Choisir un modèle : Sélectionnez un modèle adapté à votre tâche. Par exemple, pour la classification de texte, utilisez Xenova/distilbert-base-uncased-finetuned-sst-2-english.
  3. Charger le modèle : Utilisez la fonction pipeline pour charger le modèle avec les options souhaitées (quantification, WebGPU, etc.).
  4. Exécuter une tâche : Appelez le modèle avec vos données pour obtenir une réponse.
  5. Afficher les résultats : Intégrez les résultats dans votre interface utilisateur pour une expérience fluide.

Voici un exemple minimaliste pour démarrer :

async function analyserTexte() {
  const classifier = await pipeline('sentiment-analysis');
  const result = await classifier('Ce produit est incroyable .');
  console.log(result);
  // Affiche : [{ label: 'POSITIF', score: 0.9998 }]
}

analyserTexte();

Avec ces quelques lignes, vous avez déjà un classifieur de sentiment fonctionnel dans votre navigateur .

LES LIMITES À CONNAÎTRE : CE QUE TRANSFORMERS.JS NE PEUT PAS FAIRE

Malgré ses nombreux avantages, Transformers.js a quelques limites qu'il faut garder à l'esprit :

  • Taille des modèles : Les modèles d'IA sont lourds. Même après quantification, ils peuvent occuper plusieurs centaines de Mo de mémoire. Sur un smartphone avec peu de stockage, cela peut poser problème.
  • Puissance de calcul : Les modèles nécessitent une certaine puissance de calcul. Sur un ordinateur très ancien ou un smartphone bas de gamme, les performances peuvent être lentes.
  • Précision limitée : Les modèles allégés utilisés par Transformers.js sont moins précis que leurs équivalents serveurs. Pour des tâches critiques (comme le diagnostic médical), il est préférable d'utiliser une solution serveur.
  • Pas de fine-tuning : Vous ne pouvez pas entraîner ou adapter les modèles directement dans le navigateur. Pour cela, il faut utiliser des outils comme Hugging Face Transformers en Python.

Ces limites ne remettent pas en cause l'utilité de Transformers.js, mais elles montrent qu'il faut choisir la bonne solution en fonction de ses besoins. Pour des tâches simples et rapides, cette bibliothèque est parfaite. Pour des applications critiques, une solution serveur reste indispensable.

TRANSFORMERS.JS DANS VOTRE PROJET : QUELQUES IDÉES D'APPLICATIONS

Transformers.js peut être utilisé dans de nombreux contextes. Voici quelques idées pour vous inspirer :

  • Chatbots locaux : Créez un chatbot qui fonctionne sans connexion internet, idéal pour les applications mobiles ou les kiosques.
  • Modération de contenu : Analysez automatiquement les commentaires ou les messages pour détecter les contenus inappropriés ou toxiques.
  • Génération de résumés : Résumez automatiquement de longs articles ou documents pour gagner du temps.
  • Traduction instantanée : Utilisez un modèle de traduction pour traduire des textes en temps réel, sans serveur.
  • Analyse de sentiment en temps réel : Suivez l'opinion des utilisateurs sur les réseaux sociaux ou les forums en analysant leurs messages.
  • Assistant personnel : Créez un assistant qui répond à vos questions en extrayant les informations d'un document ou d'une base de connaissances.

Les possibilités sont presque infinies. Avec un peu de créativité, vous pouvez intégrer Transformers.js dans presque tous vos projets web pour ajouter une touche d'IA intelligente et locale.

TRANSFORMERS.JS VS LES SOLUTIONS TRADITIONNELLES : LE COMPARATIF

Pour mieux comprendre les avantages de Transformers.js, voici un comparatif avec les solutions traditionnelles d'IA :

« Transformers.js change la donne : pas de latence, pas de dépendance, pas de coût. L'IA devient un outil comme un autre. »
Critère Transformers.js Solution serveur (API)
Latence Instantanée (ms) 1-5 secondes (dépend de la connexion)
Coût Gratuit Payant (abonnements ou paiement à l'usage)
Confidentialité Totale (données locales) Limitée (données envoyées à un serveur distant)
Accessibilité Partout (navigateur moderne) Nécessite une connexion internet et une API
Personnalisation FAQ : TOUTES LES QUESTIONS SUR TRANSFORMERS.JS

Vous avez des questions sur Transformers.js ? Voici les réponses aux questions les plus fréquentes :

QU'EST-CE QUE TRANSFORMERS.JS ?

Transformers.js est une bibliothèque JavaScript qui permet d'exécuter des modèles d'intelligence artificielle directement dans le navigateur, sans avoir besoin de serveur distant. Elle est basée sur la même technologie que les grands modèles de langage comme BERT ou DistilBERT, mais optimisée pour fonctionner en local.

QUELLES TÂCHES PEUT-ON RÉALISER AVEC TRANSFORMERS.JS ?

Transformers.js permet de réaliser plusieurs types de tâches :

  • Classification de texte : Attribuer une catégorie à un texte (positif, négatif, spam, etc.).
  • Classement zéro-exemple : Classer un texte dans une catégorie sans avoir besoin de données d'entraînement.
  • Réponse aux questions : Extraire une réponse précise d'un texte long.
  • Résumé automatique : Générer un résumé d'un article ou d'un document.
  • Traduction automatique : Traduire un texte d'une langue à une autre.

COMMENT CHOISIR UN MODÈLE ?

Le choix du modèle dépend de la tâche que vous souhaitez réaliser :

  • Pour la classification de sentiment, utilisez Xenova/distilbert-base-uncased-finetuned-sst-2-english.
  • Pour le routage de tickets, utilisez Xenova/bart-large-mnli.
  • Pour la réponse aux questions, utilisez Xenova/distilbert-base-uncased-distilled-squad.

Vous pouvez trouver une liste complète des modèles compatibles sur le site Hugging Face.

PEUT-ON UTILISER TRANSFORMERS.JS SUR MOBILE ?

Oui . Transformers.js fonctionne sur tous les navigateurs modernes, y compris ceux des smartphones et tablettes. Cependant, la performance dépend de la puissance de l'appareil. Sur un smartphone bas de gamme, les modèles lourds peuvent être lents à charger ou à exécuter.

COMMENT OPTIMISER LES PERFORMANCES ?

Pour améliorer les performances, vous pouvez :

  • Utiliser la quantification pour réduire la taille des modèles (par exemple, dtype: 'q4').
  • Activer le WebGPU si votre appareil est compatible pour accélérer les calculs.
  • Précharger les modèles pour éviter les temps de chargement.
  • Utiliser des modèles plus petits pour les tâches simples.

TRANSFORMERS.JS EST-IL SÉCURISÉ ?

Oui . Puisque tout se passe dans le navigateur, vos données ne quittent jamais votre appareil. Aucun texte n'est envoyé à un serveur distant, ce qui garantit une confidentialité totale. C'est un avantage majeur par rapport aux solutions serveurs où les données sont souvent stockées et analysées par des tiers.

PEUT-ON ENTRAÎNER UN MODÈLE AVEC TRANSFORMERS.JS ?

Non. Transformers.js permet uniquement d'exécuter des modèles pré-entraînés. Pour entraîner ou adapter un modèle, il faut utiliser des outils comme Hugging Face Transformers en Python.

QUEL EST LE COÛT DE TRANSFORMERS.JS ?

Transformers.js est gratuit et open source. Vous pouvez l'utiliser sans restriction, sans frais d'abonnement ni limite d'usage. La seule contrainte est la taille des modèles, qui peut occuper de l'espace de stockage sur votre appareil.

EN CONCLUSION : L'IA LOCALE EST L'AVENIR

Transformers.js représente une avancée majeure dans l'utilisation de l'intelligence artificielle. En permettant d'exécuter des modèles directement dans le navigateur, elle rend l'IA accessible à tous, sans dépendance, sans coût et sans compromettre la confidentialité. Que vous soyez un développeur, un entrepreneur ou simplement un utilisateur curieux, cette technologie ouvre des possibilités infinies.

Les trois exemples concrets présentés dans cet article montrent à quel point Transformers.js est puissant et facile à utiliser. Que ce soit pour classer des textes, router des tickets de support ou répondre à des questions sur un document, cette bibliothèque transforme votre navigateur en une plateforme d'IA complète.

Alors, prêt à essayer ? Téléchargez un modèle, intégrez-le dans votre projet, et découvrez par vous-même comment l'IA peut devenir un outil du quotidien, sans serveur, sans API, et sans limite.

« L'intelligence artificielle n'a jamais été aussi proche de vous. Et si vous commenciez dès aujourd'hui ? »
Sources :
  • KDnuggets

L'indépendance de CLODCO est votre garantie.

Pour que l'actualité de l'IA reste sans filtre et sans concession, votre soutien est indispensable. Votre contribution est le seul moteur de notre liberté éditoriale.

Soutenir CLODCO
Chargement des recommandations...