Aller au contenu
en ce moment

Guides

Routage de tickets avec l’IA : Strands Decider 2B en Python

Un modèle de décision local pour router vos tickets de support en Python : certitude du choix, seuil de repli vers un humain et détection des urgences.

Par 9 min de lecture
Routage de tickets avec l’IA : Strands Decider 2B en Python

👁 118 lectures

Un modèle de décision est bien plus adapté au routage de tickets qu’un simple modèle de chat : il choisit un pôle dans votre liste, attribue un score de confiance et vous permet de renvoyer automatiquement les cas incertains vers un opérateur humain. Voici un script Python fonctionnel utilisant le modèle ouvert Strands Decider 2B que nous avons testé sur notre machine, avec nos résultats et deux pièges à éviter. Pour comprendre le fonctionnement de ces modèles et leurs performances sur notre banc d’essai de 30 tickets, consultez notre guide complet sur les modèles de décision IA.

Les montants en EUR sont des conversions indicatives des prix publiés en USD, calculées au taux de référence de la BCE du 2026-10-12 : 1 EUR = 1.1181 USD. Il ne s’agit pas de tarifs locaux confirmés ni de montants finaux toutes taxes comprises. Le fournisseur et la banque peuvent appliquer d’autres taux ou frais. ECB.

Ce que nous allons construire

Un script qui renvoie, pour chaque ticket entrant :

  • le pôle - l’un des 6 services définis (paiements, livraison, retours, compte, pannes, ventes) ou « autre »,
  • la confiance de la décision, notée de 0 à 1,
  • la file de destination - le service ciblé si le score est suffisant, ou do_czlowieka (vers l’humain),
  • l’urgence - booléen indiquant si l’incident exige une intervention immédiate dans la journée.

Le résultat produit une ligne JSON par ticket, prête à être injectée dans votre outil de helpdesk, un tableur ou un flux d’automatisation.

Les prérequis

  • Python 3.10 ou version plus récente.
  • PyTorch - configuré avec CUDA si vous disposez d’une carte NVIDIA (le modèle consomme un peu moins de 4 Go de VRAM). Sans GPU dédié, l’exécution sur processeur reste possible, mais plus lente.
  • Le package strands-decider (licence Apache-2.0). Au premier démarrage, il télécharge environ 4,4 Go : le modèle de base Qwen3.5-2B-Base et l’adaptateur fourni par AWS.
pip install strands-decider

Sous Windows, l’installateur pip remplace parfois la variante PyTorch CUDA par une version CPU standard. Vérifiez votre environnement avec python -c "import torch; print(torch.cuda.is_available())". Si la console affiche False, réinstallez PyTorch depuis l’index pytorch.org adapté à votre version de CUDA - un contretemps auquel nous avons nous-mêmes été confrontés.

Le script routing.py

# Routage de tickets avec le modele de decision Strands Decider 2B (en local, Apache-2.0).
# pip install strands-decider   (avec PyTorch et CUDA si vous avez une carte NVIDIA)
import json, sys
from strands_decider.infer import load_engine
from strands_decider.schema import SystemOneRequest

MODEL = "StrandsAgents/strands-decider-2B-hobson-v19"
DZIALY = {
    "platnosci": "Płatności, faktury, obciążenia karty, abonament",
    "dostawa": "Wysyłka, kurier, śledzenie paczki, adres dostawy",
    "zwrot": "Zwroty towaru, reklamacje, wymiana, uszkodzony produkt",
    "konto": "Logowanie, hasło, dane konta, bezpieczeństwo konta, RODO",
    "awaria": "Błędy aplikacji lub strony, awarie, integracje, wydajność",
    "sprzedaz": "Pytania o ofertę, plany, rabaty, wdrożenia dla firm",
    "inne": "Z treści nie da się ustalić, czego dotyczy zgłoszenie",
}
PROG_DZIAL = 0.60   # en dessous de ce score de confiance, le ticket part a un humain
PROG_PILNE = 0.40   # seuil calibre sur nos 30 tickets de test - a adapter a vos donnees

moteur = load_engine(MODEL, device="cuda")  # "cpu" fonctionne aussi, mais plus lentement

def router(texte: str) -> dict:
    requete = SystemOneRequest(state=texte, questions={
        "dzial": {"type": "choice", "instructions": "Do którego działu trafia to zgłoszenie?", "criteria": DZIALY},
        "pilne": {"type": "noul", "instructions": "Czy zgłoszenie wymaga reakcji jeszcze dziś (awaria, utrata pieniędzy, włamanie, nieprzekraczalny termin)?"},
    })
    reponse = moteur.evaluate(requete).answers
    dzial, confiance, p_urgent = reponse["dzial"].choice, reponse["dzial"].confidence, reponse["pilne"].noul
    file = dzial if confiance >= PROG_DZIAL and dzial != "inne" else "do_czlowieka"
    return {"file": file, "pole": dzial, "confiance": round(confiance, 2),
            "urgent": p_urgent >= PROG_PILNE, "p_urgent": round(p_urgent, 2)}

