用 DeepSeek-Harness-Vision-Tools 給純文本 dsh 接上眼睛

前言

DeepSeek Harness(dsh)的核心理念是「一切皆插件」:模型、工具、會話、沙箱和界面都可以換。官方倉庫是 deepseek-ai/deepseek-harness。日常驅動它的,往往是 DeepSeek、稠密 Qwen、Llama、Mistral 這類純文本模型

把截圖貼進對話時,會撞上兩堵牆。第一堵在發送前:dsh 按路由聲明的模態檢查附件,文本模型會被直接拒絕,並點出模型名。第二堵更麻煩:如果在文本路由上硬寫 input: [text, image],附件能發出去,但上游會在回合中途返回 400 "not a multimodal model"——此時用戶消息已經落盤,會話會反覆重試一個永遠成功不了的請求。

只加一個「看圖工具」也解不開第一扇門:模型要先看見圖片,纔會決定去調工具,而那正是 dsh 拒絕的請求。社區維護者 tonyd2wild 因此做了 DeepSeek-Harness-Vision-Tools:文本模型繼續當大腦,視覺模型只負責看,圖片字節不到大腦上下文裏。本文按插件目錄頁、GitHub README、examples/dsh.md 和倉庫源碼覈對後整理。

這是什麼

DeepSeek-Harness-Vision-Tools 是一款會話與消息類社區插件,由 tonyd2wild 維護,許可證 MIT。目錄頁與 GitHub 均標註 10 stars;目錄收錄日期爲 2026-08-10,倉庫最近推送時間爲 2026-08-13。插件包名是 dsh-plugin-visionpackage.json 中的版本爲 0.1.0

README 開頭寫明:這是非官方社區項目,與 DeepSeek AI 無隸屬、無背書、非其維護。問題請開到本倉庫,不要報到 DeepSeek。社區插件目錄 deepseek-harness-plugin.com 是獨立站點,也不是 DeepSeek / 幻方的官方應用商店。

它解決的問題可以縮成一句:任意文本模型搭配任意視覺模型,給 dsh 兩條進圖通道。

入口 機制 誰觸發
聊天裏附上的圖片 視覺代理 shim/vision_shim.py 自動攔截,模型到達前改寫
磁盤上的圖片文件 analyze_image 工具 plugin/vision/ 智能體按需調用

兩條通道互補,不是主備關係。工具接不住聊天附件:附件必須先到模型,模型纔會去調工具。代理也撿不起智能體還沒放進消息的磁盤文件。圖片只發給視覺模型;大腦看到的是 [Image: ...] 這類文字。

核心功能

大腦和眼睛分開,兩端都由你選

倉庫刻意不寫死模型。維護者自己的 DeepSeek 構建和硬件組合別人很難複用,所以配方只留兩個槽位:

槽位 放什麼 建議
大腦(文本) dsh 已經在跑的任意 OpenAI 兼容文本模型 沿用現有模型
眼睛(視覺) 代理和/或工具去調的本地 VLM fast / detailed 分檔

同一套眼睛可以服務兩扇門。工具按調用選擇後端;代理通過 --vision-model 指定一個:

角色 適用 倉庫舉例
fast(默認) 顏色、版面、粗內容 約 0.8B 的小 VLM,如 Qwen3.5-0.8B
detailed 小字、細部、偏 OCR 的工作 更大的 VLM,如約 27B 的 Qwen2.5-VL / Qwen3-VL

MODELS.md 給出的 fast 默認是 Qwen3.5-0.8B:Apple Silicon 走 MLX(mlx-community/Qwen3.5-0.8B-MLX-8bit),Windows / Linux / NVIDIA 走 llama.cpp(GGUF + mmproj)。活體佔用大約 Mac 統一內存 2–3 GB,或 PC 約 2 GB 顯存。不一定兩檔都開,先跑 fast 即可。

Ollama 目前還不能加載 Qwen3.5 的獨立 mmproj,默認 fast 模型不能走 Ollama。若堅持用 Ollama 一行命令,倉庫建議改 Moondream 或 Qwen2.5-VL,再把後端指到 http://127.0.0.1:11434/v1/chat/completions

