DeepSeek Harness 上下文壓縮機制:13 畫格圖文拆解
跟著原始碼級拆解影片逐畫格看懂 dsh 壓縮:什麼時候觸發、裁什麼、摘什麼,日誌又怎麼在替換後重建整個會話。
最近更新: 2026-10-15

這頁圖文基於一支原始碼級拆解影片,逐畫格講清 DeepSeek Harness 的上下文管理與壓縮機制。先說明畫面屬性:原片是旁白講解的機制示意動畫——作者用投影片把壓縮流水線一步一步畫出來,不是產品介面實錄。也正因為是示意,每個機制都被乾淨地隔離在一頁裡,適合當架構課本來讀。
文中關鍵數值——80% 預設觸發門檻、8192 碼點裁剪(保留開頭 4096 + 結尾 1024)、16% 近期原文保留——已對照 deepseek-harness 官方儲存庫文件核驗一致(thresholdRatio 0.8、thresholdChars 8192、retainRatio 0.16,2026-09-23 查證)。官方文件沒有展開的細節(如檢查點的八類資訊劃分)來自作者小木頭對原始碼的解讀,文中已標註。
一分鐘版本
- ▸壓縮在 dsh 裡是外掛能力而非內建邏輯:ctx.compaction 是能力介面,compaction-basic 是預設實作;上下文佔用接近視窗 80%、伺服器端回報超窗、或你手動輸入 /compact,都會觸發整理。
- ▸摘要之前先裁剪:超過 8192 碼點的工具結果只保留開頭 4096 和結尾 1024;裁完若壓力達標,連摘要這步模型呼叫都省了。
- ▸被壓縮的歷史變成結構化檢查點,最近約 16% 視窗原文保留;持久日誌完整記錄每個事件,模型檢視隨時可以靠重放重建。
壓縮流水線,12 步走完
壓縮在架構裡的位置
- 1
先看位置:DeepSeek 的請求鏈多了壓縮一段
影片開場對比請求結構:Codex 式請求是輸入 + 上下文 + 模型請求,DeepSeek Harness 在上下文和模型呼叫之間插入了一個專門的壓縮階段。這頁就是整支影片的地圖——壓縮是請求流水線裡的正式一環,不是事後補救。

請求流水線在上下文和模型呼叫之間多出壓縮一段。到影片 0:32 處看 - 2
認角色:一項能力,多個外掛協作
壓縮被拆成條能力縫:/compact 指令是人工入口,ctx.compaction 是能力介面,compaction-basic 是介面背後的預設實作;旁邊還有兩個可選搭擋——負責計量壓力的 token meter 和負責裁剪工具結果的 tool result pruner。把 compaction-basic 換掉,其餘照常運作。
$ctx.compaction$dsh-compaction$compaction-basic$command-compact
一條能力縫、五個角色:指令、介面、預設實作加兩個可選搭擋。到影片 2:18 處看 - 3
記住三個觸發入口
壓縮從三個地方啟動。每次請求前的 pre-step 檢查會把估算壓力和預設 80% 門檻(可按模型設定)比較;伺服器端已回報超窗時,回復流程跳過一般門檻、先修復現場;你在 agent 閒置時輸入 /compact,則不等 80% 直接按需整理。
$agent/pre-step$context-overflow$/compact · agent idle
三條啟動路徑,只有第一條真的等 80%。到影片 3:50 處看 - 4
看懂計量表:供應商讀數 + 變化估算
token meter 對自己的定位很誠實:它以最近一次成功呼叫的供應商用量為錨點,再估算這之後模型可見內容的變化——新增訊息往上加,替換可能往下減。片中的進度條是定性示意,不代表實測比例。

計量表是估算:上次官方讀數,加上之後的漂移。到影片 4:20 處看
裁剪、選區與摘要
- 5
先裁日誌,再談測量
第一個槓桿不是摘要,是刪除。一條超長工具結果就能佔滿大半個上下文,把它的中段裁掉,壓力可能直接回落到門檻以下。後面幾章的機制,都預設這道最便宜的工序已經跑過。

