非 codex モデルの場合、オープンソースの Codex CLI はローカルでコンテキストを圧縮します。LLM が圧縮プロンプトを使用して会話を要約します。圧縮されたコンテキストが後で使用される際、responses.create() はその要約をフレーミングするハンドオフプロンプトと共に受け取ります。両方のプロンプトはソースコードで確認できます。
codex モデルの場合、CLI は代わりに compact() API を呼び出し、暗号化されたブロブを返します。内部で LLM を使用しているかどうか、どのプロンプトを使用しているか、ハンドオフプロンプトが存在するかどうかは不明です。
以下では、シンプルなプロンプトインジェクション(2 回の API 呼び出し、35 行の Python)によって、API 圧縮パスが実際に LLM を使用してコンテキストを要約しており、独自の圧縮プロンプトと、要約の前に付加されるハンドオフプロンプトがあることを明らかにします。これらのプロンプトはオープンソース版とほぼ同一です。
ステップ 1 — compact()
細工されたユーザーメッセージを指定して compact() を呼び出します。サーバー側では、圧縮用 LLM が独自の隠されたシステムプロンプト(これまで見たことがなく、解明したいもの)を使用して入力を処理します。
サーバーは圧縮用のコンテキストを次のように組み立てているようです:

圧縮用 LLM はシステムプロンプトと入力を一緒に読み取ります。入力にはインジェクションペイロード(上の赤いテキスト)が含まれているため、圧縮用 LLM は自身のシステムプロンプトを出力に含めるように誘導されます。このプレーンテキストの要約は OpenAI のサーバー上にのみ存在します。私たちが見ることができるのは暗号化されたブロブだけです:

この時点では、ブロブの中身を読み取る方法はありません。 これは AES 暗号化されており、キーは OpenAI のサーバー上にあります。圧縮用 LLM がインジェクションに従い、プロンプトを要約に書き込んだことを願うしかありません。それを確認する唯一の方法はステップ 2 です。
ステップ 2 — create()
暗号化されたブロブと 2 つ目のユーザーメッセージを responses.create() に渡します。サーバーはブロブを復号化し、モデルのコンテキストを組み立てます。
送信する内容:

モデルは次のようなものを見ているようです:

ステップ 1 が成功していれば、復号化されたブロブには(インジェクションによって漏洩した)圧縮プロンプトが含まれているはずです。サーバーはブロブの前にハンドオフプロンプトも付加します。そのため、プローブがモデルに見た内容を繰り返させることに成功すれば、出力にはシステムプロンプト、ハンドオフプロンプト、圧縮プロンプトの 3 つすべてが明らかになるはずです。
出力
以下は、extract_prompts.py の 1 回の実行による完全な未編集の出力です。黄色 = システムプロンプト、緑 = ハンドオフプロンプト、ピンク = 圧縮プロンプト。

これらが実際のプロンプトであり、幻覚によるテキストではないとどうしてわかるのでしょうか?抽出された圧縮プロンプトとハンドオフプロンプトは、オープンソースの Codex CLI で非 codex モデルに使用されている既知のプロンプト(prompt.md、summary_prefix.md)と非常によく一致しており、モデルがゼロからそれらをでっち上げた可能性は低いです。実行ごとに結果は異なります。
推測されるパイプライン
すべてをまとめると、抽出結果に基づく、compact() がサーバー側で行っていることの最善の推測は次のとおりです。

スクリプト

未解決の疑問
なぜ Codex CLI は、基盤となるプロンプトがほぼ同一であるにもかかわらず、2 つの完全に異なる圧縮パス(非 codex モデルにはローカル LLM、codex モデルには暗号化 API)を使用するのでしょうか?そして、なぜ要約を暗号化するのでしょうか?
断言は難しいです。おそらく、暗号化されたブロブには、この単純な実験で明らかにできる以上のもの、例えばツールの結果がどのように圧縮および復元されるかに関する何か具体的なものが含まれているのでしょう。しかし、私はそれ以上テストする気にはなりませんでした。