視覺代理:聊天附件在到達大腦前變成文字

代理是一個只依賴 Python 標準庫的本地 HTTP 服務,對外說 OpenAI API,夾在 dsh 和文本上游之間:

  1. POST /v1/chat/completions:把每條消息裏的 image_url 塊換成 {"type":"text","text":"[Image: ...]"};若整條消息都變成文本,再收成普通字符串(有的服務器對 block 數組更挑剔)。
  2. GET /v1/models 以及其他 GET 原樣轉發,方便 dsh 做模型發現。
  3. 流式響應按字節轉發。dsh 每個回合都在流式輸出,緩衝會卡住界面。
  4. 視覺失敗時降級,不拋死:塊變成 [Image: (image could not be analyzed: ...)],回合仍能結束。
  5. 請求體上限 64 MB,因爲圖片是 base64 內聯的。

dsh 的模型路由要指向代理,並聲明 input: [text, image]。這句話對代理爲真,對文本大腦爲假。路由描述的是它正在對話的對象。

analyze_image:磁盤文件由智能體決定何時看

plugin/vision/index.js@deepseek-ai/dsh-toolsdefineTool() 註冊模型可見工具。參數來自源碼:

參數 是否必填 含義
path 要分析的圖片路徑
backend fastdetailed(以掛載時實際配置爲準)
prompt 問視覺模型的問題,默認 "Describe this image in detail."

工具把文件讀成 base64,POST 到對應後端的 /v1/chat/completions,把返回的純文本寫進工具結果。未知後端會拋錯並列出合法名稱,沒有靜默回退,避免把 detailed 打成 fast 卻看不出來。

讀文件優先走 ctx.fs(遵守工作區邊界和審批策略)。若退化到 readFileSync,會繞過沙箱,模型理論上能通過這個工具讀盤上任意文件。倉庫要求:只在受信任、有人值守的機器上依賴這條回退,無人值守前先把門閂上。

安裝與啓用

插件目錄頁給出的安裝命令如下,在 DeepSeek Harness 終端執行:

dsh plugin add github:tonyd2wild/DeepSeek-Harness-Vision-Tools

目錄頁同時寫了可復現寫法:把 commit 哈希接到倉庫名後面。

dsh plugin add github:tonyd2wild/DeepSeek-Harness-Vision-Tools#commit

插件以當前 dsh 進程的權限運行,安裝時可能執行代碼。安裝前應檢查源代碼倉庫和許可證。

這個倉庫不是「只丟一個 JS 插件」那麼簡單:代理是獨立 Python 進程,工具在 plugin/vision/。要兩扇門都工作,需要按 README 把眼睛服務、代理和工具分別拉起來。前置條件(README「What you need」):

  • 已有 dsh 在跑的文本模型(任意 OpenAI 兼容端點)
  • 一臺本地 VLM;最小的 fast 檔大約還要 2–3 GB 餘量
  • Python 3.8+(代理只用標準庫,零第三方依賴)
  • pnpmdsh plugin 會調它;只裝工具時需要)
  • 視覺運行時:Mac 用 MLX(mlx-vlm),Windows / PC 用 llama.cpp(或 Ollama 跑回退模型)

快速起步:

git clone https://github.com/tonyd2wild/DeepSeek-Harness-Vision-Tools
cd DeepSeek-Harness-Vision-Tools
cp .env.example .env      # 把端點改成你自己的主機
./setup.sh                # 拉起本地視覺服務(RUN_PROXY=1 時連代理一起起)

門 1,代理(聊天附件):

python3 shim/vision_shim.py --port 8900 \
  --upstream http://127.0.0.1:8000 \
  --vision-url http://YOUR_FAST_VISION_HOST:8081/v1/chat/completions \
  --vision-model your-fast-vlm

