跳到主要內容

【2026 最新】SoL-Pi 教學:四機制逐一 A/B、隱私檢查與回滾

最後更新: ·
SoL-Pi 教學 教學首圖

你把同一個 coding-agent 任務跑了兩遍,第二次 Token 少了四成,真的代表工具變有效率嗎?也可能只是模型剛好走了較短的路、少做一次測試,甚至根本沒有完成任務。這篇 SoL-Pi 教學不重講論文,而是帶你把四個開關拆開,一次只測一個。

這是 SoL-Pi 原理與官方 benchmark 分析的實作續篇,專為第一次做 Agent A/B 的讀者寫。你會完成版本釘選、baseline、四組獨立測試、隱私檢查,以及可復原的停用與移除流程;這裡不把開發團隊的 benchmark 寫成本站實測,也不虛構一組漂亮的節省率。

SoL-Pi 教學先說結論:成功率要先守住

記住這個公式:有效省 Token = 任務成功率守門 × 一次只開一個機制 × 比較「每次成功」的總成本。

  • 先用四個開關全關的設定跑 baseline。
  • 之後依序只開 Action Fusion、ObservationPack、Evidence-Preserving Reducer、Online Context Compact。
  • 每組至少做 3 次冒煙重跑,固定模型、thinking、prompt、Repo commit 與驗收指令。
  • 只要成功率下降,就算 Token 變少,也先判定不通過。
  • Evidence-Preserving Reducer 可能把合格的診斷 log 送到你指定的 reducer 模型;先用合成資料測。

三次重跑只能幫你抓出明顯回歸,不是統計學證明。若要決定是否放進團隊工作流,再把樣本擴成多個真實任務,並保留每次 run 的 JSONL、驗收輸出與 session ID。

SoL-Pi 是什麼?把四個開關想成四種「減重」

SoL-Pi 是 NVIDIA Research 公開的 Pi extension。它不換掉模型,而是在 Agent 的執行層處理重複回合、過大的工具輸出、冗長診斷 log 與已完成工作留下的 context。官方設定文件顯示,四個機制預設都是 false,很適合逐項驗收。

  1. Action Fusion:把「改檔後再跑驗證」合成一次工具呼叫,少一次模型來回。
  2. ObservationPack:大型純文字工具結果先完整送兩次,之後換成短摘要與可回讀的 observation ID。
  3. Evidence-Preserving Reducer:把較長的 build/test log 交給另一個模型壓成 receipt,再逐字核對引用是否真的出現在本機 archive。
  4. Online Context Compact:在完成 plan step 的邊界估算後續成本;達到經濟門檻或 context 壓力時,才呼叫 Pi 的原生 compaction。
SoL-Pi 四個機制分別處理工具回合、大型觀察、診斷紀錄與長期 context
四個機制省在不同位置,所以要拆成四組 A/B,不能把「全開」當成單一原因。

官方論文在 EdgeBench 報告完整組合可降低約 44.7%–49.0% 的 Token 流量,但平均分數只保留 Pi 的約 94%;同一篇論文也記錄 Terminal-Bench 4 的通過數從 Pi 的 18/63 變成 SoL-Pi 的 15/63。這些都是開發團隊在特定版本、模型與任務上的 point estimate;本文在 2026 年 9 月 20 日檢查 pinned tree 與 release surface,只找到 implementation、tests 與 docs,未看到可獨立重跑頭條數字的完整 traces、runner 與 cost ledger。因此,數字適合拿來建立假說,不適合直接當成你的預期節省率。想先看數字邊界,可回到前篇分析

第 1 步:釘住 Pi 0.85.1 與 SoL-Pi commit

SoL-Pi 的官方安裝協議指定 Node.js 22.19 以上,並以 @earendil-works/pi-coding-agent@0.85.1 作為測試版本。以下把 SoL-Pi 釘在本文檢查過的 commit bd005888b9b8a3fcdb511feb91fc27d3dfa8f2b1;commit 是固定座標,之後即使 main 繼續前進,你仍能重跑同一份程式。

node --version
npm --version
git clone https://github.com/NVlabs/SoL-Pi.git
git -C SoL-Pi checkout bd005888b9b8a3fcdb511feb91fc27d3dfa8f2b1
cd SoL-Pi
npm ci --ignore-scripts
npm run check
npm audit --audit-level=high
node scripts/check-pi-compat.mjs
npx vitest run tests/all-mechanisms.test.ts

