你把同一個 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,很適合逐項驗收。
- Action Fusion:把「改檔後再跑驗證」合成一次工具呼叫,少一次模型來回。
- ObservationPack:大型純文字工具結果先完整送兩次,之後換成短摘要與可回讀的 observation ID。
- Evidence-Preserving Reducer:把較長的 build/test log 交給另一個模型壓成 receipt,再逐字核對引用是否真的出現在本機 archive。
- Online Context Compact:在完成 plan step 的邊界估算後續成本;達到經濟門檻或 context 壓力時,才呼叫 Pi 的原生 compaction。

官方論文在 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_PROVIDER、YOUR_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。

第 3 步:Action Fusion A/B,看是否真的少一個模型回合
把 config 中只有 actionFusion 改成 true,其餘三個維持 false。它會替換 Pi 的 edit 與 write 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 有 candidate 與 applied(或清楚的 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

- 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 做遞迴刪除:
- 檢查 project 與 user-wide 兩個 config 位置,確認目前實際生效的是哪一份。
- 在有效設定中把四個 feature flag 全改回
false,重啟 Pi,跑一次原本驗收任務。 - 用
pi list --approve確認 package source 與 scope,再執行 project-local remove。 - 移除 package 後,再將
.pi/sol-pi.json重新命名為sol-pi.json.disabled,保留可還原設定。 - 用
/session鎖定單一 session ID,先把該 session 的 SoL-Pi archive 移到隔離資料夾;確認不再需要後才透過系統垃圾桶移除。 - 重開 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 個重點
- SoL-Pi 不是一個「省 Token」按鈕,而是四個處理不同浪費來源的開關。
- 先固定 Pi、SoL-Pi、模型、任務與驗收指令,再做 A/B。
- 一次只開一個機制,並留下是否觸發的證據。
- 成功率是守門條件;Token、成本與時間排在它之後。
- EPR 涉及遠端 reducer;archive 與 session state 也要納入刪除與回滾計畫。
接著閱讀
左右滑動查看更多推薦
結語:先跑 baseline,再談 49%
回到開頭的公式:有效省 Token = 成功率守門 × 一次只開一個機制 × 比較每次成功的總成本。你現在最值得做的不是全開四個 flag,而是挑一個 10–20 分鐘能驗收的小任務,先跑三次全關 baseline,保存 session ID、config hash 與驗收輸出。
等四組都過關,再做 full-stack 測試;任何一組讓成功率、證據取回或隱私路徑變差,就回滾那個開關。若你想系統化補齊 Agent、context 與自動化工作流,可接著看 AlphaLab 的 AI 實戰課程,把這張記分卡變成自己的標準驗收模板。





