
Cet article décrit l'implémentation technique du Q&R sans hallucination dans notre lecteur IA : les réponses s'appuient strictement sur le texte du livre ouvert, et les affirmations clés peuvent être retrouvées en un clic jusqu'au passage exact. Si vous développez la lecture IA, le Q&A documentaire ou des applications de type RAG, nous espérons que trois itérations et l'architecture finale vous seront utiles.
I. Évolution en trois étapes
Le Q&R sans hallucination n'a pas été conçu parfaitement dès le départ. Il a évolué sous la tension entre coût, latence et précision. Voici les trois étapes dans l'ordre chronologique—pour comprendre pourquoi l'architecture actuelle a cette forme.
Étape 1 : Injecter tout le livre dans le contexte (le plus simple—et le premier à craquer)
Approche : Quand l'utilisateur ouvre un livre et pose une question, placer tout le corps de texte extrait dans le system prompt ou le message utilisateur, puis laisser le modèle de dialogue répondre. Si le livre dépasse environ 400 000 caractères, troncature brutale—seul le début est conservé ; les chapitres suivants sont invisibles pour le modèle.
Avantages :
- Coût d'implémentation très faible, presque pas de prétraitement ;
- Résultats corrects sur les livres courts et documents simples—le modèle a vraiment « vu tout le livre » ;
- UX simple : poser une question, obtenir une réponse, sans état « veuillez patienter pendant l'analyse ».
Inconvénients (rapidement inacceptables) :
- Réponses lentes : Chaque question renvoie une charge énorme ; le délai jusqu'au premier token et la latence totale augmentent avec la longueur du livre ;
- Coût token élevé : Vous payez l'intégralité du livre en entrée à chaque question ;
- Longs ouvrages fortement déformés : Au-delà de 400k caractères, la seconde moitié, les annexes et les conclusions n'existent pratiquement plus—et l'UI n'indique souvent pas clairement la troncature ;
- Granularité de recherche nulle : Le modèle doit « trouver une aiguille dans une botte de foin » sur des centaines de milliers de caractères—risque de manquer des détails et de produire des résumés plausibles sans fondement—exactement ce qu'il faut éviter en lecture.
L'étape 1 convient à un MVP, pas à une solution produit.
Étape 2 : Un LLM léger extrait des phrases clés (compresser le contexte—trop agressivement)
Approche : Avant le Q&R (ou à la première ouverture), faire tourner un modèle moins cher sur le corps : découpage par chapitre spine (ou par blocs), extraction de phrases clés, conservation des tags de position comme [fFichier-début-fin], puis concaténation en un contexte plus court pour le Q&R ultérieur.
Pipeline typique : Extract → Cache → Chat. Extraire une fois (hors ligne ou à la demande), stocker un « paquet de phrases clés », le réutiliser à chaque question—comme beaucoup de prototypes document Q&A : compresser d'abord, répondre ensuite.
Avantages :
- Chaque question envoie beaucoup moins de texte ; la consommation de tokens par requête baisse par rapport à l'étape 1 ;
- Le prétraitement peut être mis en cache ; pas de ré-extraction par question sur le même livre ;
- Les tags de position posent les bases des citations.
Inconvénients (encore insuffisant sur les longs ouvrages) :
- Perte importante de détails : Les « phrases clés » sont choisies par le modèle ; qualificateurs, contre-exemples et chaînes d'argumentation disparaissent souvent—réponses « correctes mais unilatérales » ;
- Contexte encore volumineux sur les gros ouvrages : Même les paquets de phrases clés restent conséquents—latence et coût atténués, pas résolus ;
- Double erreur LLM : L'extraction peut omettre ; le Q&R peut mal lire les extraits—les erreurs s'accumulent ;
- Contexte statique : Que la question porte sur un chapitre ou la structure globale, le modèle reçoit toujours le même blob pré-extrait—pas de rétrécissement dynamique selon la question.
La leçon : le problème n'est pas « de compresser ou non », mais « si la compression est à la demande et si l'on peut revenir au texte source ».
Étape 3 : Index de segments + Tool à la demande + retour du texte source (actuel)
Approche : Inspiré de PageIndex. Par rapport à l'étape 2, trois changements majeurs :
- Le prétraitement produit un index structuré (résumés au niveau TOC + spans de caractères exacts), pas des extraits utilisés directement comme contexte Q&R ;
- Chaque question utilise le Tool Calling pour chercher à la demande, puis récupère le texte source avec tags de position pour répondre ;
- System prompt + frontend imposent le format de citation et permettent clic → saut → surlignage dans le lecteur.
Comparaison des trois étapes :
| Dimension | Étape 1 (texte intégral) | Étape 2 (phrases clés) | Étape 3 (actuel) |
|---|---|---|---|
| Contexte par question | Livre entier (ou première moitié tronquée) | Phrases clés pré-extraites | Uniquement extraits de source pertinents |
| Précision sur longs ouvrages | Effondrement au-delà de ~400k | Dépend de l'extraction ; perte de détail | Recherche par TOC/span ; pas de troncature brutale du livre entier |
| Vitesse de réponse | Lente | Un peu mieux ; longs ouvrages encore lents | Recherche + contexte court—nettement plus rapide |
| Coût token | Très élevé | Moyen-élevé | Prétraitement amorti + paiement à la demande |
| Traçabilité | Faible (citations difficiles) | Tags présents mais contenu filtré | Notes de bas de page → vrais spans source |
| Complexité technique | Faible | Moyenne | Élevée |
Pourquoi nous nous sommes arrêtés à l'étape 3 : En lecture, zéro hallucination ne signifie pas « montrer au modèle le plus de texte possible », mais « avant de répondre, obtenir des preuves source pour la question ». Les étapes 1–2 luttaient sur la taille du contexte ; l'étape 3 découpe le pipeline en index (prétraitement) → recherche (Tool) → preuve (source) → réponse (génération contrainte)—équilibre précision, coût et traçabilité.
Ci-dessous le détail de l'étape 3.
II. Définition du problème : En Q&R livre, l'hallucination coûte plus cher que dans un chat générique
Les utilisateurs tolèrent parfois des erreurs dans un chatbot général. En Q&R livre, le prix est plus élevé :
- Ils demandent ce que ce livre dit—not ce qui vit dans la mémoire paramétrique du modèle ;
- Une « opinion du livre » plausible peut induire en erreur notes, citations et partages ;
- Sans sources, pas de vérification—la confiance est difficile à établir.
« Zéro hallucination » devient donc trois règles applicables :
- Les questions livre doivent d'abord interroger le livre : Tout ce qui peut concerner le livre ouvert passe par la recherche (Tool) avant la réponse ;
- Les réponses doivent être traçables : Les affirmations clés portent des tags de position que l'UI peut parser et atteindre ;
- Dire quand on ne trouve pas : Si le livre ne contient pas l'information, le dire—ne pas habiller des connaissances générales en « ce que dit le livre ».
La suite suit le flux de données de l'étape 3 et la mise en œuvre de ces règles.
III. Architecture : Prétraitement → Tool → Génération contrainte → Citations cliquables
Idée centrale : ne pas laisser le modèle « répondre de mémoire »—l'obliger à « rassembler des preuves, répondre, marquer les sources ».
IV. Prétraitement : Transformer le livre en index de segments consultable
Si chaque question utilisait encore le contexte étape 1 du livre entier, les longs ouvrages explosent le budget token et la recherche est trop grossière. Étape 3 : au premier chat IA sur un livre, lancer en arrière-plan un job de résumé de segments—découpage par TOC ou longueur de texte en Segments, résumé de chacun, persistance en IndexedDB locale.
Chaque Segment contient le résumé plus la position physique dans le corps :
| Champ | Signification |
|---|---|
startFileIndex / endFileIndex | Index de fichier spine (PDF : un fichier par page) |
startOffset / endOffset | Début/fin en caractères |
sequence | Ordre de lecture linéaire |
title | Titre TOC |
Le découpage équilibre précision et coût : nœud TOC sous ~20 Ko → résumer ce nœud seul ; nœuds frères fusionnés en lots (15–20 Ko) avant appel LLM ; blocs longs non structurés en plages ~30–40k caractères.
Le system prompt de résumé exige de conserver les tags de position inline ([fNombre-Nombre-Nombre]) pour que la source récupérée par Tool s'aligne sur les offsets spine. Contrainte centrale :
If summary content relates to a passage, keep the trailing position tag [fNumber-Number-Number] (e.g. [f1-90-109]).
Tags are atomic—do not alter, merge, or omit any character or digit.
Après prétraitement, le Q&R dépend d'un index de segments structuré, pas du contexte livre entier—prérequis technique du zéro hallucination sur longs ouvrages.
V. Système de tags de position : Encoder le « d'où » dans le texte
Le zéro hallucination exige du contenu source et une provenance analysable par machine et atteignable dans l'UI. Nous utilisons des tags inline :
[f{fileIndex}-{startChar}-{endChar}]
Exemple : [f5-123-165] = fichier spine 5 (base 0), caractères 123–165.
5.1 Comment les tags sont écrits dans le corps
La couche d'extraction ajoute [f{fileIndex}-{start}-{end}] en fin de segment :
const position = `[f${fileIndex}-${absOffset}-${absOffset + segment.length}]`;
fileLines.push(segment.text.trim() + position);
Résumés de prétraitement ou extraits Tool : les positions s'alignent sur les offsets caractères spine—pas des numéros de page estimés par le modèle.
5.2 Contraintes sur la sortie du modèle
Le system prompt inclut Position Citation Rules—cinq points essentiels :
- Format standard : Doit utiliser
[f_fileIndex-startChar-endChar]; les trois parties numériques obligatoires ; - Copier uniquement depuis les sources actuelles : Notes verbatim des messages system/user ou retours Tool de ce tour ;
- Pas de fabrication : Ne pas calculer, modifier ou inventer des positions ;
- Préférer l'omission : Pas de tag valide dans le contexte → répondre normalement—ne pas émettre de tags de position ;
- Inline avec les affirmations : Tags après la phrase concernée ; pas de listes de citations en fin de réponse.
L'UI filtre aussi les tags bipartites invalides occasionnels (ex. [f1-293]) avant rendu.