任何一行失敗都先停下來。特別是 npm audit 與完整測試不能用 || true 略過,因為 Pi package 會以 Pi 程序的檔案、程序、網路與憑證權限執行。檢查通過後,再從你的測試專案安裝指定 Pi,並用 SoL-Pi checkout 的絕對路徑做 project-local 註冊:

npm install --global --ignore-scripts @earendil-works/pi-coding-agent@0.85.1
pi --version
cd /absolute/path/to/your-test-project
pi install "/absolute/path/to/SoL-Pi" --local --approve
pi list --approve

pi --version 應顯示 0.85.1,而 pi list 應列出你剛才的絕對 checkout 路徑。用 project-local scope 的好處是實驗範圍留在測試 Repo;Pi 官方文件也提醒,extension 具有任意程式碼執行能力,所以只在你已審查、已信任的專案啟用。

第 2 步:先建四個開關全關的 baseline

在測試專案建立 .pi/sol-pi.json。Project config 會整份取代 global config,不會把兩份合併;每次換設定後都要啟動新 Pi process,別在同一個 session 中途切開關。

{
  "version": 1,
  "actionFusion": false,
  "observationPack": false,
  "evidencePreservingReducer": false,
  "onlineContextCompact": false,
  "cacheWriteReadRatio": 12.5
}

選一個小而可判分的固定任務,例如:「修正一個已知 failing test,只能改指定模組,最後執行指定測試;測試通過才算完成」。把以下條件寫進 run manifest,之後一項都不要偷換:

  • 同一個乾淨 Repo commit,以及每次 run 前相同的工作樹狀態。
  • 同一個 provider、model、thinking level、prompt 與最大預算。
  • 同一條機械式驗收指令;不要由模型自己宣布成功。
  • 同一個冷/熱 cache 政策,並記錄採用哪一種。
  • 每次都用新 session,保留 JSONL、wall time、最終 diff 與驗收輸出。
mkdir -p .pi-ab/runs .pi-ab/sessions
/usr/bin/time -p pi --mode json --approve \
  --session-dir "$PWD/.pi-ab/sessions" \
  --provider YOUR_PROVIDER --model YOUR_MODEL \
  --name baseline-01 \
  "修正指定 failing test;只能改 src/example.ts;最後執行 npm test -- example.test.ts,測試通過才算完成。" \
  > .pi-ab/runs/baseline-01.jsonl \
  2> .pi-ab/runs/baseline-01.time

YOUR_PROVIDERYOUR_MODEL 與 prompt 換成你的固定值。JSON mode 會輸出完整事件流;message_end 的 assistant message 帶有 authoritative usage,tool_execution_end 可計工具呼叫,turn_start 可計回合。Pi 的 /session 總數還會納入工具回報與摘要生成用量,因此正式比較時,以每個 session 顯示的 total tokens/cost 為主,JSONL 用來解釋差異。

