Pourquoi la liste de « sources » de votre chatbot IA est sans doute fausse

ai-agents

Presque tous les chatbots de support IA affichent une rangée de sources sous leurs réponses. C’est ce qui donne à la réponse l’air d’être vérifiable : voici d’où je tiens ça.

Dans la plupart des implémentations, cette rangée vous ment. Sans malveillance, mais elle répond à une autre question que celle que pose l’utilisateur.

Récupéré ne veut pas dire utilisé

Un chatbot à génération augmentée par récupération (RAG) répond à peu près ainsi : il cherche dans la base de connaissances, place les meilleurs résultats dans le contexte du modèle et le laisse écrire. La façon évidente de construire la rangée de sources, c’est d’afficher tout ce que cette recherche a renvoyé.

C’est ce que font la plupart des produits, et c’est faux d’une façon bien précise. Une recherche sémantique renvoie dix candidats, parce que dix est un nombre raisonnable de documents à proposer au choix d’un modèle de langage. Le modèle les lit, puis en utilise un. Afficher les dix comme sources dit à l’utilisateur que dix articles ont nourri la réponse, alors que neuf ont été écartés.

L’échec ne fait pas de bruit. Personne n’ouvre un ticket disant « la rangée de sources contient trop d’éléments ». Les utilisateurs apprennent simplement, peu à peu, que la rangée est décorative, et cessent de la lire. Vous avez payé tout le coût technique des citations sans obtenir la confiance qu’elles devaient vous apporter.

Quand la réponse liste tous les articles

L’échec devient plus visible dès qu’un utilisateur pose une question sur la structure.

« Sur quels sujets avez-vous des articles ? »

Un bon assistant répond par la liste de vos articles. La rangée de sources contient alors tous les articles de votre centre d’aide et répète, juste sous la réponse, exactement les liens qu’elle contient déjà. L’utilisateur voit les trente mêmes titres deux fois.

C’est là que l’abstraction se brise sous vos yeux, et il faut le prendre au sérieux, parce que cela révèle le vrai bug : on ne peut pas déduire la provenance de la récupération. Il faut la déduire de ce que le modèle a fait.

Trois ensembles, pas un seul

Pour corriger, cessez de traiter tout cela comme une seule liste. Derrière chaque réponse, il y a trois ensembles de documents distincts :

Récupérés — tout ce qu’un outil a renvoyé pendant l’échange. C’est l’ensemble que la plupart des produits affichent. Son vrai rôle est autre, et il compte : c’est la liste d’autorisation. Si le modèle cite un document qui n’a jamais été récupéré, il a inventé la référence, et vous l’écartez. Cette vérification n’a rien de théorique. Lors de mes propres tests, un modèle qui recopiait trente identifiants de documents s’est trompé d’un seul caractère sur l’un d’eux ; le garde-fou l’a détecté et a refusé de transformer un identifiant corrompu en source.

Cités — les documents vers lesquels la réponse pointe réellement. C’est ce qui rend les citations dans le texte cliquables, et c’est une base honnête pour une facturation à l’usage.

Consultés — les documents dont le modèle a lu le texte. C’est le seul ensemble qui a sa place dans une rangée de sources.

Personne ne calcule le troisième ensemble, et pourtant ce n’est pas difficile. Vous savez déjà quel outil a renvoyé chaque document. Certains outils donnent au modèle du vrai contenu : une recherche qui renvoie des extraits, ou un appel « récupérer ce document » qui renvoie le texte complet. D’autres lui donnent une table des matières : lister les catégories, lister les articles, parcourir une section. Ceux-là renvoient des titres.

Donc :

  • Le modèle a ouvert un document en entier → c’est une source, que la réponse contienne un lien vers lui ou non. L’avoir ouvert, c’est la provenance. Si le modèle résume un article et oublie d’écrire un lien Markdown, c’est un oubli de mise en forme, pas une absence de preuve.

  • Une recherche l’a renvoyé et la réponse l’a cité → c’est une source. La citation indique lequel des dix candidats a servi.

  • Le modèle ne l’a vu que comme un titre dans une liste → ce n’est jamais une source, même si la réponse contient un lien vers lui.

Avec cette règle, « quels articles avez-vous ? » produit une liste propre de liens qui fonctionnent, sans aucune rangée de sources, parce que le modèle n’a rien lu. Et « comment configurer le SSO ? » produit un paragraphe avec une ou deux pastilles en dessous : les articles qu’il a réellement lus.

Le détail de conception qui piège

L’implémentation cache un piège, et il vaut la peine de le nommer, car il est facile de se tromper d’une manière qui semble correcte jusqu’à ce qu’un utilisateur clique quelque part.

Votre tableau de sources remplit en général deux rôles. Ce sont les données derrière les pastilles, et c’est la table de correspondance qui rend les citations du texte cliquables : le gestionnaire de clic cherche l’identifiant du document cité dans ce tableau et l’ouvre.

Vous ne pouvez donc pas simplement réduire le tableau à l’ensemble consulté. Faites-le, et chaque lien d’une réponse en forme de liste devient un lien mort : affiché comme une citation, stylé comme une citation, et inerte au clic.

Gardez tout l’ensemble cité dans le payload, marquez chaque élément d’un indicateur, et ne filtrez qu’au moment de l’affichage. Un booléen par source, filtré dans le rendu. Les liens continuent de fonctionner ; les pastilles disent la vérité.

Rendez l’indicateur facultatif

Si vous livrez ce changement dans une API, rendez le champ facultatif plutôt qu’obligatoire, et traitez une valeur absente comme « oui, à afficher ».

Cette seule décision fait qu’un ancien client face à un nouveau serveur continue de fonctionner, et qu’un nouveau client face à un ancien serveur revient au comportement précédent au lieu de masquer toutes les sources. Vous ne déploierez pas les deux côtés au même instant, et les utilisateurs gardent des copies de votre widget en cache plus longtemps que vous ne le voudriez.

Pourquoi ça vaut l’effort

Une rangée de sources est une affirmation : cette réponse vient de ces documents. Si l’affirmation est tirée de la récupération, elle est à peu près vraie, et les utilisateurs finissent par le remarquer. Si elle est tirée de ce que le modèle a réellement lu, elle est exactement vraie, et elle devient le moyen le plus rapide pour votre équipe support de vérifier une réponse qui a mal tourné.

Il y a un second bénéfice. Dès que « aucune source » signifie à coup sûr « le modèle n’a rien lu », cela devient un vrai signal. Une réponse sans source à une vraie question sur le produit révèle une lacune de la documentation : vous pouvez filtrer ces réponses et en faire une liste d’articles à écrire.

Cela ne marche que si la rangée veut dire quelque chose.


L’assistant de chat IA de Kookee suit la règle ci-dessus : la rangée Sources montre les articles sur lesquels une réponse s’appuie, et chaque article lié dans la réponse reste cliquable. Pour les détails, voir Comment l’assistant choisit ses sources ; pour la vue d’ensemble, Créer un centre d’aide pour votre SaaS.