先裁再說——一條巨大的工具結果可能就是全部問題。到影片 1:15 處看 - 6
拆裁剪器:8192 碼點,保留 4096 + 1024
工具結果文字超過 8192 個 Unicode 碼點(三個 Web 預設目前的設定)就會被改寫:保留開頭 4096 碼點、一條裁剪標記、結尾 1024 碼點。計量單位是碼點不是 token,而且這一步完全不呼叫模型。這兩個數值與官方 compaction-tool-result-pruner 預設值(thresholdChars 8192、headChars 4096、tailChars 1024)一致。
$threshold: 8192 code points$keep head 4096 + tail 1024
8192 碼點是門檻;開頭 4096、標記、結尾 1024。到影片 5:40 處看 - 7
選區:近期 16% 原文保留,切線避開配對
裁完壓力還超,compaction-basic 就開始選區:從最新訊息往前累計,原文保留到大約 16% 視窗預算為止(即官方 retainRatio 預設值),而且切線永遠落在工具呼叫和它的結果之外——配對不拆散。按完整訊息節點累計,實際保留量可能略超 16%;此時只是選定區間,還沒有產生任何摘要。

從最新往前走,切線永不落在呼叫與結果之間。到影片 6:00 處看 - 8
產生檢查點:compaction/start 與八類資訊
摘要以附加指令的方式執行:請求保留原 system、原 tools 和選定的舊訊息,結尾附加一條 user 訊息,要求把對話整理成結構化檢查點。影片把它畫成八類資訊——使用者目標與意圖、關鍵技術概念、檔案與程式碼、錯誤與修復、待完成工作、目前工作、下一步行動、關鍵背景與約束。官方文件確認存在檢查點前言,八類的具體劃分是作者的示意解讀。
$compaction/start
摘要指令要求產出結構化檢查點——八類是作者的示意畫法。到影片 7:05 處看 - 9
摘要合格,才准替換
摘要要過三道關才能頂替歷史:模型完整結束並給出非空文字(出錯、中斷、達到輸出上限截斷都算失敗);只保留 text 內容——reasoning 和 tool calls 不寫入檢查點,圖片輸出直接拒絕;含包裝的摘要估值必須小於被替換舊區間的估值。

任何一關不過,摘要都到不了模型面前。到影片 7:56 處看
替換、重放與邊界
- 10
日誌只附加,模型檢視被替換
成功之後,持久日誌附加 start、summary、checkpoint、end 一串事件,而模型可見歷史透過一次表層替換換新——畫面裡畫的是 surfaceOp 的替換操作:檢查點在前,保留下來的近期原文在後。上游什麼都沒刪,日誌仍是完整記錄。
$surfaceOp: { op: 'replace' }$compaction/start · summary · end
日誌只增不減,被換掉的只是模型檢視。到影片 8:48 處看 - 11
回復靠重放日誌
因為日誌只附加且完整,回復從不需要原始上下文:按事件順序讀回,逐條套用 surfaceOp 的 append 或 replace,模型檢視就重建出來了——舊內容、檢查點、近期原文各歸其位。被壓縮過的會話能撐過重啟,靠的就是這個。
$surfaceOp: append / replace
回復就是對只附加日誌的確定性重放。到影片 9:05 處看 - 12
收束:介面穩定,實作可換
結尾頁把整條流水線收成四個動作——測量壓力、裁剪工具結果、按需摘要、替換模型檢視——並劃清分工:ctx.compaction 保持穩定,compaction-basic 是目前預設實作,agent loop、token meter 和 /compact 入口環繞在外。每一塊都能獨立演化而不牽連其他。

四個動作、一個穩定介面、一個可替換實作。到影片 10:00 處看
看儀表:實際介面裡的 Token usage
前面講的都是機制,這裡是它落地後的樣子。下面兩張截圖取自 AISeeKing 的週更實測(錄製時為 0.1.5-rc.1 開發者預覽版,介面文案可能與目前版本略有出入):一次累計 300 萬 token 的執行結束後,Token usage 彈窗列得清清楚楚——快取命中 99%、未命中輸入 33,671、命中輸入 2,931,968、輸出 50,350。視窗保持穩定、只追加不重寫,重複的前綴就會持續命中快取——壓縮機制的回報就反映在這塊儀表上。


