Pour les modèles non-codex, le Codex CLI open source compacte le contexte localement : un LLM résume la conversation à l'aide d'une invite de compactage. Lorsque le contexte compacté est utilisé ultérieurement, responses.create() le reçoit avec une invite de transition qui encadre le résumé. Les deux invites sont visibles dans le code source.
Pour les modèles codex, le CLI appelle plutôt l'API compact(), qui renvoie un blob chiffré. Nous ne savons pas si elle utilise un LLM en interne, quelles invites elle utilise, ni s'il existe une invite de transition.
Ci-dessous, je montre comment une simple injection d'invite (2 appels API, 35 lignes de Python) révèle que le chemin de compactage de l'API utilise bien un LLM pour résumer le contexte, avec sa propre invite de compactage et une invite de transition ajoutée au résumé. Les invites sont presque identiques aux versions open source.
Étape 1 — compact()
J'appelle compact() avec un message utilisateur conçu. Côté serveur, un LLM compacteur traite notre entrée en utilisant sa propre invite système cachée (que je n'ai jamais vue et que je veux découvrir).
Le serveur semble assembler le contexte du compacteur comme ceci :

Le LLM compacteur lit son invite système + notre entrée ensemble. Parce que notre entrée contient une charge utile d'injection (texte rouge ci-dessus), le compacteur est amené à inclure sa propre invite système dans sa sortie. Ce résumé en texte clair n'existe que sur le serveur d'OpenAI. Nous ne voyons que le blob chiffré :

À ce stade, nous n'avons aucun moyen de lire ce qui se trouve à l'intérieur du blob. Il est chiffré avec AES et la clé se trouve sur les serveurs d'OpenAI. Nous espérons seulement que le compacteur a obéi à l'injection et a écrit son invite dans le résumé. La seule façon de le savoir est l'étape 2.
Étape 2 — create()
Je passe le blob chiffré + un deuxième message utilisateur à responses.create(). Le serveur déchiffre le blob et assemble le contexte du modèle.
J'envoie :

Le modèle semble voir quelque chose comme ceci :

Si l'étape 1 a fonctionné, le blob déchiffré devrait contenir l'invite de compactage (divulguée par notre injection). Le serveur ajoute également une invite de transition au blob. Donc, si notre sonde réussit à faire répéter au modèle ce qu'il voit, la sortie devrait révéler les trois : l'invite système, l'invite de transition et l'invite de compactage.
Sortie
Voici la sortie complète et non éditée d'une exécution de extract_prompts.py. Jaune = invite système, vert = invite de transition, rose = invite de compactage.

Comment savons-nous qu'il s'agit des vraies invites et non d'un texte halluciné ? L'invite de compactage et l'invite de transition extraites correspondent étroitement aux invites connues utilisées pour les modèles non-codex dans le Codex CLI open source (prompt.md, summary_prefix.md), ce qui rend peu probable que le modèle les ait inventées de toutes pièces. Les résultats varient selon les exécutions.
Le Pipeline Supposé
En rassemblant tout cela, voici notre meilleure estimation de ce que compact() fait côté serveur, sur la base de ce que l'extraction a révélé.

Le Script

Question Ouverte
Pourquoi le Codex CLI utilise-t-il deux chemins de compactage totalement différents (LLM local pour les modèles non-codex, API chiffrée pour les modèles codex) alors que les invites sous-jacentes sont presque identiques ? Et pourquoi chiffrer le résumé ?
Difficile à dire. Peut-être que le blob chiffré contient quelque chose de plus que ce que cette simple expérience peut révéler, par exemple quelque chose de spécifique sur la façon dont les résultats des outils sont compactés et restaurés. Mais je n'ai pas pris la peine de tester davantage.





