前言¶
在 DeepSeek Harness(DSH)裏,工具返回帶圖片的結果時,dsh-spill-policy 會依據 LLM 適配器提供的 imageRequestPricing 估算圖片佔用的 token,再與 maxInlineTokens 比較,決定是否把過大的 base64 內聯內容移出請求。默認情況下 LlmAdapter.imageRequestPricing() 返回 undefined,只有 dsh-llm-deepseek 實現了該方法;走 @deepseek-ai/dsh-llm-pi-ai 的路由沒有實現,spill-policy 在取不到計算器時會拋錯並被外層捕獲,日誌裏出現「keeping the inline content」,整段大圖仍 inline 發給模型,容易撐爆上下文。dsh-token-meter 也會退回到固定結構啓發式,而不是按實際發送的字節計價。
下面介紹社區插件 dsh-llm-pi-ai-image-offload(維護者 ender-candle),它在適配器實例上補回 imageRequestPricing,讓 spill-policy 能按字節估算視覺 token 並 offload 超大圖片。
這是什麼¶
dsh-llm-pi-ai-image-offload 是 DSH 的 Cordis 插件包(npm 名 dsh-llm-pi-ai-image-offload,版本 0.1.0,MIT)。定位是:爲未聲明圖片計價的 pi-ai 適配器路由安裝 imageRequestPricing,並在每次 llm/adapters-updated 時重新應用。這裏的「pricing」指 token 覈算,不是計費。插件零運行時依賴,分類上屬於模型推理相關能力;在 SkillHub 插件目錄 可查到條目(社區站點,與 DeepSeek / 幻方無官方從屬關係)。
它修復的問題¶
當工具結果攜帶圖片時,spill-policy 會調用:
const calculator = ctx.get("llm")?.imageRequestPricing(provider, model);
if (calculator === undefined) throw new Error("the current model has no image token calculator");
pi-ai 路由沒有 override 該方法,上述邏輯失敗後被插件外層 try 喫掉,工具結果保持完全 inline,多兆字節的 base64 會原樣進入 provider 請求。裝上本插件後,無計價的適配器實例會得到基於傳輸字節的估算,spill-policy 才能與 maxInlineTokens 對齊並 shed 放不下的圖片。
核心行爲¶
- 對返回「無圖片計價」的適配器實例掛載
imageRequestPricing;已有真實實現的適配器不會被覆蓋(上游修復後本補丁會自動失效)。 - 若某適配器自己的實現會 throw,則不會被替換。
- Offload 不會從會話或工作區刪除文件;模型會收到 spill-policy 的說明和可再通過
read_image讀取的路徑。
計價公式(路由未發佈 vision-token 賬時,按實際傳輸字節計):
transmitted = min(attachment.bytes, imageRequestTarget(...).maxBytes)
visualTokens = ceil(base64Length(transmitted) / charsPerToken)
其中 base64Length(b) = ceil(b / 3) * 4,與 harness 的字節換算一致。README 給出的失敗案例:2048×2048 JPEG 約 1,266,320 字節、請求預算 1 MiB 的路由上,截斷後 base64 約對應 349,526 tokens,高於默認 maxInlineTokens: 12500,因此應被 shed。
配置¶
字段均可選,通過 profile 裏該 bundle 的 config 傳入:
| field | default | meaning |
|---|---|---|
enabled |
true |
關閉整個補丁 |
charsPerToken |
4 |
每個 token 對應的 base64 字符密度 |
maxVisualTokens |
400000 |
單次圖片 occurrence 的上限 |
providers |
(all) | 允許的 provider route id 白名單 |
debug |
false |
向 harness logger 記錄每條被 patch 的路由 |
示例(profile patch 片段):
- id: llm-pi-ai-image-offload
name: dsh-llm-pi-ai-image-offload
config:
debug: true
安裝與啓用¶
先從 GitHub 安裝到指定 profile(推薦):
dsh plugin --profile <profile> add github:ender-candle/dsh-llm-pi-ai-image-offload
需要可復現安裝時可 pin commit:
dsh plugin --profile <profile> add github:ender-candle/dsh-llm-pi-ai-image-offload#<sha>
本地 checkout 路徑安裝:
dsh plugin --profile <profile> add /absolute/path/to/dsh-llm-pi-ai-image-offload
dsh plugin add 會更新 profile 的 package.json 與 pnpm-lock.yaml。接着在 profile 的 package.json 裏把 bundle 名加入 dsh.profile.bundles:
{
"dsh": {
"profile": {
"bundles": ["...", "dsh-llm-pi-ai-image-offload"]
}
}
}
包內 cordis.patch.yml 會自動插入 host 行,一般無需手改 patch。重啓 harness 後 bundle 在啓動時加載。
如何確認已生效¶
Harness logger 使用內存 ring buffer,事後未必能看到 warn。README 建議:debug: true,再生成一張大圖觸發 spill,在 session log 中查找 image/offload 事件;未打補丁前該信號不會出現。
本地可跑單元測試(18 項,無額外依賴):
node test/offload.test.mjs
適用場景與注意¶
- 適合:使用
@deepseek-ai/dsh-llm-pi-ai路由、工具結果常帶大圖 base64,且已啓用dsh-spill-policy的 DSH profile。 - 權限與安全:插件與當前 dsh 進程同權限運行;安裝前請閱讀 GitHub 倉庫 源碼與 MIT 許可證。
- 風險(README 原文):
LlmAdapter實例字段不是文檔化的擴展點;registry 形狀變化時補丁可能靜默失效(行爲回到補丁前)。對上游按 vision 分詞的路由,估算可能偏多,這是保守策略,只會更早觸發 shed;provider 返回的usage仍是權威計量。
結尾¶
dsh-llm-pi-ai-image-offload 用很小的補丁把 pi-ai 路由缺失的 imageRequestPricing 補回來,讓 spill-policy 和 token 預算邏輯重新能處理超大 inline 圖片,避免上下文被 base64 佔滿。
- 目錄頁:https://www.skillhub.cn/plugins/ender-candle/dsh-llm-pi-ai-image-offload
- 源碼與中文 README:https://github.com/ender-candle/dsh-llm-pi-ai-image-offload