Lesson 1 — Le cas d'usage et l'architecture

Le SAV et ses garde-fous

5 min read

This content is not translated yet. Showing the original version.

Le SAV et ses garde-fous

Le cas d'usage

Roue Libre (boutique fictive) reçoit chaque jour les mêmes questions : délais, frais de livraison, retours, garantie de la batterie. Sa FAQ tient en 16 entrées (faq.json) :

files/faq.json (extrait)
{"id": "FAQ-07", "categorie": "retours", "question": "Quand serai-je remboursé ?",
 "reponse": "Le remboursement est effectué sur le moyen de paiement d'origine sous 10 jours après réception et contrôle du retour à l'entrepôt."}

Chaque entrée a un identifiant stable (FAQ-07). C'est lui que l'assistant citera, et c'est lui que le code vérifiera.

Pourquoi refuser est une fonctionnalité

Un client demande « Proposez-vous une assurance contre le vol ? ». La FAQ n'en parle pas. Un modèle sans garde-fou répondra souvent quelque chose de plausible (« oui, en partenariat avec… ») : c'est une hallucination, et dans un SAV elle engage la boutique. La bonne réponse est : « Je ne sais pas, un conseiller peut vous répondre. »

RéponseCoût pour la boutique
juste et citéeaucun : le client est servi
« Je ne sais pas » + contactun ticket pour un humain
inventéepromesse non tenue, litige, perte de confiance

Les trois niveaux de refus

flowchart TD
  Q["Question"] --> N1{"1. Seuil : une entrée est-elle assez proche ?"}
  N1 -- "non" --> R1["Refus immédiat, sans appel au modèle"]
  N1 -- "oui" --> N2{"2. Le modèle juge-t-il que les entrées répondent ?"}
  N2 -- "non" --> R2["Je ne sais pas"]
  N2 -- "oui" --> N3{"3. Code : la réponse cite-t-elle des id récupérés ?"}
  N3 -- "non" --> R3["Remplacée par un refus"]
  N3 -- "oui" --> OK["Réponse envoyée au client"]
  R1 --> J["Journal des questions non couvertes"]
  R2 --> J
  R3 --> J
  1. Le seuil est déterministe et gratuit : on compare le meilleur score de similarité à une valeur calibrée. Il élimine les questions franchement hors sujet.
  2. Le modèle élimine les cas subtils : l'entrée la plus proche parle de livraison, mais pas de livraison en Suisse.
  3. Le code ne fait confiance à personne : une réponse sans [FAQ-xx] ou avec un identifiant qui n'a pas été récupéré est rejetée.

Pourquoi le premier niveau de refus (le seuil) est-il placé avant l'appel au modèle ?

Quels refus doivent alimenter le journal des questions non couvertes ?

Chaîne simple ou agent ?

Le lab propose deux versions qui partagent le même cœur (faq_rag.rechercher) :

Chaîne simple (faq_rag.repondre)Agent ADK (agent.py)
Appels de génération par question0 ou 12 en général (décider l'outil, puis répondre)
Reformulation de la questionnonoui, l'agent choisit le texte envoyé à l'outil
Conversation sur plusieurs toursà codergérée par la session ADK
Quand la choisirFAQ, une question = une réponsedialogue, plusieurs outils (suivi de commande…)

Exercice : trouver les questions pièges

Sans lancer de code, classez ces questions : couverte par la FAQ, hors périmètre évident, ou piège (proche d'une entrée mais non couverte). « Livrez-vous à Bruxelles ? », « Livrez-vous à Genève ? », « Puis-je louer un vélo ? », « Quel temps fera-t-il demain ? ».

Voir la solution
QuestionClassementPourquoi
Livrez-vous à Bruxelles ?couverteFAQ-03 : Belgique, 7 à 10 jours
Livrez-vous à Genève ?couverteFAQ-03 dit explicitement « pas en Suisse » : la bonne réponse est « non », citée
Puis-je louer un vélo ?piègeproche de FAQ-16 (essais), mais la location n'est pas mentionnée
Quel temps fera-t-il demain ?hors périmètre évidentaucun lien avec la FAQ

Les pièges sont ceux qui mettent le seuil en difficulté : leur score est plus haut que celui d'une question absurde. C'est pour eux que le niveau 2 existe.

Résultat obtenu

Exécution réelle du 2026-10-15, chaîne simple :

$ python faq_rag.py ask "Combien coûte la livraison d'un vélo ?"
La livraison d'un vélo coûte 39 euros, montage compris [FAQ-02].
  (sources : ['FAQ-02', 'FAQ-01'], raison du refus : None)
$ python faq_rag.py ask "Vendez-vous des trottinettes ?"
Je ne sais pas : cette question n'est pas couverte par notre FAQ. Un conseiller peut vous répondre via le formulaire de contact.
  (sources : [], raison du refus : seuil)

La seconde question a été refusée au niveau 1 : aucun appel de génération.

Je sais faire

  • Expliquer pourquoi un refus vaut mieux qu'une réponse inventée dans un SAV
  • Décrire les trois niveaux de refus et leur coût
  • Choisir entre chaîne simple et agent
Next