VI. Tool Calling : D'abord chercher, ensuite répondre
Quand le chat est lié à un livre (resourceId présent, chatType === 'chat'), nous enregistrons deux Tools avec executors avant chaque génération—boucle function calling compatible OpenAI.
6.1 get_related_segment_summaries — Recherche ciblée de segments
Pour : concepts, personnages, intrigue, détails de chapitre—intention de recherche claire.
Flux :
- Le modèle reformule la question en termes susceptibles d'apparaître dans le livre (« Optimize Search Queries » dans le system prompt) ;
- Appel Tool avec
question; - Grouper toutes les résumés de segments par budget token (~30k tokens par lot, max 5 lots) ;
- Par lot : requête LLM séparée choisit les ID pertinents (max 5) dans
{ id, title, summary }, JSON du type{"Thinking":"...","answer":["1","3"]}; - Pour les segments choisis, tirer le texte source tagué du spine—not les résumés—comme résultat Tool.
Design clé : le Tool renvoie la source, pas les résumés. Le modèle répond à partir de vrais paragraphes avec [f…] inline, évitant la dérive « résumé → re-résumé ».
6.2 get_full_book_segment_summaries — Vue d'ensemble du livre
Pour : « résumer le livre », « critiquer ce livre », « structure/thèmes globaux »—vue globale.
Concaténer tous les champs summary des segments dans l'ordre de lecture—éviter de manquer des chapitres clés par pertinence par morceau seule.
6.3 System prompt : Livre d'abord, outils d'abord
Avec un livre lié, s'applique Core Principles for Reading Assistant :
1. Book First, Tool First
- Any question possibly about the book must call tools first;
- Answers must rely mainly on retrieval—never invent “book content” without retrieval.
2. General Knowledge as Fallback Only
- Only for: casual chat / user explicitly skips the book / tools return nothing;
- If the book lacks it, say “not mentioned in this book” before general knowledge.
3. Direct Style
- Get to the point—avoid “based on the provided materials…” and similar filler.
La génération exécute la boucle Tool : tool_calls → exécuter → ajouter role: tool → continuer jusqu'au texte final. Avec tools activés, le canal thinking est coupé pour éviter les conflits de protocole.
VII. Traçabilité frontend : De la note de bas de page au surlignage
La sortie [f5-123-165] du modèle n'est pas affichée brute ; la couche de rendu en fait des citations cliquables.
7.1 Rendu des notes
Normaliser les tags en liens Markdown comme [1]([f5-123-165]), afficher en notes numérotées ; dédupliquer la même position.
7.2 Interaction au clic
- Premier clic : Parser
[f…]→ fileIndex + offsets → extraire texte spine → aperçu (titre TOC optionnel) ; - Même note à nouveau : Fermer l'aperçu ;
- Confirmer le saut : Ouvrir la vue lecture, surligner la plage de caractères.
Du tag copié du modèle au texte source visible par l'utilisateur, la chaîne ne repasse jamais par un autre appel LLM—déterministe et reproductible.
VIII. Cas limites et dégradation honnête
Zéro hallucination ≠ « toujours une réponse »—c'est pas de preuve, pas d'invention :
| Scénario | Comportement |
|---|---|
| Résumés de segments pas prêts | Extraire d'abord le texte intégral et résumer |
| Tool ne trouve rien | Retourner (No relevant segment excerpts found…) ; le modèle doit dire « pas dans le livre » |
| Tags bipartites invalides du modèle | Filtrage frontend ; pas de notes cassées |
| Discussion informelle | Le system prompt autorise les connaissances générales hors livre |
| Exporter le chat | Les notes peuvent devenir des deep links lecteur pour partage/archivage |

