Comment Stalker Chat Export récupère une conversation
Ce que ChatGPT nous envoie réellement.
Dans le premier article, nous avons raconté pourquoi nous avons construit Stalker Chat Export V4.
Cette fois, nous allons regarder ce qui se passe réellement lorsque l’on clique sur DOWNLOAD.
Il n’y a pas de défilement de la conversation.
Pas de reconstruction du contenu à partir de milliers d’éléments HTML.
V4 va chercher directement les données dont elle a besoin.
La première question : quelle conversation sommes-nous en train d’exporter ?
Lorsque l’extension s’exécute sur une conversation ChatGPT, elle doit d’abord identifier cette conversation.
L’information est déjà présente dans l’environnement de la page.
Le premier élément dont nous avons besoin est donc simplement l’identifiant de la conversation.
Firefox
│
├── conversation ID
│
└── session access token
│
▼
API requestL’identifiant permet de savoir quelle conversation demander.
Le token permet à la requête d’être effectuée dans le contexte de la session ChatGPT déjà ouverte dans Firefox.
À ce stade, nous avons donc deux informations essentielles :
conversation ID session access token
Ensuite, nous ne regardons plus la page.
C’est ici que notre approche change complètement.
Au lieu de demander au navigateur de parcourir le contenu affiché, V4 demande directement les données de la conversation au backend utilisé par ChatGPT.
Firefox │ │ conversation ID │ session token ▼ ChatGPT conversation endpoint │ ▼ JSON │ ▼ conversation data
La réponse n’est donc pas une succession d’éléments HTML à parcourir.
Nous recevons une structure de données.
Et cette différence est fondamentale.
We are not reading the conversation from the screen.
We are reading the conversation data.
Le JSON contient beaucoup plus qu’une simple liste de messages.
Au premier regard, on pourrait imaginer quelque chose de très simple :
message 1 message 2 message 3 message 4 ...
Mais ce n’est pas ainsi que la conversation est structurée.
La réponse contient notamment un mapping.
Ce mapping associe des identifiants de nœuds à des objets qui contiennent notamment leur parent, leurs enfants et, lorsqu’il existe, le message correspondant.
mapping │ ├── node │ ├── parent │ ├── children │ └── message │ ├── node │ ├── parent │ ├── children │ └── message │ └── ...
C’est là que les choses deviennent intéressantes.
Une conversation ChatGPT peut contenir des embranchements. Une réponse peut être régénérée. Un message peut être modifié. Plusieurs chemins peuvent donc exister à partir d’un même point.
V4 ne peut pas simplement prendre tous les nœuds et les mettre bout à bout.
Le point de départ du chemin actif.
Le JSON fournit également une information essentielle : current_node.
Ce nœud permet de retrouver le chemin correspondant à la conversation active.
mapping
│
├── branch A
│
├── branch B
│
└── branch C
│
▼
current_node
│
▼
active pathÀ partir de là, le travail de V4 consiste à reconstruire une séquence exploitable à partir de la structure reçue.
Le principe est simple à représenter :
current_node
│
▼
parent
│
▼
parent
│
▼
...
│
▼
rootLe chemin est ensuite remis dans son ordre naturel.
root ↓ message ↓ message ↓ message ↓ current node
Nous obtenons enfin une séquence que l’exporteur peut traiter.
De la structure au document.
Une fois le chemin reconstruit, V4 n’a plus besoin de connaître la mécanique interne du graphe pour produire son export.
Elle dispose maintenant d’une suite de messages exploitables.
API response
↓
JSON
↓
mapping
↓
current_node
↓
active path
↓
messages
↓
exportDans V4.0.1, cette chaîne mène notamment aux deux formats qui constituaient le cœur de la première version :
active conversation
│
├───────────────┐
▼ ▼
Markdown HTML
│ │
.md .htmlLes traitements sont ensuite effectués localement.
Aucune conversation n’est envoyée vers un serveur StalkerLabs pour être reconstruite.
Le serveur intermédiaire n’existe tout simplement pas.
Pourquoi cette architecture nous intéressait ?
Notre ancien problème venait justement du fait que le DOM ne représente pas nécessairement l’intégralité d’une très longue conversation à un instant donné.
Une page peut être virtualisée. Des éléments peuvent être absents du DOM. Le navigateur peut réinjecter des messages pendant le défilement.
Pour un exporteur, cela crée une quantité inutile de problèmes.
Avec l’accès direct aux données de conversation, nous pouvons travailler sur la structure complète reçue plutôt que sur ce qui est actuellement visible à l’écran.
The screen is for reading.
The conversation data is for exporting.
Et V4 vérifie avant d’exporter.
Nous avons également voulu éviter un comportement très simple : considérer qu’un export est réussi simplement parce qu’une requête HTTP a répondu.
La logique de V4 vérifie plusieurs étapes avant d’arriver au téléchargement.
API response received
↓
mapping present ? ✓
current_node present ? ✓
root found ? ✓
active path valid ? ✓
messages reconstructed ✓
↓
DOWNLOADC’est cette philosophie qui explique l’indication VERIFIED dans l’interface.
Le plugin ne fait pas seulement :
REQUEST → DOWNLOAD
Il fait plutôt :
REQUEST ↓ RECEIVE ↓ UNDERSTAND ↓ RECONSTRUCT ↓ VERIFY ↓ DOWNLOAD
Un détail important.
Cette architecture dépend de la structure interne utilisée par ChatGPT au moment où V4 a été développée.
Les interfaces internes d’un service web peuvent évoluer sans préavis. Notre objectif n’est donc pas de prétendre que cette structure est éternelle, mais de comprendre précisément ce que V4 reçoit et de vérifier chaque étape avant de produire un fichier.
C’est aussi pour cette raison que le panneau de diagnostic existe.
STALKER DIAGNOSTICS Endpoint conversation API Extraction API Messages detected Mapping nodes detected Current node detected Active path verified Integrity ✓
Si ChatGPT change un jour la structure de ses données, nous voulons pouvoir voir où le problème apparaît.
Pas simplement obtenir un mystérieux Export failed.
La partie la plus intéressante est encore à venir.
Parce que nous avons volontairement gardé le détail du mapping pour la suite.
Pourquoi un message possède-t-il un parent ?
Pourquoi plusieurs children peuvent-ils exister ?
Que se passe-t-il lorsqu’une réponse est régénérée ?
Et surtout : comment choisir le bon chemin lorsque plusieurs branches existent ?
C’est là que l’on découvre que la conversation n’est pas une liste.
C’est un graphe.
À suivre …
(3) – De JSON brut à quatre formats d’export
Nous allons ouvrir le mapping, regarder les parent, les children et le current_node, puis suivre concrètement la reconstruction d’une branche active.
La partie la plus amusante commence là.
AxehGo & DebIA
Independent Research & Experiments in Linux, AI and Statistical Computing
// discussion
No comments