if __name__ == "__main__":
    for ligne in sys.stdin:
        if ligne.strip():
            print(json.dumps({"texte": ligne.strip()[:60], **router(ligne)}, ensure_ascii=False))

Traduction des critères testés en polonais : platnosci = paiements, factures, débits, abonnement ; dostawa = livraison, coursier, suivi, adresse ; zwrot = retours, réclamations, échange, produit endommagé ; konto = connexion, mot de passe, compte, sécurité, RGPD ; awaria = bugs d’application ou de site, pannes, intégrations, performances ; sprzedaz = questions commerciales, offres, remises, intégration pro ; inne = impossible de déterminer l’objet de la demande. Questions associées : « À quel service ce ticket doit-il être adressé ? » et « Ce ticket nécessite-t-il une réaction dès aujourd’hui (panne, perte d’argent, intrusion, échéance critique) ? »

Quelques choix d’architecture à noter :

  • Nous avons testé les critères en polonais. Dans notre banc d’essai, ces descriptions locales ont fonctionné aussi bien que des définitions en anglais, tout en étant plus faciles à relire et maintenir pour une équipe support.
  • Deux questions regroupées en un seul appel. Le modèle traite le contexte une seule fois et évalue les questions en parallèle pour un coût marginal nul. Ajouter un troisième critère (par exemple « le client menace-t-il de résilier ? ») n’augmente pas la latence.
  • La décision finale revient au code, pas au modèle. L’IA renvoie de simples probabilités : c’est votre logique Python qui applique les seuils et oriente les flux, ce qui rend le paramétrage modulable sans retoucher au modèle.

Exécution et résultats

Le script lit les tickets sur l’entrée standard, à raison d’une ligne par demande :

python routing.py < zgloszenia.txt

Voici les mesures obtenues sur notre GeForce RTX 4090 pour six requêtes que le système n’avait jamais traitées auparavant (nous avons mené ce test sur des messages rédigés en polonais) :

Ticket Sans option « autre » Avec option « autre »
Od rana nie działa logowanie przez Google, cały zespół stoi. (Depuis ce matin la connexion via Google ne fonctionne plus, toute l’équipe est bloquée.) compte 0,54 - humain, urgent compte 0,46 - humain, urgent
Proszę o fakturę VAT na firmę do zamówienia 77120. (Merci d’éditer une facture avec TVA pour ma société pour la commande 77120.) paiements 0,46 - humain autre 0,63 - humain
Paczka wróciła do nadawcy, bo kurier nie mógł znaleźć adresu. (Le colis est retourné à l’expéditeur car le livreur n’a pas trouvé l’adresse.) livraison 0,96 livraison 0,90
Czy macie zniżki dla szkół i uczelni? (Proposez-vous des tarifs réduits pour les écoles et universités ?) ventes 0,58 - humain ventes 0,31 - humain
Hej, mam pytanie. Coś mi nie gra. (Bonjour, j’ai une question. Quelque chose ne tourne pas rond.) panne 0,80 panne 0,41 - humain
Zwracam kurtkę, ale nie wiem, czy zwrot pójdzie na kartę czy na konto. (Je renvoie une veste, mais j’ignore si le remboursement sera versé sur ma carte ou mon compte.) retours 0,94 retours 0,84

Sur notre GPU, chaque requête a pris environ 135 ms, après une phase d’initialisation du modèle de 16 s. Toutes les demandes classées automatiquement ont atteint le bon service. De son côté, l’alerte d’urgence ne s’est déclenchée que pour le blocage de connexion impactant l’équipe au complet : le comportement attendu a été parfaitement respecté.

Premier piège : l’excès de confiance sur un message vague

Dans notre première version, nous n’avions pas prévu d’option « autre ». Face au message vague « Hej, mam pytanie. Coś mi nie gra. » (« Bonjour, j’ai une question. Quelque chose ne tourne pas rond. »), le modèle a choisi la catégorie panne avec une confiance de 0,80. Ce score dépassant notre seuil, le ticket aurait été envoyé à tort aux ingénieurs support. Il ne s’agit pas d’une défaillance du modèle : contraint de choisir parmi six catégories, la somme de ses probabilités doit toujours être égale à 1. Un modèle de décision ne répondra jamais « je ne sais pas » sans porte de sortie explicite.

La parade : créer une catégorie inne (« autre ») accompagnée de l’instruction « le contenu ne permet pas de déterminer l’objet de la demande », assortie d’une règle dans le code qui réoriente d’office cette classe vers un opérateur humain. Avec cet ajustement, le score sur le message creux est tombé à 0,41, provoquant son transfert vers un agent.

Second piège : l’option « autre » dilue la certitude