IX. Compromis de conception : Pourquoi pas le « RAG vectoriel » ?
Les pairs en Q&A documentaire demandent souvent : si vous faites de la génération augmentée par recherche, pourquoi pas Embedding + base vectorielle Top-K ?
Nous faisons du RAG—chercher avant de générer. La différence : « RAG » dans le discours commun implique souvent la similarité vectorielle ; notre étape 3 est index de segments + Tool avec source à la demande—pas de couche vectorielle par choix. Ci-dessous : raisons architecturales, sans nier la valeur du RAG vectoriel.
Périmètre : pas « pas de recherche », mais « pas de recherche vectorielle »
- RAG au sens large : chercher → générer → nous le faisons ;
- RAG vectoriel : rappel par similarité d'embedding → pas dans cette version.
Le prétraitement construit un index de résumés de segments ; le modèle choisit des segments via Tools et reçoit le texte source. La recherche existe sans modèle d'embedding séparé ni maintenance d'index vectoriel.
Raison 1 : Fournisseurs LLM personnalisés—surface d'intégration réduite
Les utilisateurs peuvent brancher leurs propres clés API, des base URL personnalisées ou Ollama local—le modèle de chat est leur choix ; coût et chemin de données restent maîtrisés.
Le RAG vectoriel typique élargit l'intégration :
- Outre le modèle de chat, il faut en général un modèle d'embedding (autre nom, parfois autre endpoint) ;
- Ollama local nécessite un modèle d'embedding séparé plus compatibilité dimension/API ;
- Plus de modes de défaillance : chat OK mais recherche vide—embedding, index ou dimension ; debug plus difficile qu'un seul fournisseur de bout en bout.
Ici, choix de segments et réponse partagent une config fournisseur—pas de « chat sur A, index sur B ». Pour des apps LLM branchables, cela compte souvent plus que quelques points de rappel.

