← 返回研究
單人建構 2026-05-05

上下文視窗稅:AI 工具輸出有 48% 的 Token 被浪費了

每次 AI 編碼會話都有一個隱藏的 Token 消耗:JSON 回應、檔案讀取、測試失敗日誌等工具輸出,把大量模型根本不需要的結構塞入上下文視窗。實測顯示,透過 TOON 符號和 debug 輸出折疊,可以自動回收 24–66% 的 Token 消耗。

重點摘要

AI 編碼助理在「結構」上燒 Token,而非「意義」。一個 200 行的 JSON API 回應發送了數千個 Token 的括號、引號和重複鍵名——模型在推理時對這些用量為零。在跨 JSON、CSV、YAML 和 debug 輸出的實測中:

內容類型Token 節省
中型 JSON65.0%
API 格式回應50.3%
巢狀物件48.2%
多語言內容46.3%
大型 JSON42.6%
CSV 類資料24.5%
平均值(48 個案例)48.1%

來源:Toonify 基準測試,2026 年 4 月 30 日。

機制:透過 PostToolUse hook 在工具輸出進入上下文視窗前攔截並壓縮。不需要改變使用 Claude Code 的方式。


問題:JSON 不是 LLM 輸入的正確格式

JSON 是為機器對機器的序列化而設計的。每個值都用引號包裹,每個鍵對陣列中的每個物件都重複一次,每層巢狀都增加括號和逗號。對解析 JSON 的程式而言,這個結構是契約。對閱讀它的 LLM 而言,大部分結構都是雜訊。

以一個 10 行的 API 回應為例:

[
  {"id": 1, "name": "Blue Lake Trail", "distanceKm": 7.5, "elevationGain": 320},
  {"id": 2, "name": "Royal Arch", "distanceKm": 5.2, "elevationGain": 490},
  ...再 10
]

鍵名 idnamedistanceKmelevationGain 每行出現一次。10 行就有 40 次鍵名重複。模型的注意力不需要重複就能理解 schema——它需要 schema 一次,然後是值。

TOON(Token-Oriented Object Notation,面向 Token 的物件符號)直接解決這個問題。對於相同結構的物件陣列,它使用 CSV 式表格布局:宣告一次標頭,然後逐行列出值:

id | name | distanceKm | elevationGain
1 | Blue Lake Trail | 7.5 | 320
2 | Royal Arch | 5.2 | 490

資料模型是無損的——TOON 是 JSON 的直接替代表示,不是有損摘要。差異在於結構開銷:TOON 剝除了為解析器而存在的部分,而非為模型而存在的部分。


為什麼 Hook 式壓縮有效

Toonify 的第一個版本是 MCP server:你需要明確調用工具來壓縮內容。沒有人能持續這樣做。

解鎖真實使用的洞見是 PostToolUse hook。Claude Code 在每次工具調用後、結果進入上下文視窗前觸發這個事件。在那裡攔截意味著:

  • 每個 Bash 輸出自動壓縮
  • 每個 Read 結果自動壓縮
  • 不需要額外指令,不需要改變工作流程,不需要紀律

Hook 讀取工具輸出,偵測內容類型(JSON、CSV、YAML 或 debug 輸出),如果節省超過 30% 閾值就壓縮,否則原樣傳遞。Token 數低於 50:直接傳遞。壓縮會破壞內容:直接傳遞。處理過程中出現任何錯誤:直接傳遞。這個實作永遠不會中斷工作流程。

這個設計原則——永遠靜默失敗,永遠不中斷會話——讓自動 hook 執行無需每個工具逐一同意就能安全上線。


v0.7.0 的擴展:Debug 輸出有相同的問題

上線六個月後,使用模式揭示了第二個罪魁禍首:debug 輸出。

長篇測試失敗日誌、TypeScript 編譯器診斷訊息和 lint 輸出,與 JSON 有相同的 Token 浪費模式——重複而非意義。一個在 40 行中針對 40 個相同問題重複檔案路徑和錯誤代碼的 TypeScript 錯誤,在結構上與 JSON 陣列重複 40 個物件鍵名完全相同。

v0.7.0 的壓縮器通過折疊重複診斷模式來處理這個問題:

  • 連續相同行折疊為一行,附帶 (×N) 計數
  • 不同檔案路徑但相似的 TypeScript/lint 診斷折疊為一個代表性樣本附計數
  • Stack trace 保留頂部框架(失敗所在位置),折疊下方的函式庫內部調用

實際上,這讓測試失敗的上下文顯著縮短,同時不丟失對 debug 真正重要的資訊——哪個檔案、哪一行、什麼錯誤。


壓縮效果最好(和最差)的情況

高壓縮(50–66%): 相同結構的物件陣列——API 回應、資料庫查詢結果、具有共享 schema 的日誌條目。鍵名重複問題在這裡最大。

中等壓縮(42–48%): 巢狀 JSON、多語言內容(TOON 正確處理 Unicode)、大型檔案讀取。

低壓縮(24%): 已是欄位結構的 CSV 類資料。TOON 仍然移除引號開銷並規範化空白,但增益較小,因為 CSV 已經相對緊湊。

完全跳過: 低於 50 Token 的短內容、自由格式散文、必須保留精確原始格式的內容(二進位資料、某些配置)。評估器跳過這些情況,而非冒著損壞的風險。


快取層

在真實 AI 編碼會話中,相同的內容會反覆出現——你讀取同一個配置檔,執行同一個測試套件,得到同一個 API 回應。與其對每次 hook 觸發重新壓縮相同內容,Toonify 在本地 LRU 快取中快取壓縮結果,TTL 為一小時。

快取以內容雜湊值為鍵。快取命中意味著每次調用的開銷接近零——壓縮工作對每個唯一內容在每次會話中只發生一次。


田野筆記

原始專案描述中 30–65% 的範圍來自早期基準測試平均值。在更廣泛的邊緣案例測試——非常小的 payload、已緊湊的 CSV、多語言內容——之後,當前測量的 48.1% 平均值更能代表真實世界會話的情況。

塑造每個取捨的設計約束:只有當壓縮對開發者透明時,Token 節省才有意義。需要思考何時壓縮的開發者,已經把大部分認知成本還回去了。

延伸問題

  • 上下文視窗到多大時,壓縮本身的開銷(解析 + 編碼時間)會超過它帶來的節省?
  • TOON 編碼是否會降低模型在結構化資料推理任務上的準確率,還是模型能像處理 JSON 一樣良好地處理位置符號?