Insérer un choix fourre-tout a une contrepartie : la probabilité globale se disperse. La confiance a légèrement fléchi, y compris sur des cas évidents (le colis est passé de 0,96 à 0,90, la veste de 0,94 à 0,84), et la demande de facture a fini dans « autre » plutôt que dans les paiements. Pour corriger ce biais :

  • Enrichissez vos descriptions avec le vocabulaire métier exact. Si une demande de facture glisse vers « autre », intégrez explicitement « facture avec TVA, facture rectificative, duplicata » dans la définition du service facturation.
  • Calibrez votre seuil de déclenchement sur votre historique. Isolez 50 à 100 tickets déjà traités, soumettez-les au script et déterminez à quel niveau de confiance l’automatisation atteint le zéro faute. Notre seuil de 0,60 sert de point de départ, pas de dogme.
  • Surveillez la proportion d’escalades humaines. Si plus de 30 à 40 % des tickets partent vers l’humain, vos définitions manquent de netteté ou vos services se chevauchent.

Mesurer l’urgence : un curseur à étalonner

Lors de nos essais sur 30 tickets, Strands Decider a attribué aux cas critiques une probabilité comprise entre 0,22 et 0,47. Avec un seuil arbitraire placé à 0,5, aucun incident n’aurait été signalé comme urgent, d’où notre choix de fixer le curseur à 0,40 dans le script. À l’inverse, le modèle plus volumineux Clef-flash de Cloudflare avait tendance à surévaluer l’urgence et donnait ses meilleurs résultats avec un seuil à 0,95. La règle reste constante : traitez les sorties probabilistes comme un score relatif et déterminez le seuil de bascule sur vos propres données de test.

Comment basculer sur un autre moteur

Strands Decider, Cloudflare Clef, ainsi que Kev et Jev de TypeSafe partagent la même structure de requêtes (System One : state + questions). Le code peut migrer vers ces alternatives simplement en modifiant l’interface d’appel :

  • Clef-flash en local (sur GPU 24 Go) : via la méthode systemone() du fichier joint_schema_model.py disponible dans le dépôt Cloudflare/clef-flash. Lors de nos benchmarks, il s’est montré légèrement plus véloce (112 ms) et plus tranché, mais réclame 18 Go de VRAM. Retrouvez notre retour complet dans notre article dédié à Cloudflare Clef.
  • Workers AI : par un simple appel POST sur l’endpoint /ai/run/@cf/cloudflare/clef-flash avec la même structure JSON, facturé 0,0805 EUR (0,09 USD) pour un million de tokens en entrée avec un quota gratuit quotidien (compte Cloudflare nécessaire).
  • Serveur HTTP Strands : via la commande strands-decider serve ... --port 8000 et des requêtes adressées à /v1/systemone, ce qui évite au script Python d’instancier lui-même les poids du modèle en mémoire.

Pour approfondir les détails d’architecture, la licence et les scores complets, parcourez notre dossier sur Strands Decider 2B.

Dans quels cas éviter les modèles de décision pour le tri

  • Si vous souhaitez générer directement une réponse rédigée au client : cette tâche nécessite un grand modèle génératif (LLM). En revanche, le modèle de décision peut parfaitement sélectionner le template de réponse adéquat.
  • Si votre flux se limite à une poignée de messages par jour : solliciter un modèle généraliste avec du JSON structuré se révèle plus direct (une méthode détaillée dans notre guide sur le Structured output).
  • Si l’organisation de vos équipes change chaque semaine sans historique étiqueté : vous manquerez de recul pour étalonner des seuils statistiques fiables.
Google · Vos sourcesPromptif plus haut dans Google - en un clicAjouter aux sources préférées →

Sources

Kinetyra

// read next

More on this from PROMPTIF

Promptif

Promptif

ADMINISTRATOR
à lire ensuiteQuelle IA pour la musique de vidéo ? Notre comparatifoutils d'iaQuelle IA pour la musique de vidéo ? Notre comparatifQuelle IA choisir pour la musique de fond d'une vidéo ? Comparatif entre Eleven Music, Stable Audio 3 et Suno : licences, prompts et tarifs.

Les plus lus

  1. 1Applications de génération vidéo IA : Kling, PixVerse et autres
  2. 2Calendrier IA 2026 : lancements de modèles, conférences et IA Act
  3. 3Affaire Thélyson Orélien : j’ai testé le roman avec trois détecteurs d’IA. Même paragraphe : 100 %, 85 % et 0 %
// plan du site

Cette page dans d’autres langues6

promptif en chiffres 0textes dans les archives0actus des 7 derniers jours0modèles vidéo dans l'observatoire
🎬 Studio Vidéo IA : Higgsfield AI DoP Presets Caméra & Calculateur • Code Promo Higgsfield AI -50% • Higgsfield vs Kling AI
× ‹ agrandissement ›