環境變量與 CLI 一一對應,CLI 優先:SHIM_PORT / --portVISION_TARGET / --upstreamEYES_URL / --vision-urlEYES_MODEL / --vision-model。健康檢查:

curl http://127.0.0.1:8900/health

門 2,工具(磁盤文件)。先把插件拷到穩定路徑,並按倉庫「陷阱 2」改 package.json@deepseek-ai/dsh-toolslink:,指向當前 Harness 自帶的那一份,不要裝 npm 上的舊包(文檔寫的是 npm 上的 0.0.1-rc.1 比 Harness 自帶的 0.1.0-rc.6 更老,而且會去引一個從未發佈的包):

cp -r plugin/vision ~/.dsh/plugins/vision
dsh plugin --profile <p> add link:~/.dsh/plugins/vision

<p> 換成實際 profile,例如 webheadless。插件從 profile 目錄解析,不要丟進安裝目錄的 node_modules,否則所有 profile 啓動都會 ERR_MODULE_NOT_FOUND。每個要用的 profile 都要加一次。

典型用法

把一條 dsh 路由指到代理

模型路由寫在 $DSH_HOME/settings.yaml 的 pi-ai 提供方塊裏。baseURL 指向代理,並聲明圖文輸入。下面是 examples/dsh.md 的佔位配置,主機和模型 id 換成你的:

llm-pi-ai:
  providers:
    vision-proxy:
      displayName: Your Text Model (via vision proxy)
      apiKeyEnv: YOUR_PLACEHOLDER_KEY_ENV
      api: openai-completions
      baseURL: http://127.0.0.1:8900/v1
      models:
        - id: your-text-model-id
          contextWindow: 262144
          maxTokens: 32768
          input: [text, image]

無密鑰的上游也要填 apiKeyEnv,指向任意非空環境變量。省略的話 pi-ai 會去做環境發現,找不到就報 PI_AI_ERROR: No API key

再留一條直連上游、不聲明 input 的後備路由,代理掛了還能繼續幹活:

    text-only-direct:
      displayName: Your Text Model (direct, no vision)
      apiKeyEnv: YOUR_PLACEHOLDER_KEY_ENV
      api: openai-completions
      baseURL: http://127.0.0.1:8000/v1
      models:
        - id: your-text-model-id
          contextWindow: 262144
          maxTokens: 32768

模型路由熱加載,不用重啓。保存後在模型選擇器裏選代理那條,附上一張圖即可。

analyze_image 配兩個後端

在插件配置塊或環境變量裏寫:

export VISION_FAST_URL=http://YOUR_FAST_VISION_HOST:8081/v1/chat/completions
export VISION_FAST_MODEL=your-fast-vlm
export VISION_DETAILED_URL=http://YOUR_DETAILED_VISION_HOST:8010/v1/chat/completions
export VISION_DETAILED_MODEL=your-detailed-vlm

智能體調用形態是 analyze_image(path, backend, prompt)。例如對截圖或票據覆蓋提示詞:prompt: "List every object and any visible text."

Web 表面上,面向模型的工具行在宿主層是關掉的,要靠 agent preset 才能看見。不要去改隨安裝分發的 standard preset,升級會被覆蓋。建一個新 id 的用戶 preset(例如 standard-vision),組合 webanalyze_image。用戶 preset 不能複用已分發的 id,否則會被靜默遮住。然後在 settings.yaml 裏設默認(熱加載):

agent-presets:
  default: standard-vision

Preset 第一次開會話才掛載。看乾淨啓動日誌不能證明工具在;要開一場真實會話。

告訴智能體:它並沒有變成多模態模型

dsh 會把 $DSH_HOME/AGENTS.md 讀進每場會話。代理生效後,模型常會推斷自己被切到了視覺路由。倉庫提供了一段可粘貼說明,核心是:你仍是原來的文本模型;圖已經被代理或工具寫成了 [Image: ...];請說「描述表明……」,不要說「我能看見……」。

倉庫給出的端到端覈對方法

