Comment les réponses restent ancrées dans les faits
Un assistant intégré à la documentation n’a de valeur que s’il n’invente pas de contenu. Une réponse erronée énoncée sur un ton assuré coûte plus cher que l’absence d’assistant : le lecteur agit en conséquence, et votre équipe d’assistance en subit les conséquences dès le lendemain.
La question importante n’est donc pas « utilise-t-il l’IA ? » — c’est à partir de quelles sources le modèle est-il autorisé à répondre, et que se passe-t-il lorsque le passage pertinent ne se trouve pas devant lui. Cette page apporte la réponse, avec le niveau de détail que vous obtiendriez en consultant l’implémentation.
Ce que vous obtenez#
Chaque réponse que voit le lecteur est rédigée à partir du texte des pages que Docsbook a récupéré pour cette question précise, dans le cadre de cette requête. Le lecteur voit le processus : le widget affiche Found N results ainsi qu'une ligne Reading <page> pour chaque page ouverte, chacune étant un lien vers la page elle-même. Sous la réponse figure une liste de citations, et une citation n'est conservée que si le modèle a cité le chemin de cette page dans sa propre réponse ou si le serveur a effectivement récupéré cette page pour cette question. Un chemin inventé par le modèle et jamais cité ne peut pas devenir une citation.
Lorsque la récupération ne trouve rien de pertinent, il est demandé au modèle d'indiquer que la documentation ne couvre pas le sujet plutôt que de composer une réponse plausible. Ce refus est enregistré, et non ignoré : il devient une ligne dans votre rapport des questions sans réponse ainsi qu'un webhook chat.no_answer, ce qui vous indique quelle page rédiger ensuite.
Comment une réponse est-elle produite ?#
Sept étapes, dans cet ordre. Chaque étape ci-dessous correspond à une branche réelle de la requête, et non à un diagramme.
1. Vos documents sont divisés en unités, puis vectorisés#
L’indexation automatique s’effectue à la granularité des titres : une unité par section d’une page. Le texte envoyé au modèle de vectorisation est le fil d’Ariane du titre de la section suivi du corps de la section — Billing > Refunds devant le texte sur les remboursements — car une section appelée « Limites » signifie quelque chose de différent sous « Webhooks » et sous « Chat IA », et le vecteur doit conserver cette différence. Chaque unité est limitée à 6 000 caractères. La granularité au niveau de la page et de la ligne existe également dans l’indexeur ; le chemin automatique utilise les titres.
L’identité d’une unité correspond au chemin de sa page et à son ancre de titre. Les ancres se répètent au sein d’une page — un journal des modifications peut contenir quarante titres ### Fixed — et une ancre répétée reçoit donc un suffixe ordinal. Sans cela, chacune de ces sections constituerait la même unité, et l’écriture entrerait en conflit.
2. Les unités deviennent des vecteurs, et les unités inchangées ne coûtent rien#
Les embeddings sont openai/text-embedding-3-small, 1 536 dimensions, demandés via OpenRouter par lots de 96 unités par appel. La colonne de stockage est un vector(1536), et un modèle renvoyant une largeur différente est immédiatement rejeté plutôt que d’être enregistré puis détecté comme incohérent ultérieurement.
Chaque unité contient un hachage de contenu de sha256(model + NUL + text). Lors d’une réindexation, toute unité dont le hachage est déjà enregistré est ignorée : modifier une page ne coûte donc que l’équivalent de l’embedding d’une page, et non celui de l’ensemble du corpus. L’estimation qui vous est affichée avant une exécution comporte un nombre exact d’unités (le séparateur est déterministe et a déjà été exécuté) et un nombre approximatif de tokens de characters ÷ 4 — considérez ce chiffre comme pouvant varier de ±30 %, raison pour laquelle il est présenté comme une estimation et non comme le prix.
3. La réindexation suit vos commits#
Chaque commit apporté à votre documentation met une réindexation en file d’attente. Une exécution en attente est prise en charge par un processus d’arrière-plan toutes les deux minutes, et non par un callback attaché à la réponse déjà envoyée — c’est précisément ce qui finissait auparavant par s’interrompre en cours d’exécution et par laisser derrière lui un index estampillé, mais vide. Les commits consécutifs effectués dans un délai de cinq minutes sont regroupés en une seule exécution, puisqu’un flux de publication valide le contenu, puis la navigation, puis l’image de marque.
La décision d’utiliser ou non la recherche sémantique repose sur la présence de vecteurs, et jamais sur un horodatage de « dernière indexation ». Un horodatage est une affirmation ; une ligne est une preuve, et c’est toute la différence entre « la recherche sémantique est activée » et « la recherche sémantique fonctionne ».
4. La récupération exécute toujours les deux récupérateurs#
| Récupérateur | Quand il s’exécute | Ce qu’il apporte |
|---|---|---|
Pages mentionnées par le lecteur @ |
Chaque fois qu’elles sont présentes | Placées de force au début de la liste |
| Recherche vectorielle | Chaque fois que l’espace de travail contient des vecteurs et que l’interrupteur du propriétaire est activé | Jusqu’à 3 pages distinctes |
| Recherche en texte intégral PostgreSQL | Toujours, en parallèle de la recherche vectorielle | Au moins 2 emplacements, davantage lorsque la recherche vectorielle en trouve moins |
| Recherche lexicale dans le graphe de documents | Uniquement lorsque les deux méthodes précédentes n’ont rien renvoyé | Jusqu’à 4 pages |
| Boucle de recherche agentique | Uniquement lorsque toutes les méthodes précédentes n’ont rien renvoyé | Jusqu’à 2 pages |
La recherche vectorielle extrait les 6 lignes les plus proches selon la distance cosinus, les convertit en une similarité de 1 − distance, élimine tout élément dont la similarité est inférieure au seuil de 0.25, déduplique par page avant de réduire à 3 résultats (les six correspondances sont souvent six sections d’une même page) et conserve sa position prioritaire dans la liste finale.
La recherche en texte intégral n’est pas une solution de secours ici. Elle s’exécute pour chaque question et ses pages sont fusionnées aux résultats, avec une limite telle que la recherche vectorielle et la recherche lexicale réunies ne dépassent jamais 5 pages. La raison est mesurée sur notre propre index : pour la question "Quel modèle d’URL Docsbook utilise-t-il pour servir mon site de documentation ?", le segment correspondant le mieux à la page correcte était classé 48e sur 1 341 segments selon la similarité cosinus — 18 autres pages obtenaient un score supérieur — tandis que la recherche lexicale le renvoyait en première position, car la page contient littéralement les termes de la requête. Aucune valeur top-k ne corrige cela : le classement lui-même était incorrect pour cette requête. Un résultat vectoriel non vide mais erroné est précisément le problème que cette fusion doit corriger, et une règle du type « exécuter la recherche lexicale uniquement lorsque la recherche vectorielle est vide » ne peut pas le détecter.
Les deux dernières lignes du tableau concernent les corpus qui ne disposent d’aucun index. La boucle agentique fournit au modèle un outil search_docs et lui permet de relancer la requête avec différentes formulations pendant au maximum 4 allers-retours à une température de 0, avant de devoir se décider pour au plus deux chemins de pages — de la même manière que vous utiliseriez grep dans une base de code après l’échec de votre première hypothèse.
5. Les pages sont récupérées et tronquées à partir de la fin#
Chaque page sélectionnée est récupérée depuis votre dépôt, sur sa branche par défaut, puis placée dans le prompt avec son chemin et son titre sur une ligne d’en-tête. Une page de plus de 12 000 caractères n’est pas tronquée au début : les 9 000 premiers caractères et les 3 000 derniers sont conservés, l’omission étant indiquée entre les deux. Les politiques de remboursement, les sections « Connexes » et celles consacrées au dépannage se trouvent à la fin d’une page ; la troncature au début supprime donc précisément la partie qui concerne le plus probablement la question posée. La page actuellement consultée par le lecteur est incluse séparément, avec une limite de 8 000 caractères.
6. Le modèle est contraint avant d’écrire#
Le modèle par défaut du chat de lecture est openai/gpt-4o-mini — une fenêtre de contexte de 128 000 tokens et une limite de sortie de 16 384 tokens, selon la référence des modèles d’OpenAI. Vous pouvez choisir un modèle différent pour chaque projet ; consultez Chat IA.
Le message système est court et vous pouvez le remplacer. Les règles d’ancrage se trouvent dans le bloc d’instructions qui accompagne le contenu, et elles sont spécifiques, car chacune correspond à un échec qui s’est produit :
- Fonder les réponses uniquement sur le contenu fourni. Ne vous appuyez jamais sur les connaissances préentraînées pour définir un terme ou combler une lacune que la documentation ne couvre pas.
- Ne pas affirmer l’absence d’un fait lorsqu’il est présent. Relisez les pages fournies avant de dire qu’un élément manque — notamment lorsque le fait se trouve sur une page qui traite également d’une fonctionnalité payante ou facultative.
- Garder distincts les comportements gratuits et payants. Ne mélangez pas un détail de la page payante avec la description du comportement par défaut.
- Les pages ont été trouvées par recherche et n’ont pas été vérifiées par un humain. Vérifiez chaque page par rapport à l’élément précis demandé, et non par rapport à une simple correspondance de mots. Une page sur les sous-répertoires de langue contient les mots « modèle d’URL » sans répondre à une question sur l’URL par défaut.
- Prêter attention à la question plus restrictive. Si une page répond à une version nuancée de la question (une langue, une formule, un module complémentaire) et que la question ne comportait aucun de ces qualificatifs, cette page répond à une autre question.
- Les questions de configuration nécessitent une phrase exacte. Pour « comment configurer X », trouvez la phrase qui indique un chemin de menu, un bouton ou une étape concrète pour X. S’il n’y en a pas, dites que la documentation ne décrit pas d’intégration X intégrée — une mention de X ailleurs, ou un mécanisme générique qui pourrait théoriquement être relié à X, ne constitue pas une procédure de configuration.
- Les prérequis sont obligatoires et mentionnés deux fois. Parcourez toute la page à la recherche d’une formule, d’un rôle, d’une étape préalable, d’une version ou d’un quota requis — la documentation les place dans une courte ligne en gras en haut de la page, facile à ignorer en passant aux étapes numérotées. Une vérification finale juste avant la génération relit le début de chaque page, car un prérequis mentionné uniquement dans l’introduction d’une page n’est plus mis en concurrence avec quoi que ce soit de local lorsque le modèle est arrivé à la sous-section concernée.
La réponse est demandée au format JSON strict — un corps Markdown et un tableau refs — et diffusée avec une température de 0,3.
7. Les citations sont attachées par le serveur et non considérées comme fiables lorsqu’elles proviennent du modèle#
C’est l’étape qui détermine si une citation signifie réellement quelque chose.
| Ce que fournit le modèle | Ce que fait le serveur |
|---|---|
pagePath |
Conserve la référence uniquement si ce chemin a été cité en ligne dans le propre marqueur [ref:…] de la réponse ou s’il s’agit d’une page que le serveur a effectivement récupérée. Un chemin que le modèle n’a ni lu ni cité est supprimé avant que le lecteur ne le voie. |
pageTitle |
Utilisé comme libellé du lien |
headingText, copié verbatim depuis la page |
Recalcule lui-même l’ancre, avec le même générateur de slugs que celui utilisé par le moteur de rendu |
| (rien) | L’identifiant d’ancre n’est jamais demandé au modèle et n’est jamais accepté de sa part |
La règle des ancres ne relève pas du pinaillage. Une règle de génération de slugs écrite manuellement (« minuscules, espaces remplacés par des tirets, suppression des caractères spéciaux ») ne correspond pas à celle du moteur de rendu pour la simple ponctuation ASCII — Edge cases & errors devient edge-cases--errors sur la page et edge-cases-errors avec une règle fabriquée manuellement — et réduit un titre non latin à une suite de tirets. Un seul composant calcule cette chaîne ; tous les autres la lui demandent.
Que se passe-t-il lorsqu’aucun élément pertinent n’est trouvé#
Rien n’est inventé pour combler le vide. Lorsque tous les récupérateurs reviennent bredouilles, aucune page n’est jointe, aucune ligne Found N results n’apparaît, et l’instruction laissée au modèle est d’indiquer clairement que le contenu fourni ne répond pas à la question.
Le refus est ensuite traité comme une donnée :
- Le texte de la réponse est analysé à la recherche d’un modèle d’absence de réponse ; une correspondance déclenche un webhook
chat.no_answeren plus de l’événementchat.question_askedhabituel. - La question apparaît dans Questions sans réponse, qui est la vue filtrée de toutes les questions de chat enregistrées dont la réponse a échoué à cette vérification.
- Les lecteurs peuvent évaluer négativement une réponse dans le widget ; ces évaluations sont comptabilisées par page dans vos analytics.
Une lacune dans votre documentation vaut davantage comme ligne de rapport que comme paragraphe inventé — c’est le compromis sur lequel repose toute cette page.
Pourquoi c’est la bonne méthode (preuves)#
| Règle dans Docsbook | Pourquoi cela fonctionne | Source |
|---|---|---|
| Répondre à partir des pages récupérées, et non de la mémoire du modèle | Les modèles augmentés par récupération « génèrent un langage plus spécifique, diversifié et factuel qu’une référence seq2seq paramétrique de pointe » | Lewis et al., 2020 — Génération augmentée par récupération pour les tâches de traitement du langage naturel nécessitant des connaissances (NeurIPS) |
| Une citation n’est valide que si elle nomme une page réellement consultée | Mesuré sur quatre moteurs de recherche générative, « seulement 51,5 % des phrases générées sont entièrement étayées par des citations » et « seulement 74,5 % des citations étayent la phrase qui leur est associée » — une citation que le système ne vérifie pas ne constitue pas une preuve | Liu, Zhang & Liang, 2023 — Évaluation de la vérifiabilité dans les moteurs de recherche générative |
| Effectuer une recherche lexicale pour chaque question, et non comme solution de secours | Sur plus de 18 jeux de données de récupération, « BM25 constitue une référence robuste » dans les configurations sans apprentissage, tandis que les récupérateurs denses « sont souvent moins performants… ce qui souligne la marge considérable d’amélioration de leurs capacités de généralisation » — votre corpus est hors domaine pour tout modèle d’embeddings | Thakur et al., 2021 — BEIR |
| Vecteurs de 1 536 dimensions, unités de 6 000 caractères | text-embedding-3-small produit 1 536 dimensions et accepte 8 192 tokens d’entrée ; une unité limitée à 6 000 caractères reste dans cette limite tout en laissant de la place pour le fil d’Ariane |
OpenAI — Guide des embeddings |
| Limiter le prompt à cinq pages, tronquer les pages longues en partant de la fin | Les performances du modèle « sont souvent maximales lorsque les informations pertinentes se trouvent au début ou à la fin du contexte d’entrée, et se dégradent considérablement lorsque les modèles doivent accéder à des informations pertinentes au milieu de contextes longs » — davantage de pages n’implique pas davantage de précision | Liu et al., 2023 — Perdu au milieu |
| Demander explicitement le refus et l’enregistrer | L’ajustement ordinaire par instruction « force le modèle à terminer une phrase, que le modèle connaisse ou non la connaissance » ; le refus doit être demandé | Zhang et al., 2023 — R-Tuning : apprendre aux LLM à dire « Je ne sais pas » (NAACL 2024) |
| L’ancrage réduit les hallucinations, mais ne les élimine pas | L’annotation d’environ 18 000 réponses RAG a montré que, même avec la récupération, « les LLM peuvent toujours présenter des affirmations non étayées ou contradictoires avec les contenus récupérés » | Niu et al., 2024 — RAGTruth |
Ce que nous mesurons — et ce que nous ne publions pas#
Nous ne publions aucun pourcentage de précision pour le chat Docsbook AI. Nous n’avons pas réalisé de benchmark annoté sur les corpus de nos clients, et un chiffre produit sur notre propre documentation ne vous apprendrait rien sur la vôtre. En citer un enfreindrait la règle qui guide la rédaction du reste de cette documentation.
Voici ce qui existe à la place :
| Mesure | Ce qu’elle fait | Où elle apparaît |
|---|---|---|
| Évaluateur des réponses | Un LLM lit la transcription terminée d’une conversation (limitée à 8 000 caractères) avec une température de 0 et renvoie un verdict strict {answered, reasoning} |
La colonne Répondu de l’onglet Chat |
| Enregistré une fois, jamais réévalué | Une transcription ne change pas, son verdict non plus — chacun est écrit une fois, puis relu par la suite | — |
| Limité par requête | Au maximum 6 nouvelles conversations sont évaluées par chargement de page, afin qu’un espace de travail contenant mille fils non évalués ne paie pas mille appels la première fois que quelqu’un ouvre l’onglet | — |
| Détection des réponses absentes | Une recherche de motif dans le texte de la réponse, qui déclenche chat.no_answer et alimente les questions sans réponse |
Webhooks, questions sans réponse |
| Pouces par réponse | Le verdict du lecteur lui-même sur cette réponse, comptabilisé par page | Analyses |
| Étiquette de récupération | Le flux de chaque réponse indique quel récupérateur a produit ses pages — semantic, fulltext, semantic+fulltext, doc_graph, agentic ou mentions |
Le flux de réponse ; vérifiable avec un seul appel HTTP |
Cette dernière ligne est délibérée. « La recherche sémantique est activée » est impossible à réfuter de l’extérieur, ce qui explique précisément comment un index estampillé mais vide a pu être considéré comme fonctionnel pendant des mois. Nommer le récupérateur dans chaque réponse rend cette affirmation vérifiable par n’importe qui, y compris vous.
Docsbook exécute également deux suites internes — un jeu doré de 40 cas qui évalue l’outil auquel le modèle fait appel en premier avec une température de 0, et une suite de scénarios en direct avec des vérifications déterministes ainsi qu’un évaluateur LLM limité. Toutes deux couvrent l’assistant d’administration de votre tableau de bord, et non le chat destiné aux lecteurs, et nous le précisons plutôt que de laisser leurs indicateurs verts être interprétés comme une affirmation de qualité concernant le sujet de cette page.
Limites#
- Aucun chiffre de précision publié. Voir ci-dessus. Considérez tout chiffre de précision unique fourni par un fournisseur — le nôtre compris, si nous venions à en citer un — comme inutilisable tant que son corpus, son jeu de questions et son évaluateur ne sont pas publiés.
- La récupération peut être erronée avec assurance. Le cas classé 48e sur 1 341 ci-dessus est le nôtre, sur notre propre corpus. La fusion avec la récupération lexicale corrige une grande partie de ces cas ; elle ne les élimine pas. La récupération est également la moins fiable précisément là où elle compte le plus : des travaux mesurés montrent qu'elle aide davantage pour les faits moins populaires, lorsque le modèle n'a rien de mémorisé sur lequel s'appuyer (Mallen et al., 2023).
- Le seuil de similarité de 0.25 est une constante fixe, qui n'est pas ajustée pour chaque corpus. Un corpus au vocabulaire inhabituel peut nécessiter un seuil différent, et il n'existe aujourd'hui aucun contrôle par projet pour le modifier.
- Le filtre des citations utilise un OU, et non un ET. Une référence est conservée si le chemin a été récupéré ou si le modèle l'a citée dans le texte. Exiger les deux vidait
refsdans presque toutes les réponses, car les modèles remplissent le tableau et omettent le marqueur. La conséquence est qu'un chemin que le modèle aurait à la fois inventé et cité dans le texte passerait le filtre ; seule la moitié récupérée est étayée par construction. Ce point reste à l'étude jusqu'à ce que la moitié intégrée au texte soit également vérifiée par rapport au corpus. - L'ancrage documentaire ne constitue pas une preuve de fidélité. Le serveur peut garantir qu'une page citée a été lue ; il ne peut pas garantir que chaque phrase de la réponse en découle. C'est ce résidu que mesure RAGTruth, et il est bien réel.
- Le détecteur d'absence de réponse est une correspondance de motifs en anglais. Un refus rédigé dans une autre langue ne sera pas reconnu ;
chat.no_answeret le rapport des questions sans réponse sous-estiment donc les chiffres sur les sites non anglophones. Ce point reste à l'étude jusqu'à la publication d'un remplacement mesuré. - Les pages très longues perdent leur milieu. Une page de plus de 12 000 caractères est transmise au modèle sous forme d'en-tête et de fin, le milieu étant marqué comme omis. Un fait présent uniquement au milieu d'une page très longue peut être manqué. La solution consiste à scinder cette page, ce qui l'améliore également pour les utilisateurs humains.
- Le comportement du modèle dépend de sa version. Le modèle lecteur par défaut, sa fenêtre de contexte et son comportement en cas de refus peuvent être modifiés par le fournisseur. Le mécanisme présenté sur cette page est le nôtre ; le respect de celui-ci par le modèle ne l'est pas.
- La récupération sémantique nécessite des vecteurs. Tant qu'une exécution d'indexation n'est pas terminée, la récupération se rabat sur la recherche plein texte et le graphe documentaire. Il s'agit d'un chat fonctionnel, et non d'un chat défaillant — mais ce n'est pas celui décrit à l'étape 4.
Connexe#
- Chat IA — le contrat : ce que l’assistant peut et ne peut pas faire.
- Recherche — l’index lexical partagé par ce pipeline.
- Sources — ce que l’assistant est autorisé à lire au-delà de vos pages.
- Hooks de chat — bloquer une question ou transmettre au modèle un fait que seuls vos systèmes connaissent.
- Comment Docsbook prouve ce qu’il affirme — la règle selon laquelle cette page est rédigée.