jq -s '{
  turns: ([.[] | select(.type == "turn_start")] | length),
  tool_calls: ([.[] | select(.type == "tool_execution_end")] | length),
  tool_errors: ([.[] | select(.type == "tool_execution_end" and .isError == true)] | length),
  assistant_tokens: ([.[] | select(.type == "message_end" and .message.role == "assistant") | (.message.usage.totalTokens // 0)] | add // 0)
}' .pi-ab/runs/baseline-01.jsonl

分母要用成功的 run。若 baseline 三次成功、某機制只有一次成功,不能只拿那一次漂亮數字相比;先把成功率回歸列為失敗,再查 log。

SoL-Pi A/B 實驗從固定任務、單一開關到成功率與 Token 記分板
正確順序是「固定任務 → 一次一個開關 → 先看成功率 → 再看每次成功的 Token 與時間」。

第 3 步:Action Fusion A/B,看是否真的少一個模型回合

把 config 中只有 actionFusion 改成 true,其餘三個維持 false。它會替換 Pi 的 editwrite tool schema,讓模型可在同一個呼叫帶入 then_run。理想案例是「寫檔 → 模型再決定跑測試」由三段縮成「寫檔+測試 → 模型看結果」兩段。

{
  "version": 1,
  "actionFusion": true,
  "observationPack": false,
  "evidencePreservingReducer": false,
  "onlineContextCompact": false,
  "cacheWriteReadRatio": 12.5
}

驗收時看三件事:JSONL 的 tool args 是否真的出現 then_run、相同任務的 turn 是否下降、驗收測試是否仍通過。若模型沒選用 then_run,那次只能記為「未觸發」,不能宣稱 Action Fusion 沒效果。官方實作還會在執行命令前檢查目標檔案雜湊;檔案在排隊期間被改動時,融合命令會被跳過,避免把驗證跑在意外版本上。

這一格尤其不能省:2026 年 9 月 11 日有使用者在公開 issue #20回報 Pi 0.85.1 未執行 then_run;本文釘選的較新 commit 已加入 0.85.1 package integration test,官方相容性文件也說測試通過,但那組測試使用 deterministic faux provider,不等於你的 live provider 路徑已被驗證。因此,把 then_run marker 與命令輸出列為 blocking acceptance evidence。

第 4 步:ObservationPack A/B,確認大輸出可逐頁取回

這組只開 observationPack。官方程式的門檻是「成功、純文字、超過 10 KiB」的工具結果;同一 observation 在前兩次 provider request 仍完整送出,從第三次開始才改成含 1 KiB 頭尾節錄的 placeholder。因此,一個只問一次就結束的短任務不會測到它。

{
  "version": 1,
  "actionFusion": false,
  "observationPack": true,
  "evidencePreservingReducer": false,
  "onlineContextCompact": false,
  "cacheWriteReadRatio": 12.5
}

準備一份不含私密資訊、可重建且超過 10 KiB 的合成文字 fixture,讓任務讀取它後還要完成至少三次模型請求。觸發後,session 目錄內應出現 sol-pi/<session-id>/observation-pack/ledger.jsonl,事件會由 full 轉為 placeholder。請模型用 placeholder 內的 ID 呼叫 obs_recall,再依 next_offset 逐頁讀到 eof=true;每頁上限約 16 KiB/400 行,不能把只讀第一頁誤寫成「完整取回」。

通過條件是:任務仍成功、ledger 確實記到 placeholder、需要的原文能以 obs_recall 讀回,而且 archive 的 SHA-256 與同一份 fixture 一致。ObservationPack 修改的是送往 provider 的 context projection,不會改寫已保存的原始 session history。

第 5 步:Evidence-Preserving Reducer 先做隱私測試

這組只開 evidencePreservingReducer,並先指定你已在 Pi 設定、已授權使用的 provider/model。它只考慮特定 build/test 類命令的較長診斷輸出,官方實作門檻為 4,096 bytes;原始 log 會先寫進本機 archive,再交給 reducer。回傳內容只有在 schema、hash、exit 狀態與逐字 quote 全部通過 deterministic verifier,且 receipt 確實較小時才會套用,否則原始結果照常交給主模型。

{
  "version": 1,
  "actionFusion": false,
  "observationPack": false,
  "evidencePreservingReducer": true,
  "evidencePreservingReducerProvider": "YOUR_REDUCER_PROVIDER",
  "evidencePreservingReducerModel": "YOUR_REDUCER_MODEL",
  "onlineContextCompact": false,
  "cacheWriteReadRatio": 12.5
}

第一次只餵合成 log。官方安全文件明確說,likely-secret detector 是預防措施,不是完整的 secret scanner;需要全程留在本機的 log,不要啟用遠端 reduction。通過條件包括:session JSONL 中的 reducer journal 有 candidateapplied(或清楚的 fallback 原因)、receipt 的每段 evidence 能在 archive 原文逐字找到、source hash 可重算一致,以及 reducer 用量也有計入成本。

若輸出含像憑證的字串而觸發 likely-secret,或模型不可用、回覆無法驗證、receipt 不夠短,正確行為是 fallback。這不是「節省失敗」而已,而是安全與完整性守門真的有工作。

還有一個要列入威脅模型的未定案訊號:2026 年 9 月 15 日的公開 issue #55回報 EPR 重用既有 archive object 時可能接受同內容的 symlink。這是尚未由維護者定案的使用者報告,不把它寫成已確認漏洞;但在釐清前,測試應放在只有自己能寫入的 session directory,並把 archive object 是否為 regular file 納入驗收。

第 6 步:Online Context Compact A/B,別把比率當帳單

最後一組只開 onlineContextCompact。它新增 update_plan,在 plan step 完成的邊界估算剩餘請求、context 成長、cache write/read ratio 與改寫成本;只有預估可省下更多,或接近 context window 壓力時才 compact。這表示短任務可能完全不觸發,屬於合理結果。

{
  "version": 1,
  "actionFusion": false,
  "observationPack": false,
  "evidencePreservingReducer": false,
  "onlineContextCompact": true,
  "cacheWriteReadRatio": 12.5
}

cacheWriteReadRatio 是 compaction 決策輸入,不是價格表,也不是最終費用估算。官方設定說它在 extension 啟動時載入,換模型後不會自動重算;如果 provider 的 cache 政策不同,請先查當下官方價格,再改 ratio,並開新 session。驗收時看 session log 是否出現版本化 plan state 與 compaction entry、compact 後是否自動續跑並重建 plan,以及最終任務是否成功。

短任務通過後,再補一個長 session:2026 年 9 月 17 日的公開 issue #70回報舊的 request horizon 可能讓後段邊界過度 compact。它同樣是尚未定案的單一使用者 trace,但足以提醒你記錄每次 compact 前後的 context、距上次 compact 的請求數,以及是否真的回收 rewrite/cache debt;若出現短時間連續 compact,就先停用這個開關。

第 7 步:用同一張記分卡判斷四組結果

不要只抄「總 Token」。每個機制至少記以下欄位,並在 baseline 與各 A/B 組使用完全相同定義:

  • 成功:固定驗收指令的 exit code 與必要產物。
  • 總 Token/成本:Pi session 的完整 totals,包含主模型、工具回報與 summary;EPR 另列 reducer usage。
  • 時間:wall-clock,不把快取預熱偷偷算給某一組。
  • 工作量:turn、tool call、tool error 與最終 diff 大小。
  • 觸發證據:then_run、ObservationPack ledger、reducer journal、compaction entry。
  • 可追溯性:session ID、Repo commit、config SHA-256、JSONL 與驗收輸出位置。

建議判分順序是:① 成功率不能退步;② 證據可取回;③ 隱私路徑符合預期;④ 才比較每次成功的 Token、成本與時間。若一個開關平均少 20% Token,卻讓成功率從 3/3 變 2/3,先回滾而不是替它找理由。你也可以參考Agent Harness A/B Test,理解為什麼一次只動一個旋鈕。

資料去哪裡?本機 archive、遠端 reducer 與 session state

SoL-Pi 四個機制的本機保存、遠端 reducer 與可復原回滾資料流
Action Fusion 留在工具回合;ObservationPack 與 EPR 會寫本機 archive;只有 EPR 會把符合條件的 log 送到設定的 reducer 模型。
  • Action Fusion:在 Pi 工具層把改檔與命令串起來,沒有額外 reducer call。
  • ObservationPack:原文保存在 <session-directory>/sol-pi/<session-id>/observation-pack/;官方 README 明確說 archive 在 session 結束後不會自動刪除。
  • Evidence-Preserving Reducer:原始診斷 log 先寫入 evidence-preserving-reducer/,合格內容才會經 Pi 管理的驗證與憑證路徑送至設定模型。
  • Online Context Compact:plan 與 compaction state 寫入 Pi session log,不另建 sidecar;刪除該 Pi session 時會一併移除這類 state。

這也是為什麼「刪掉 session」和「刪掉 SoL-Pi archive」不能被當成同一件事。Pi 的 session picker 可從 /resume 選取 session 後按 Ctrl+D 並確認;Pi 在可用時會呼叫系統 trash。ObservationPack/EPR archive 則要先由 /session 記下精確 session directory 與 ID,再檢查對應的 sol-pi/<session-id> 資料夾。

如何回滾與完整移除 SoL-Pi?

回滾先求可復原,不要直接對整個 .pi 或 home directory 做遞迴刪除:

  1. 檢查 project 與 user-wide 兩個 config 位置,確認目前實際生效的是哪一份。
  2. 在有效設定中把四個 feature flag 全改回 false,重啟 Pi,跑一次原本驗收任務。
  3. pi list --approve 確認 package source 與 scope,再執行 project-local remove。
  4. 移除 package 後,再將 .pi/sol-pi.json 重新命名為 sol-pi.json.disabled,保留可還原設定。
  5. /session 鎖定單一 session ID,先把該 session 的 SoL-Pi archive 移到隔離資料夾;確認不再需要後才透過系統垃圾桶移除。
  6. 重開 Pi,確認沒有 extension load error,再跑 baseline 驗收。
pi list --approve
pi remove "/absolute/path/to/SoL-Pi" --local --approve
mv .pi/sol-pi.json .pi/sol-pi.json.disabled
mkdir -p .pi-ab/quarantine
mv "<session-directory>/sol-pi/<exact-session-id>" \
  ".pi-ab/quarantine/<exact-session-id>-sol-pi"

最後兩個 placeholder 必須替換成 /session 顯示的精確值,不能原樣貼上。若 pi list 顯示的 source 與安裝時不同,先停下來確認 scope;不要猜另一個路徑,也不要同時移除 user-wide 與 project-local 版本。

SoL-Pi 教學常見失敗:看見省 Token,不等於通過

  • 四個一起開:你無法知道是哪個機制省下 Token,也無法定位成功率回歸。
  • 只跑一次:Agent 路徑本來就有變異,一個樣本只能算 smoke test。
  • 只看 input token:summary、reducer、cache 與失敗重跑可能把成本移到別處。
  • 用真實機密測 EPR:secret detector 不是安全邊界,第一輪應使用合成 log。
  • 換模型卻沿用 ratio:cacheWriteReadRatio 不會跟著模型自動更新。
  • 沒保留 trigger evidence:功能未觸發與功能無效,是兩個不同結論。
  • 直接刪整個資料夾:會讓 baseline、session、archive 與其他 Pi 設定一起失去,回滾也無從核對。

FAQ:8 個最容易誤判的問題

1. SoL-Pi 官方說少近一半 Token,我也會得到同樣結果嗎?

不一定。官方數字來自特定 benchmark、模型與設定;你的任務是否會產生大工具輸出、長 log、重複驗證與多個 plan 邊界,會直接影響觸發率。

2. 四個機制可以一開始就全開嗎?

可以設定,但不適合第一次驗收。先逐項 A/B,知道每個開關在你的工作負載中做了什麼,再測 full stack 的交互效果。

3. ObservationPack 壓縮後,原文還找得到嗎?

可以逐頁回讀已歸檔的 observation。用 placeholder 的 ID 呼叫 obs_recall,沿著 next_offset 讀到 eof=true,並用 archive hash 做完整性核對。

4. EPR 的 log 全都只留在本機嗎?

不是。原文先本機歸檔,但符合條件的診斷 log 可能送到你設定的 reducer model;要求資料全程留在本機的工作負載不要啟用它。

5. likely-secret detector 通過,就代表 log 安全嗎?

不代表。官方安全文件把它定位為 precaution,不是完整 secret scanner。是否能傳送,仍要由你的資料分類與 provider 政策決定。

6. Online Context Compact 沒觸發,是 bug 嗎?

不一定。任務太短、沒有完成 plan boundary,或預估節省低於 rewrite cost,都可能讓它合理地不 compact;先查 plan state 與事件,而不是只看最終 Token。

7. 哪個指標應該排第一?

任務成功率。接著才是可追溯性、隱私與每次成功的 Token/成本/時間。省下 Token 卻增加失敗重跑,通常不是有效率。

8. AlphaLab 這篇有跑出四組節省率嗎?

這篇提供可重跑的驗收流程,不發布本站未執行的數字。目前環境未預先提供 Pi runtime 與已授權模型帳號,因此依官方 artifacts 建立測法、保留版本與失敗條件;你跑完後應以自己的 retained artifacts 做決策。

給新手的 5 個重點

  1. SoL-Pi 不是一個「省 Token」按鈕,而是四個處理不同浪費來源的開關。
  2. 先固定 Pi、SoL-Pi、模型、任務與驗收指令,再做 A/B。
  3. 一次只開一個機制,並留下是否觸發的證據。
  4. 成功率是守門條件;Token、成本與時間排在它之後。
  5. EPR 涉及遠端 reducer;archive 與 session state 也要納入刪除與回滾計畫。

結語:先跑 baseline,再談 49%

回到開頭的公式:有效省 Token = 成功率守門 × 一次只開一個機制 × 比較每次成功的總成本。你現在最值得做的不是全開四個 flag,而是挑一個 10–20 分鐘能驗收的小任務,先跑三次全關 baseline,保存 session ID、config hash 與驗收輸出。

等四組都過關,再做 full-stack 測試;任何一組讓成功率、證據取回或隱私路徑變差,就回滾那個開關。若你想系統化補齊 Agent、context 與自動化工作流,可接著看 AlphaLab 的 AI 實戰課程,把這張記分卡變成自己的標準驗收模板。

ALPHALAB 社群

有問題?來 Telegram 聊

和 Terry、編輯、其他網友一起討論這篇文章。提問、分享觀點,回覆更即時。

加入 Telegram 討論

📩 訂閱 AlphaLab 電子報

每週最多三封:一封 Weekly 週報與最多兩封關鍵 Alpha Signal。

我們不會 spam,隨時可退訂。