小墨同學札記 · 譯文串讀
Pi 為什麼把工作階段與上下文留在你手裡
讀完《無法隨身帶走的工作階段》、《Pi 中的壓縮機制》和《Agent 中的提示快取》,我越來越覺得,它們討論的不是三個孤立的功能,而是同一個問題:一次 Agent 工作,究竟有多少部分是我們自己能帶走、檢查和修改的?
想象你讓 Agent 修一個持續兩天的故障。它讀了日誌,改過程式碼,排除了幾種猜測,最後還沒修完。此時你想換模型繼續。如果你手裡只有一個廠商的工作階段 ID,或者一段你無法開啟的“壓縮後狀態”,新模型拿到的究竟是什麼?它能知道已排除的錯誤原因嗎?你能看見遺漏了哪一步嗎?
這是我讀這幾篇譯文時找到的主線:
保留記錄,是為了能追溯;控制上下文,是為了能決定模型現在看什麼;控制轉換層,是為了不讓某一家模型的介面決定你如何工作。
三層連在一起,才接近一個屬於自己的代理框架(Agent Harness)。
先分清三樣東西
- 工作階段記錄回答“任務發生過什麼”。本地 JSONL 工作階段、工作階段樹和擴充功能(Extension)條目,留下分支、工具呼叫與摘要。
- 本輪上下文回答“下一次讓模型看到什麼”。當前分支、壓縮摘要、近期訊息和擴充功能的
context處理,共同決定本輪材料。 - 廠商請求回答“這些材料怎樣交給模型”。Pi 的適配層轉換輸入;必要時,擴充功能可以檢查或調整請求載荷。
工作階段是長期記錄;本輪上下文從當前工作階段路徑重建,還會加入系統提示和工具定義;廠商請求再把這些材料轉換為具體介面需要的形式。“我的工作階段裡有”不等於“模型此刻看到了”;“模型看到了”也不等於“換一家廠商還能原樣接上”。 Pi 的工作階段檔案格式說明列出了工作階段條目如何構成模型訊息;擴充功能文件則提供了在請求前調整訊息和請求載荷的入口。
這裡的“可自定義”也有邊界:Pi 的工作階段檔案有自己的 JSONL 結構,並不是使用者隨意發明一種磁碟格式,Pi 就會自動識別。真正值得關注的是,記錄留在本地且可讀,擴充功能能增加條目或訊息,也能改變從記錄派生出的本輪上下文。
圖解:工作階段留下“發生過什麼”,本輪上下文決定“模型現在看什麼”。這張圖展示的是基本關係;下面兩張繼續解釋字首變化與跨模型交接。開啟原圖
為什麼先要握住工作階段
工作階段可移植性那篇譯文讓我意識到,儲存聊天文字還不夠。程式設計 Agent 的“經歷”還包括系統指令、工具呼叫、工具結果、模型切換、分支和壓縮。如果關鍵步驟只藏在廠商內部,離開它的服務以後,即使匯出了一份漂亮的聊天記錄,也未必能重建當時的工作狀態。
Pi 預設把工作階段儲存在本地 JSONL 檔案中,按工作目錄組織,並以樹結構保留不同路線。你可以繼續、回到分叉點,或另開工作階段。壓縮也會作為條目寫入記錄:舊內容可能不再進入下一輪模型上下文,但原來的工作階段條目仍可回看。這給了我們兩個不同的能力:繼續當前路線,以及事後追問某個判斷從哪裡來。Pi 工作階段文件和檔案格式說明描述了這些機制。
本地工作階段仍不是萬能備份。模型提供商沒有返回的隱藏推理、託管搜尋內部過程,Pi 不可能憑空記錄;工作階段樹也不會替你恢復磁碟檔案。要讓另一個模型接手,至少還應儲存目標、關鍵決策、已改檔案、驗證結果和未解決的問題。程式碼本身仍需靠檔案與 Git 核對。
為什麼平時儘量不動字首,必要時才壓縮
長工作階段有一個容易忽略的成本:下一輪通常會再次傳送前面的大部分內容。提示快取能複用完全相同的輸入字首。所以,一邊工作一邊不斷從中間刪除舊工具結果、重排工具定義、修改系統提示,雖然看起來把提示變短了,卻可能讓後面本可複用的內容重新計算。
這解釋了為什麼 Pi 偏好穩定、以追加為主的記錄。字首穩定,快取才有機會命中;但“有機會”不是保證,提供商仍可能過期、淘汰快取,或把請求路由到別處。工作階段 ID 也不能把兩個不同的字首變成同一個字首。提示快取譯文把這筆成本講得很透。
壓縮是另一件事。當上下文接近模型視窗,或者你主動輸入 /compact,Pi 會把較早的一段內容整理為可讀摘要,並保留近期訊息,再用“摘要 + 近期內容”繼續。這一步有意改寫了輸入字首,原來的提示快取通常要重新建立。換句話說,Pi 不是“保留原字首來壓縮”:它是平時保持字首穩定,確有必要時接受一次快取重置,換取更短、還能繼續工作的上下文。Pi 壓縮(Compaction)文件說明了摘要、保留近期訊息及可自定義的壓縮流程。
圖解:第二輪只是繼續追加,因此相同字首有機會命中快取;壓縮會改寫較早部分,近期訊息雖然保留,舊的完整字首也不再相同。手機上可左右滑動,或開啟原圖放大檢視。
這也是一個取捨,而不是神奇的“無損記憶”。摘要會省掉細節。如果某個報錯原文、使用者約束或驗收結果不能丟,就要讓它在摘要中明確出現,或寫進可重新讀取的專案檔案。壓縮後讓 Agent 複述目標和下一步,再與檔案核對,比只看“壓縮完成”四個字可靠。
為什麼還要能改“模型看到的內容”
如果工作階段記錄等於每次都原樣發給模型,那我們只能在“永久刪除記錄”和“永遠傳送全部記錄”之間選。可真正需要的是第三種選擇:記錄保持可追溯,本輪輸入按任務需要組織。
例如,一次工具執行產生了上千行日誌。你可能希望工作階段保留完整結果,方便追責;下一次呼叫只給模型錯誤摘要、關鍵行號和原始檔案路徑。或者換了一個上下文視窗更小的模型,就需要更緊湊的交接內容。Pi 的擴充功能 context 事件可以在每次模型呼叫前,對訊息副本做非破壞性調整;自定義壓縮鉤子可以提供自己的摘要;自定義訊息可以進入上下文。擴充功能文件和壓縮文件分別給出了這些入口。
我會把這種能力理解為“上下文策略可以自己定”:決定哪些事實必須原樣保留,哪些可以摘要,哪些只在特定任務中提供。它並不意味著 Pi 自動為所有模型找到最優格式,更不意味著一套摘要能在任何廠商那裡維持同一個壓縮比。模型的分詞方式、上下文視窗、工具協議和快取計費都可能不同;換模型後的 KV 快取也不能直接搬過去。可移植的是你能讀懂、能修改的工作記錄與交接規則,不是某個提供商內部的計算狀態。
圖解:換模型時,延續的是可讀記錄和你制定的交接規則。A、B 的請求需要分別適配,廠商內部快取不會跟著遷移。開啟原圖
真正值得問的不是“能壓到多短”
我現在會用一個很樸素的交接來檢驗這些能力:假設明天必須換模型,甚至換一套 Agent,我能否只靠手裡的記錄回答以下問題?
- 使用者最初要完成什麼,哪些要求不能改變?
- 哪些事情已經做完,證據在什麼檔案或工具結果裡?
- 哪些判斷只是猜測,哪些方案已經被排除?
- 壓縮時刪去了什麼細節,有沒有必要回查原工作階段?
- 下一步交給另一個模型時,它實際會收到什麼?
如果答不上來,問題不一定出在模型“不夠聰明”。也可能是工作階段不完整、摘要丟了關鍵約束,或我們根本沒有檢查過傳送前的上下文。
《什麼是代理框架?》說的是系統提示、工具、迴圈與模型轉換層如何一起托住 Agent。在我看來,保留工作階段、字首穩定、壓縮和上下文可調整,正是把這副“安全帶”留在自己手裡的具體做法。它們不保證每一步都正確,卻讓錯誤有機會被發現,規則有地方可改,換路線時不必從一片黑箱重新開始。
想親手驗證,可以從工作階段的儲存與續寫、上下文與壓縮和CASE 02 · 壓縮前後對照開始;再按上文順序讀三篇譯文。本文是我的串讀與判斷,不代表 Earendil 原作者把這些文章合寫成了同一個論點。