對於非 codex 模型,開源的 Codex CLI 會在本地壓縮上下文:LLM 使用壓縮提示來總結對話。當壓縮後的上下文後續被使用時,responses.create() 會接收它,並附帶一個交接提示來為該總結提供背景。這兩個提示在原始碼中都可見。
對於 codex 模型,CLI 則改為呼叫 compact() API,該 API 會回傳一個加密的 blob。我們不知道它在內部是否使用了 LLM、使用了哪些提示,或者是否完全有交接提示。
下面,我將展示一個簡單的提示注入(2 次 API 呼叫,35 行 Python 程式碼)如何揭示:API 壓縮路徑確實使用了 LLM 來總結上下文,並帶有其自身的壓縮提示,以及一個附加在總結前的交接提示。這些提示與開源版本幾乎相同。
步驟 1 — compact()
我使用一條精心設計的使用者訊息來呼叫 compact()。在伺服器端,一個壓縮器 LLM 使用其自身的隱藏系統提示(我從未見過,並且想要弄清楚)來處理我們的輸入。
伺服器似乎像這樣組合壓縮器的上下文:

壓縮器 LLM 會一起讀取其系統提示 + 我們的輸入。由於我們的輸入包含一個注入負載(上方的紅色文字),壓縮器被欺騙,將其自身的系統提示包含在其輸出中。這個純文字摘要僅存在於 OpenAI 的伺服器上。我們只看到加密的 blob:

此時我們無法讀取 blob 內部的內容。 它經過 AES 加密,金鑰存在於 OpenAI 的伺服器上。我們只能希望壓縮器遵循了注入指令,並將其提示寫入了摘要中。找出答案的唯一方法是進行步驟 2。
步驟 2 — create()
我將加密的 blob + 第二條使用者訊息傳遞給 responses.create()。伺服器解密 blob 並組合模型的上下文。
我發送:

模型似乎會看到類似這樣的內容:

如果步驟 1 成功,解密的 blob 應該包含壓縮提示(由我們的注入洩露)。伺服器還會在 blob 前面加上一個交接提示。因此,如果我們的探測成功讓模型重複它所看到的內容,輸出應該會揭示所有三個部分:系統提示、交接提示和壓縮提示。
輸出
以下是來自一次 extract_prompts.py 執行的完整、未經編輯的輸出。黃色 = 系統提示,綠色 = 交接提示,粉紅色 = 壓縮提示。

我們如何知道這些是真實的提示,而不僅僅是模型幻想的文字?提取出的壓縮提示和交接提示與開源 Codex CLI 中用於非 codex 模型的已知提示(prompt.md、summary_prefix.md)非常吻合,這使得模型從頭開始憑空發明它們的可能性很低。不同執行的結果會有所差異。
推測的流程
綜合所有資訊,以下是我們基於提取結果對 compact() 在伺服器端所做操作的最佳猜測。

腳本

未解問題
為什麼 Codex CLI 使用兩種完全不同的壓縮路徑(非 codex 模型使用本地 LLM,codex 模型使用加密 API),而底層的提示卻幾乎相同?而且為什麼要加密摘要?
很難說。也許加密的 blob 攜帶了比這個簡單實驗所能揭示的更多的東西,例如,關於工具結果如何被壓縮和恢復的特定資訊。但我沒有費心去進一步測試。