Raison 2 : Les embeddings lient l'index—changer de fournisseur coûte cher
En RAG vectoriel, les vecteurs ne sont pas un format intermédiaire universel—ce sont des coordonnées sous un modèle d'embedding. Index avec A, requête avec B : la similarité est en général incomparable—souvent ré-embedding complet, et les dimensions (768 / 1024 / 1536 …) verrouillent le schéma de stockage.
L'étape 3 persiste résumés structurés + spans de caractères, pas de vecteurs ; changer de modèle de chat ne reconstruit pas l'index ; la chaîne de preuve (positions source) reste—aligné avec « tester différents LLM à tout moment ».
Raison 3 : Le routage structuré suffit souvent pour les longs documents avec TOC
E-books et PDF ont en général une structure de chapitres ; le prétraitement fournit titres de segment + résumés. Pour « que dit le chapitre X » ou « comment le livre définit Y », choisir des segments dans le catalogue puis tirer la source fonctionne bien en pratique ; le Tool renvoie la source avec [f…], le zéro hallucination reste ancré sur les spans de caractères.
Les vecteurs aident pour la sémantique floue, le multilingue, les correspondances littérales longues ; pour des lecteurs TOC + prétraitement + forte traçabilité, investir dans Tool + retour source + règles de citation a souvent un meilleur ROI.
Avenir : Rappel hybride, pas une refonte
Nous pourrions ajouter un rappel vectoriel grossier (embedding uniquement pour Top-N chapitres candidats), en terminant toujours par choix de segment → source → trace cliquable—règles zéro hallucination inchangées. Si ajouté : embedding optionnel, invites explicites de ré-indexation au changement de modèle—éviter un mauvais rappel silencieux.
D'ici là : toute API chat compatible OpenAI fonctionne ; changer de modèle de chat ne reconstruit pas l'index local.
X. Synthèse
| Étape | Méthode | Rôle |
|---|---|---|
| Prétraitement | Découpage TOC/longueur + cache de segments | Longs ouvrages consultables et localisables |
| Tags de position | [fFichier-début-fin] dans la source | Provenance analysable par machine |
| Tool | Segments / résumés livre entier par question, retour source | Forcer les preuves avant réponse |
| System prompt | Livre d'abord, pas de faux tags, dire quand absent | Contraindre la génération |
| Frontend | Note → aperçu → saut et surlignage | L'utilisateur vérifie les preuves |
| Pas de recherche vectorielle | Un fournisseur ; changer de modèle chat sans ré-index | Coût d'intégration et migration réduit |
« Zéro hallucination » ne signifie pas que le modèle ne se trompe jamais—c'est que l'ingénierie verrouille la sortie sur une chaîne de preuves : pas de recherche → ne pas feindre du contenu livre ; avec recherche → positions source vérifiables.
Si vous développez la lecture IA ou le Q&A documentaire, nous espérons que le chemin texte intégral → phrases clés → Tool-first à la demande, plus tags de position inline + retour source, soit une implémentation de référence utile.
Ce sont des retours d'expérience du lecteur IA Foxycape—à titre indicatif uniquement. Essayez le lecteur sur la page de téléchargement.
