Comment BibGenie compacte le contexte
Comment BibGenie combine compression du contexte, checkpoints structurés et persistance arborescente pour préserver la cohérence, la reprise et la traçabilité des longues conversations de recherche.
Toute conversation de recherche prolongée finit par rencontrer une contrainte incontournable : la fenêtre de contexte d'un modèle est limitée.
Cette limite est particulièrement visible dans Zotero. Une même session peut enchaîner recherche bibliographique, lecture de PDF, extraction de citations, organisation de notes, appels d'outils et corrections successives. À mesure que l'historique s'allonge, le renvoyer intégralement devient plus coûteux, puis finit par dépasser la capacité du modèle. Supprimer simplement les anciens messages n'est pas acceptable : c'est souvent au début de la conversation que figurent l'objectif de recherche, les sources clés, les contraintes et les décisions dont dépend la suite du travail.
La fonctionnalité Context Compaction de BibGenie répond à ce problème. Elle transforme le contexte ancien en un checkpoint de recherche structuré, tout en conservant l'historique complet et une portion récente des échanges dans leur forme originale. Le modèle reçoit ainsi un contexte de travail plus compact et plus dense, sans perdre de vue le travail accompli ni les prochaines étapes.
Cet article présente les choix d'ingénierie qui rendent ce fonctionnement possible.
Pourquoi une requête d'agent ne cesse de grandir
Une interface de chat semble simplement ajouter des messages, mais le modèle ne mémorise pas automatiquement la requête précédente. Chaque requête doit de nouveau contenir le contexte nécessaire. Les appels d'outils, les lectures de PDF et les recherches Zotero l'augmentent jusqu'à ce que le fournisseur refuse la requête parce que la fenêtre de contexte est dépassée.
Il reste alors deux possibilités : commencer une nouvelle conversation sans historique ou transformer le contexte existant en une représentation plus compacte qui permette de poursuivre le travail. Compact choisit la seconde.
Gérer le contexte ne consiste pas à supprimer les messages les plus anciens
Les solutions les plus évidentes consistent à ne garder que les N derniers messages ou à supprimer depuis le début lorsque la limite approche. Pour un agent de recherche, aucune n'est fiable.
D'abord, le nombre de messages n'a pas de relation stable avec le nombre de tokens. Un simple « continue » peut n'en utiliser que quelques-uns, tandis qu'une lecture de PDF ou un résultat d'outil peut en contenir plusieurs milliers. Couper selon le nombre de messages ne renseigne donc pas sur la charge réelle du contexte.
Ensuite, ancien ne signifie pas secondaire. L'objectif de recherche, les critères d'inclusion, les articles imposés, le style bibliographique et les décisions structurantes apparaissent souvent tôt dans la session. Les supprimer peut laisser l'agent capable de comprendre la dernière phrase, mais incapable de se rappeler pourquoi le travail a commencé.
Enfin, une conversation d'agent n'est pas une simple liste de textes. Un processus de recherche complet peut également contenir :
- des appels d'outils et leurs résultats ;
- des clés d'items Zotero, des pièces jointes et des localisateurs ;
- des corrections apportées à des conclusions antérieures ;
- des tentatives infructueuses à ne pas répéter ;
- des tâches inachevées et des hypothèses à vérifier ;
- des contenus multimodaux, notamment des images.
Compact ne peut donc pas se réduire à une troncature. L'opération doit réorganiser l'information de façon contrôlée : éliminer les détails de processus remplaçables tout en préservant l'état nécessaire à la poursuite du travail.
BibGenie définit Compact ainsi :
Transformer l'ancien contexte du modèle en un checkpoint de recherche structuré, tout en conservant l'historique complet de la session et les échanges récents dans leur forme originale.
La distinction est essentielle : c'est le contexte envoyé lors de la prochaine requête qui est compacté, pas l'historique de l'utilisateur.
De l'historique complet à « Checkpoint + Recent Tail »
Imaginons une session de trois tours :
U1 → A1 → U2 → A2 → U3 → A3Après Compact, BibGenie ne supprime ni ne réécrit aucun de ces nœuds. Il ajoute un checkpoint interne C1 à la fin de la session active :
U1 → A1 → U2 → A2 → U3 → A3 → C1
↑
feuille durable de la sessionC1 contient le résumé du contexte antérieur. Son champ firstKeptMessageId désigne le premier message qui doit rester intégral. Si cette frontière est U3, la prochaine requête adressée au modèle contient :
C1.summary → U3 → A3Après une nouvelle question, le contexte devient :
C1.summary → U3 → A3 → U4Deux vues compatibles coexistent alors :
- Historique durable : la base et l'interface conservent toute la chaîne
U1 → A1 → … → C1 → U4. - Projection du modèle : le modèle ne reçoit que le checkpoint le plus récent, la fin récente conservée mot pour mot et les nouveaux messages postérieurs au checkpoint.
L'enjeu n'est donc pas simplement de raccourcir une chaîne de caractères, mais de séparer un historique complet et vérifiable d'une mémoire de travail dense pour le modèle.
Quand Compact se déclenche
BibGenie propose trois points d'entrée qui partagent la même résolution du modèle, la même estimation de capacité et les mêmes règles de seuil.
1. Déclenchement manuel
L'utilisateur peut sélectionner Compact lorsqu'une phase de recherche est terminée et qu'il souhaite structurer le contexte avant de poursuivre.
Le déclenchement manuel n'est pas limité par le seuil automatique. Il correspond à une demande explicite de créer un checkpoint immédiatement :
- Avant le premier checkpoint, une session courte peut être compactée dès qu'elle compte au moins deux tours : le premier est résumé, le second reste intégral.
- Si un checkpoint existe déjà et que de nouveaux messages le suivent, un checkpoint actualisé peut reprendre le résumé précédent même si la frontière de conservation ne doit pas avancer. Si elle avance, l'historique nouvellement exclu est intégré au résumé.
- Si la session ne contient qu'un tour impossible à compacter, ou si le checkpoint le plus récent est déjà la feuille de la branche, l'opération devient un no-op réussi plutôt qu'une erreur inutile.
L'utilisateur peut ainsi marquer des étapes de recherche pertinentes sans que l'absence de contenu compressible soit présentée comme un échec.
2. Vérification automatique après un tour terminé
Une fois la réponse finale de l'assistant correctement persistée, BibGenie mesure l'occupation du contexte. Si elle approche de la limite de sécurité, Compact démarre de manière proactive.
Ce déplacement du travail hors du prochain envoi évite généralement à l'utilisateur d'attendre la génération d'un résumé avant de poser sa question suivante.
La vérification ne s'exécute que lorsque la session est stable. Si un appel d'outil, un résultat ou une approbation utilisateur est encore en attente, Compact est ignoré afin de ne jamais figer un workflow incomplet dans un checkpoint.
3. Preflight avant l'envoi
La vérification après chaque tour améliore la latence, mais le preflight avant envoi constitue la dernière garantie de correction.
Avant qu'un nouveau message utilisateur n'entre dans l'état de l'AI SDK, BibGenie l'ajoute temporairement à la projection et estime la prochaine requête. Le système peut ainsi détecter un long texte collé, une image ajoutée ou le passage à un modèle doté d'une fenêtre plus petite.
Si la requête reste trop volumineuse après Compact, BibGenie n'envoie pas au fournisseur une requête vouée à l'échec. Le brouillon est conservé et l'utilisateur est invité à le raccourcir.
Décider selon la capacité du modèle, pas selon le nombre de messages
Les modèles diffèrent par leur fenêtre de contexte et leur longueur maximale de sortie. BibGenie n'utilise donc pas un seuil global unique.
La relation fondamentale est la suivante :
Limite d'entrée sûre = Fenêtre de contexte - Tokens réservésLa réserve laisse de la place à la prochaine réponse. Elle est calculée à partir de la fenêtre du modèle actif : un grand modèle peut réserver une sortie plus confortable, tandis qu'un petit modèle réduit cette réserve au lieu d'hériter d'une constante globale inadaptée.
Le budget du Recent Tail évolue lui aussi avec la capacité du modèle. Compact n'aplatit donc pas toute la conversation récente pour économiser des tokens, mais ne conserve pas non plus une fin de conversation qui ne pourrait pas entrer dans un modèle plus petit.
La frontière est toujours placée au début d'un tour utilisateur complet ; elle ne coupe jamais une réponse de l'assistant ou un résultat d'outil. Si un seul tour assistant/outil dépasse déjà le budget, BibGenie choisit la frontière utilisateur la plus proche après ce tour, plutôt que de conserver ce bloc surdimensionné en recherchant un message plus ancien.
Privilégier l'usage réel du fournisseur
Un tokenizer exact pour chaque fournisseur ajouterait une forte complexité, alors que les fournisseurs ne calculent pas tous le contexte et la facturation de la même façon. BibGenie utilise donc les données réelles lorsqu'elles existent et n'estime que le complément :
- Repérer, après le dernier checkpoint, le message assistant le plus récent doté d'un usage valide.
- Utiliser le nombre de tokens communiqué par le fournisseur comme base.
- Estimer les messages ajoutés depuis cette requête et qui ne figurent pas encore dans cet usage.
- En l'absence d'usage fiable, estimer toute la projection actuelle.
Le résultat représente le contexte susceptible d'être transmis lors de la prochaine requête, et non la consommation cumulée de l'utilisateur. Le totalUsage de facturation n'est pas assimilé à l'occupation du contexte.
Le texte utilise une approximation prudente par caractères. Le reasoning est compté lorsqu'un fournisseur peut le rejouer. Les images reçoivent un coût fixe lors du preflight afin qu'un message multimodal ne soit pas réduit à un nom de fichier. Dans le plugin actuel, les parts file côté utilisateur proviennent principalement d'images collées et de captures Zotero.
L'estimation ne prétend pas à une précision artificielle. Elle répond de façon stable à une question opérationnelle : la prochaine requête reste-t-elle dans une zone sûre ?
Le résumé est un instantané de l'état de l'agent, pas un compte rendu
Un résumé conversationnel classique décrit ce qui s'est passé. Un checkpoint d'agent doit également contenir l'état nécessaire pour reprendre le travail.
BibGenie impose donc une structure fixe :
- Research Goal : objectif de recherche actuel ;
- User Requirements and Constraints : exigences, préférences et limites ;
- Research Progress : travaux terminés, en cours ou bloqués ;
- Findings and Evidence : résultats et éléments probants ;
- Key Zotero Resources : items, pièces jointes et clés Zotero essentiels ;
- Decisions : choix déjà arrêtés ;
- Next Steps : prochaines actions concrètes ;
- Critical Context : toute autre information indispensable à la reprise.
Le prompt demande également de distinguer les déclarations de l'utilisateur, les faits produits par les outils et les inférences du modèle. Une hypothèse provisoire risque ainsi moins de devenir un fait établi après Compact.
Sérialiser le contexte de recherche
Avant de générer le résumé, BibGenie convertit les UIMessage en une représentation textuelle compacte adaptée à la recherche :
- le texte ordinaire conserve son contenu et son rôle ;
- le reasoning n'entre pas dans le checkpoint à long terme ;
- les entrées d'outils sont conservées, tandis que les résultats trop longs sont tronqués ;
- les erreurs et refus sont explicitement signalés ;
- les images et pièces jointes conservent nom de fichier et type MIME ;
- les données Zotero gardent les champs nécessaires à la reprise.
Les informations retenues dépendent du type de ressource Zotero :
- références bibliographiques : item key, titre et texte de citation ;
- pages PDF : nom de la pièce jointe, page courante et nombre total de pages ;
- EPUB : index de section, href et CFI ;
- annotations : annotation key, texte, commentaire, page et parent item key ;
- collections et tags : identifiants stables et libellés.
Les objets sources volumineux ne sont donc pas intégralement envoyés à chaque résumé, tandis que les localisateurs nécessaires aux appels d'outils suivants restent disponibles.
Éviter l'empilement des checkpoints
Une longue session peut être compactée plusieurs fois. BibGenie n'envoie jamais tous les anciens checkpoints au modèle : seul le plus récent est projeté.
Lors d'un nouveau Compact, le système combine :
résumé précédent + nouveaux messages devenus ancienspour créer un nouveau résumé :
Résumé 1 + nouvel historique → Résumé 2
Résumé 2 + nouvel historique → Résumé 3Le contexte ne croît donc pas linéairement avec le nombre de checkpoints.
La frontière est aussi monotone : la nouvelle limite de conservation ne peut pas reculer avant celle du checkpoint précédent. Un historique déjà remplacé par un résumé n'est jamais redéployé dans le Recent Tail.
Les déclenchements manuel et automatique diffèrent volontairement :
- Compact automatique ne s'exécute que si la frontière peut avancer et libérer du contexte supplémentaire.
- Compact manuel peut réutiliser la frontière lorsque de nouveaux messages suivent un checkpoint et produire un résumé actualisé à partir du précédent. Si la frontière avance, le nouvel historique exclu est lui aussi intégré.
Cette distinction concentre l'automatisation sur le gain de capacité, tout en laissant à l'utilisateur la possibilité de marquer une nouvelle phase de recherche.
Le budget de sortie du résumé provient de la réserve et reste plafonné par la sortie maximale du modèle. Il s'agit d'une limite de sécurité pour les recherches complexes ; le prompt exige malgré tout une rédaction concise.
Pourquoi Compact doit comprendre l'arbre de session
Les sessions BibGenie ne sont pas de simples tableaux : elles forment des arbres de messages susceptibles de se ramifier.
L'utilisateur peut relancer une réponse, modifier son dernier message ou créer un fork depuis une ancienne réponse de l'assistant. Plusieurs sessions peuvent partager les premiers nœuds, tandis que chacune désigne sa branche active par sa propre feuille durable.
Compact ne doit donc ni réécrire les anciens nœuds ni recopier le Recent Tail après le checkpoint. Dans le cas contraire :
- la compression d'une branche pourrait affecter les autres ;
- les relations parent des nœuds partagés pourraient changer ;
- Retry pourrait hériter d'un checkpoint devenu invalide ;
- des messages récents seraient enregistrés plusieurs fois ;
- l'historique visible et le contexte réellement envoyé pourraient diverger.
BibGenie utilise un checkpoint append-only :
C1.parentId = A3 indique où et quand le checkpoint a été ajouté dans l'arbre. C1.firstKeptMessageId = U3 indique où reprend la projection verbatim du modèle. Ces deux dimensions sont distinctes et ne peuvent se remplacer.
Un fork créé depuis A2 n'hérite pas de C1. Un fork créé depuis un message assistant stable situé après C1 contient naturellement le checkpoint dans sa chaîne d'ancêtres. Aucun nœud partagé n'a besoin d'être copié ou modifié.
Traiter le checkpoint comme un commit d'état sûr en concurrence
La génération du résumé peut prendre plusieurs secondes. Si la branche est modifiée ou relancée pendant cet intervalle, un résumé fondé sur l'ancien historique ne doit pas être validé.
BibGenie considère Compact comme un commit d'état conditionné par une version. Deux valeurs sont relevées au départ :
leafId: extrémité actuelle de la branche durable ;branchRevision: version de branche incrémentée uniquement lorsque le contenu durable change réellement.
Une fois le résumé généré, une transaction dédiée compare ces deux valeurs, confirme la stabilité du workflow d'outils et vérifie que la frontière appartient toujours à la branche active. Ce n'est qu'alors qu'elle ajoute le checkpoint, déplace la feuille de session et incrémente la révision. Toute divergence rend le résumé obsolète et entraîne son rejet.
Si la branche change pendant la génération, BibGenie recharge son état durable réel au lieu d'imposer un checkpoint obsolète. Une annulation avant la fin de la transaction provoque son rollback. Après un commit réussi, l'état mémoire est synchronisé avec le checkpoint validé afin que la base et l'interface convergent vers la même branche.
Cohérence avec Retry, Edit, Fork et les actions existantes
Une compression fiable doit préserver la sémantique des opérations existantes, et pas seulement réussir à produire un résumé.
Retry
Un checkpoint est un message interne. Retry cible la dernière véritable réponse assistant. Si un checkpoint suit le tour relancé, il est invalidé avec l'ancienne fin de branche ; la nouvelle réponse repasse ensuite par les contrôles de capacité normaux.
Edit
Lors de la modification du dernier véritable message utilisateur, la réponse assistant suivante et les checkpoints ultérieurs quittent la branche active. Le nouvel envoi passe à nouveau par le preflight.
Fork
Un fork ne peut cibler qu'un message assistant conversationnel stable, jamais un checkpoint interne. L'héritage d'un checkpoint dépend uniquement de la chaîne d'ancêtres du nœud cible.
Protection des historiques endommagés
Au chargement, BibGenie vérifie les parents manquants, les cycles et les messages durables invalides. Si la topologie est corrompue, l'interface n'affiche que la portion lisible en sécurité et rend la session accessible en lecture seule. La base d'origine n'est jamais réécrite silencieusement lors du chargement ou de Compact.
Expérience utilisateur pendant Compact
La compression du contexte relève de l'infrastructure, mais elle ne doit pas ressembler à un blocage inexpliqué de l'interface.
Lorsqu'un Compact manuel ou automatique commence, le chat affiche Compacting earlier context… et permet l'annulation. L'éditeur reste disponible afin de préparer la question suivante.
Ce n'est qu'au moment où l'utilisateur envoie explicitement cette question que son contenu est figé dans l'attente du Compact en cours. Une fois l'opération terminée, BibGenie poursuit automatiquement. En cas d'échec ou d'annulation, aucun message n'est envoyé à l'insu de l'utilisateur et le brouillon reste intact.
Retry, Edit, Fork, le changement de modèle et un second Compact sont temporairement désactivés, car ces actions modifieraient la branche utilisée par le résumé. La simple édition du champ de saisie n'altère pas l'historique durable et ne doit donc pas être bloquée prématurément.
Pour l'utilisateur, le résultat est concret :
- une longue recherche ne s'interrompt pas brutalement lorsque le contexte grandit ;
- il n'est pas nécessaire de recréer une conversation et d'expliquer à nouveau le contexte ;
- le passage à un modèle plus petit déclenche une nouvelle évaluation avant l'appel ;
- sources clés, clés Zotero, conclusions et tâches ouvertes sont préservées ;
- les échanges récents restent intacts et conservent références locales et tonalité ;
- après redémarrage du plugin, le checkpoint appartient toujours à la bonne branche ;
- l'historique complet antérieur à Compact reste consultable.
La compaction a un coût : le cache de prompt repart de zéro
Un contexte plus court ne rend pas nécessairement la première requête suivant la compaction moins chère. La compaction remplace une partie du préfixe par un résumé ; cette première requête doit donc être recalculée, puis un nouveau cache peut être établi autour du préfixe compacté.
L'objectif n'est pas d'obtenir le prompt le plus court, mais d'équilibrer capacité du contexte, informations nécessaires, réutilisation du cache, latence et coût.
Choix de conception : la vérifiabilité plutôt qu'une fausse précision
L'implémentation de BibGenie reprend des principes éprouvés de compaction d'agents et les adapte à Zotero, aux entrées multimodales et à une persistance arborescente. Elle évite volontairement de complexifier le système sans bénéfice clair :
- pas de tokenizer prétendument universel et exact pour tous les fournisseurs ;
- pas de suppression physique ni de modification des parents des anciens messages ;
- pas de duplication du Recent Tail ;
- pas de Compact automatique suivi d'une répétition après un overflow du fournisseur ;
- pas de création ou de modification de checkpoints par la persistance ordinaire ;
- pas de confusion entre tokens cumulés de facturation et occupation du contexte.
Ces choix rendent les propriétés essentielles plus faciles à vérifier : moment du déclenchement, branche résumée, messages projetés, données validées en base et état obtenu après un échec.
Compact reste, par nature, une compression avec perte. Son objectif n'est pas de faire retenir chaque token au modèle, mais de préserver la continuité de la tâche dans une fenêtre finie. L'historique complet assure la traçabilité, le checkpoint conserve l'état de travail et le Recent Tail maintient les détails locaux.
Du chatbot au partenaire de recherche durable
Un système conversationnel classique se demande surtout : « Comment répondre à ce tour ? » Un agent de recherche doit aussi répondre à une autre question : « Quel état dois-je emporter dans le prochain tour ? »
La Context Compaction de BibGenie ne se limite pas à un appel de résumé. Elle associe preflight de capacité, sérialisation du contexte de recherche, checkpoints structurés, projection d'une session arborescente, contrôle de version concurrent, persistance transactionnelle et comportement cohérent avec Retry, Edit et Fork.
Lorsque la recherche s'étend sur des dizaines de tours, plusieurs articles et de nombreux appels d'outils, retenir chaque token compte moins que savoir durablement :
- ce que l'utilisateur cherche finalement à accomplir ;
- quelles affirmations sont déjà étayées ;
- quelles conclusions restent hypothétiques ;
- quel travail est terminé ;
- quelle doit être la prochaine étape.
C'est ce que Compact apporte à BibGenie : la capacité de faire tenir, dans une fenêtre de contexte finie, une session d'agent qui progresse dans le temps, se reprend de manière fiable et conserve le fil de la recherche.