對應官方 0.1.7 的部分
這頁拆的是外掛流水線,而官方 0.1.7 系列正從產品側打磨同一處接縫——alpha 更新說明寫明為主動壓縮保留輸出容量與上下文餘裕,長指令逾時後可轉入背景繼續跑。想算清這些長時間任務的實際開銷, 看這份 token 用量與成本追蹤指南.
內建 compaction-basic 套件與 headroomTokens
0.2.x 系列把壓縮做成內建套件——packages/compaction/compaction-basic——這個官方套件名本身也成了搜尋詞。兩個旋鈕最關鍵。先是自動開關:按官方討論 #8774 給出的設定名,背景觸發器是 compaction-basic.auto,把它關掉就停用自動摘要,/compact 仍可手動隨時用。
第二個旋鈕是 headroomTokens,即為摘要預留的空間。官方討論 #8785 記錄了它的毛邊:預設值 65,536 不會隨視窗縮小而縮放,在短上下文模型上,這筆預留本身就可能擠佔它要保護的歷史——小視窗請明確設定。如果你更想抬高天花板而不是調預留,tyan66666/billion-context-dsh(★124)是社群給出的答案。
上下文管理與壓縮工具:內建與社群三支橫評
前文拆的壓縮流水線是內建機制。圍繞它長出了一小圈上下文管理外掛:把視窗構成看清楚的儀表板、替代壓縮引擎,還有硬天花板守衛。下方星數於 2026-10-08 經 GitHub API 實查——每一支都請對照它們所擴充或取代的內建 compaction-basic 來衡量。
基線:內建 compaction-basic
就是本頁拆掉的預設實作:三觸發(80% 預檢、伺服器溢出、手動 /compact)、8192 碼點工具結果裁剪、16% 近期原文保留、檢查點替換加重放。它隨 dsh 內建、無需安裝——把它當參照系,下方每支社群工具都是對它做的調整;先確認它運作正常,再往上疊東西。
bowenliang123/dsh-context(★1,892)——先看見上下文
斷層領先的簇頭牌:Context 面板、瀏覽器與側邊欄加一條 context 命令,把視窗的真實構成拆開看——統計、組成,以及壓縮與剪枝事件的演進。它自己不做壓縮,是觀測層,告訴你內建壓縮做得怎麼樣。這一節只裝一支的話,裝它。
yoza10635/dsh-argp(★9)——可稽核的壓縮
另一顆引擎、另一份契約:LLM 只提議,確定性守衛裁決。逐原子收縮帶逐字守衛、零模型呼叫的惰性參照圖剪枝、附加式日誌逐位元組召回——承諾的壓縮率精確兌現,歷史永不銷毀。當你對摘要的懷疑多過信任時,選它。
AllShadowAnan/dsh-context-compressor(★0)——絕對天花板
三支裡最年輕的一支:在專屬設定頁設一個上下文絕對上限,會話一碰到這條線就自動壓縮——一個不依賴 80% 預設門檻的硬停。為「真實視窗比標稱小」的模型而生,這正是下面 FAQ 拆解的那類故障。
記憶與上下文一側的更多精選——知識圖譜、跨會話召回、上下文工程——見 記憶與上下文合集.
dsh 壓縮的兩種觸發:自動壓縮與手動 /compact(0.2.1-alpha.3)
0.2.1-alpha.3(alpha 通道,2026-10-14 發布)把壓縮升級成一等命令:Web 與桌面端可用 /compact 手動壓縮目前對話,極簡模式還會自動壓縮長對話(並支援讀取圖片)。底下跑的還是本頁拆過的那條管線——同樣的裁剪、同樣的檢查點、同樣的替換重放——只是觸發權從壓力計交到你手裡。
版本核對:alpha.3 掛在 npm 的 alpha 標籤下,stable latest 仍是 0.2.0-rc.2——如果你的 Web/桌面端還沒有 /compact 這條命令,原因就在這。本頁其餘內容(門檻、裁剪、重放)講的是 stable 已內建的 compaction-basic 套件,它在 agent 閒置時的手動觸發見第 3 步。
什麼時候值得手動壓一次:往已經很重的工作階段裡餵長文件之前;一波工具密集、逐字記錄已經沒用的操作之後;或用量表早就顯示壓力不小、而約 80% 的自動觸發還遙遙無期的時候。
討論區實測帳本:壓縮的真實成本與故障樣態
官方討論區把壓縮從一份設計變成了一本帳。下面每一條就是一個實測發現加討論串編號——原始報告都在 deepseek-ai/deepseek-harness 儲存庫的 Discussions 標籤頁裡。
#9629 —— 一次壓縮白燒約 25 萬未快取 token
壓縮摘要請求建構時沒帶工作階段的 reasoningEffort,快取鍵與前後主請求不同——偏偏是重讀整個視窗的這一發打不進快取。回報者環境(opencode-go 路由、kernel 0.1.7-rc.2)下,等於每次壓縮多付約 25 萬本可避免的未快取 token。
#9643 —— 每輪動態注入打穿 KV 前綴快取
每輪注入的內容(記憶、上下文類外掛)排在對話歷史之前,提示詞前綴永遠對不上上一輪請求。本地 LM Studio 引擎實測 KV 前綴重用率恆為 0,每輪對 9 萬–14 萬 token 全額重算 prefill;報告建議把注入挪到提示詞尾部。跑本地模型、疑惑 GPU 時間為何爆炸的,先看這則。
#9404 —— 視窗才 40% 就開始自動壓縮死循環
0.2.1-alpha.2 加本地 llama.cpp 模型(96k 視窗):約 3.79 萬 token(約 40%)時自動壓縮啟動,隨後連續重觸發,壓縮記錄洗版,對話無法推進。
#9544 —— 超過模型視窗的工作階段就此報廢
長跑工作階段一旦超出模型視窗,之後每一輪都回傳 400:重啟全量重放表面、壓縮陷入死鎖、排程任務靜默失效——產品內沒有任何復活手段。
#9635 —— 上下文溢出且沒有手動恢復路徑
alpha.2 上的三連故障:token 低估、摘要器自己的重放又撐爆視窗、且沒有手動恢復手段——工作階段永久不可用。加上 #9404 與 #9544,壓縮行為異常時先對照這個死循環三連。
常見問題
觸發、遺失與上限——畫面本身說不清的部分。
壓縮是怎麼觸發的?會不會打斷我正在跑的任務?
三個入口:請求前預檢(預設 80% 門檻)、伺服器端超窗回復、以及閒置時手動 /compact。觸發點都在請求之間,不會攔腰打斷正在產生的回合;/compact 在 agent 忙碌時會提示暫不可用,你排隊送出的訊息等它跑完再繼續。
壓縮之後上下文會不會不見?
舊回合的原文會離開模型視野,但不是憑空消失:它們被整理成涵蓋目標、檔案、錯誤、待辦的結構化檢查點;最近約 16% 視窗原文保留;持久日誌裡每個原始事件都還在。失去的是模型對舊原文的直接引用,不是記錄本身。
8192 碼點裁剪,會不會把重要的工具輸出砍斷?
有可能,這是設計取捨:裁剪器只認位置不認語意,保留開頭和結尾,中段一律換成標記。好處是確定性——絕不把 emoji 之類的代理對切壞;代價是語意上重要的中段內容,要靠你自己在必要時重跑指令取回。
這些數字是寫死的嗎?
不是。80% 是 thresholdRatio 預設值,16% 是 retainRatio 預設值,都能按供應商和模型分別設定;裁剪器的 8192/4096/1024 碼點預算同樣可設定。本文數值以 2026-09-23 官方儲存庫文件為準——把它們當目前預設值,不是常數。
長時間任務還是被截斷了,壓縮救不了怎麼辦?
壓縮救的是會話太長,救不了單件超大產物:系統提示、工具定義、會話前置段落壓不動,一條巨大的工具呼叫也不會被拆開。這種情況把任務拆小,或轉給子代理、背景任務去跑,讓主會話只收結論。
怎麼關閉自動上下文壓縮?
把 compaction-basic.auto 設為 false——這是官方討論 #8774 給出的設定名,該帖同時提議在 Web GUI 加一鍵開關。關閉後背景自動摘要停用,/compact 仍可手動觸發。順手檢查 headroomTokens:預設 65,536 不隨視窗縮小(#8785),在短上下文模型上這筆預留本身就能製造壓力。注意代價:沒有自動壓縮,長會話會更貼近溢出閾值——一旦越過,結束對話的是服務商,不是 dsh。
壓縮怎麼一發再發——無限循環了?
症狀:一輪壓縮剛結束,下一個請求又壓一遍,循環從不停下。機制級報告見官方討論 #9041:當某條路由宣告了異常大的 maxTokens,自動觸發的門檻算術會坍縮,每一輪都被判為超壓,自動壓縮永久重跑。修復落地前的繞行:調低該路由宣告的 maxTokens,或把任務挪到數值正常的路由;用 compaction-basic.auto: false 關掉背景觸發,需要時手動 /compact;保留附加式日誌——無論循環與否,重放恢復照常運作。
壓縮壓根不觸發——然後服務商把會話拒了,為什麼?
這是官方討論 #9022 記錄的靜默失效:某模型宣告的 contextWindow 沒有進入 dsh 的模型資訊解析器。壓力估計永遠過不了門檻,自動壓縮從不啟動,第一個可見徵兆是閘道的上下文溢出拒絕套著一層籠統的報錯。先確認模型的上下文視窗確實註冊上了(換模型指南講了解析鏈路),應急時手動 /compact,長會話突然 400 時先按溢出讀、再按額度讀。
上下文滿了該怎麼辦?需要遷移對話嗎?
官方討論 #9071 的原問。短答:不需要遷移。dsh 每個請求前檢查壓力,逼近上限就會壓縮——舊輪次變成結構化檢查點,近期尾部逐字保留,附加式日誌什麼都在,會話原地續命。如果會話已經被上面的無限循環或靜默失效卡死:趁 Agent 閒置敲 /compact,或者新起會話讓檢查點把結論帶過去;真要把原始會話檔挪走,匯出工具隨時可用。
Web UI 裡的「Cache hit」百分比是什麼?
這個膠囊報告你的輸入有多少命中了服務商的提示快取、不用按全價重算——上文 Token usage 截圖就是 99% 的例子,輸入、快取讀/寫、輸出分桶列示。快取讀按新鮮輸入的一小部分計費,命中率高就是你察覺不到的最便宜提速。各 provider 語意不同:本地 Ollama 端點可能給不出有用數字,DeepSeek 閘道則單獨列快取——官方討論 #9091 正是為這顆膠囊要文件的帖子。壓縮與它互相影響:穩定前綴持續命中,重寫歷史就會清零重算。
什麼時候該手動 /compact,而不是等 dsh 自動壓縮上下文?
三個時機:往已經很長的工作階段裡塞已知的大塊內容(長需求文件、大檔案傾印)之前;一波工具密集、逐字輸出已經沒用的忙碌之後;用量表壓力早就很高、而約 80% 的自動觸發遲遲不來時。手動壓縮走的是同一條濃縮管線,不會多丟東西。注意:Web/桌面端的 /compact 命令本身是 0.2.1-alpha.3(alpha 通道)的新功能;stable 上 compaction-basic 仍支援 agent 閒置時的手動觸發,見上文第 3 步。
為什麼壓縮之後費用反而變高了?
壓縮省的是視窗空間,不一定是錢。兩條實測機制在反向發力:#9629——摘要請求的快取鍵不同(沒帶 reasoningEffort),每次壓縮把整個視窗按約 25 萬未快取 token 重讀一遍;#9643——每輪動態注入排在歷史之前,本地引擎的 KV 前綴快取完全失效,每輪都要全額重算 prefill。帳單總在壓縮事件附近跳的,先對照這兩則。
相關攻略
DSH 學習路線裡的相鄰課題。
DeepSeek Harness Token 用量與成本追蹤
壓縮省了多少,量出來才算數:會話內、日誌裡、供應商帳單頁三處對帳。
閱讀教學DeepSeek Harness 四種模式比較
standard、code(PTC)、cordis 三個 Web 預設共用同一套壓縮組合,其餘差異看這篇。
閱讀教學DeepSeek Harness 疑難排解手冊
超窗錯誤、壓縮重試這些長會話常見故障,一次到位的修法。
閱讀教學DeepSeek Harness 子代理實戰指南
一個上下文不夠用時:把長時間任務拆給子代理和背景任務,別硬撐單執行緒。
閱讀教學dsh TUI 終端機上手
ask_user_question 與背景任務同屏的終端機,長時間任務掛背景的理想搭檔
閱讀教學dsh 系統提示詞是怎麼拼出來的
上下文的另一半:每一輪系統提示詞的組裝順序,以及改寫它的外掛
閱讀教學視覺化你的 dsh 上下文視窗
dsh-context 外掛實錄:構成模態框、逐請求趨勢圖,以及給上下文每個組成部分標價的請求瀏覽器。
閱讀教學來源與署名
全部 13 張畫面擷取自同一支影片——旁白講解的機制示意動畫,非官方產品介面、非實機錄影;每張圖都可深鏈回原片對應秒數。同一支拆解在 YouTube 由 01Coder、在 Bilibili 由 五里墩茶社 發布(同一作者:小木頭)。