文本模型拿到圖片塊時,會編一段看起來合理的描述,讀起來像成功。倉庫用模型猜不到的純色圖做過觀察:

  • 非流式:純綠 → “The image is a solid, bright green.”
  • 流式:純藍 → “a solid, uniform field of deep, saturated blue”(5 個 chunk,乾淨的 [DONE]
  • 同一套文本模型,直接塞圖片會返回 400 "is not a multimodal model",用來證明字來自代理的視覺腿,不是大腦

復現方式:生成幾張純色 PNG,聊天裏附一張問顏色(代理路徑),或讓 analyze_image 指向文件(工具路徑),覈對描述是否對得上。

適用場景與注意事項

適合:希望保住現在這顆文本大腦,又要讓 dsh 對截圖、照片、攝像頭幀有情境感知的人。倉庫原話是:它附加能力,不接管部署;代理是獨立進程,隨時可殺;工具只是多一個智能體可以調用的能力。

不適合當成原生多模態。倉庫「Honest limits」寫得很直:

  • 描述是有損的。細部、精確空間關係和小物體可能丟。版面推理請換更大的 detailed 模型。
  • 小 VLM 讀圖中文字弱。fast 用體積換精度。OCR 重的工作把代理或工具指到更大的 VLM,並接受額外內存和延遲。
  • 大腦推理的是字,不是像素。多數智能體工作(屏幕上有什麼、照片裏是什麼、讀一條報錯)夠用;關鍵 OCR 或細粒度視覺推理不夠。
  • input: [text, image] 是聲明,不是檢查。只對真正收圖的端點聲明:代理,或真正的 VLM。寫在純文本模型上,會在消息落盤後中途 400。

另外幾條來自 examples/dsh.md 的坑:

  1. llama.cpp 路徑必須帶 --mmproj(視覺投影器)。backends/pc_llamacpp.sh 會自動傳。漏了的話 llama.cpp 會靜默按純文本跑,描述全是空話。這是最常見的「進程在跑但看不見」。
  2. Windows 絕對路徑在 preset 裏可用,在 profile patch 裏會把 C: 當成 URL scheme,報 ERR_UNSUPPORTED_ESM_URL_SCHEME。兩邊都用裸包名更穩。
  3. settings.yaml(模型路由、默認 preset)不用重啓;改 preset 的 agent.cordis.yml 也不用,下場會話按文件時間戳換代;改插件 index.js 要重啓(ESM 按進程緩存);代理本身只重啓代理進程,dsh 不受影響。

若文本大腦跑在 DGX Spark 上,倉庫認爲 fast 視覺模型大約 2–3 GB,通常可以和大腦放在同一臺機器,把 --vision-url 指到 127.0.0.1。Spark 上報的「空閒」內存會高估 CUDA 實際可用量(GPU 與 CPU 共用一塊池);小 fast 多半放得下,大 detailed VLM 未必。先確認服務起來再依賴。

持久化方面:代理可用 autostart/ 裏的 Windows 登錄腳本(.vbs)或 Linux systemd user unit;工具靠上面的用戶 preset。兩者獨立。

小結

DeepSeek-Harness-Vision-Tools 做的不是把 dsh 換成多模態模型,而是在聊天附件和磁盤文件兩條入口上,把「看」交給本地視覺模型,把「想」留給原來的文本模型。目錄頁安裝命令是 dsh plugin add github:tonyd2wild/DeepSeek-Harness-Vision-Tools;真要兩扇門都通,還要按 README 起視覺服務、代理,並按 profile 用 link: 掛上 plugin/vision

安裝前請閱讀源碼和 MIT 許可證。插件以當前 dsh 進程權限運行。問題請開到本倉庫,不要報到 DeepSeek。

  • 插件目錄:https://deepseek-harness-plugin.com/zh-CN/plugins/deepseek-harness-vision-tools/
  • GitHub:https://github.com/tonyd2wild/DeepSeek-Harness-Vision-Tools
  • 集成說明:倉庫內 examples/dsh.md
  • DeepSeek Harness 官方倉庫:https://github.com/deepseek-ai/deepseek-harness
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