dsh-vision-plugins

August 14, 2026 · View on GitHub

DeepSeek Harness(dsh web)的委托式识图插件对:让纯文本主模型(如 deepseek-v4-flash)也能"看图"——聊天框直接粘贴/上传图片会自动调用视觉模型(默认 mimo-v2.5)识别,图片从不进入主模型上下文;主模型是原生多模态模型时则图片直通、原生识别。

解决的问题

DSH 的请求层有两道闸门:

  1. apiproxy 发送闸门:当前模型未声明 image 输入模态时,带图消息直接被拒(MODEL_DOES_NOT_SUPPORT_IMAGES);
  2. LLM 适配器:请求内容含图片而模型未声明 image 输入时抛 UNSUPPORTED_CONTENT

纯文本模型(deepseek-v4-flash / deepseek-v4-pro 等)本身不接收图片,所以"粘贴图片"和"模型读图"在原生 DSH 里都不可用。本插件对在模型与网关之间加了一层自动委托:

用户在聊天框粘贴图片
  → 发送闸门放行(设置里给纯文本模型声明 input: [text, image])
  → vision-inline 在 agent/pre-step 钩子接管
  → 读取附件 → mimo-v2.5 详细识别
  → 图片块替换为文字描述(【用户上传的图片,已由视觉模型识别】…)
  → 主模型拿描述继续推理

按模型能力自动分流

判断依据是 pi-ai 模型目录(opencode-go.json)的原生 input 模态,不受 settings.yaml 里为过闸门声明的 input 影响:

主模型粘贴图片read_image 工具
纯文本(deepseek-v4-flash/pro、qwen3.7-max、glm-5.x、hy3、mimo-v2.5-pro、minimax-m2.7)自动转视觉模型文字描述被守卫拒绝(防网关报错)
原生多模态(mimo-v2.5、qwen3.7-plus、minimax-m3、kimi-k2.6/k2.7/k3、qwen3.6-plus、grok-4.5)图片直通模型,原生识别可用
未知模型按纯文本处理(安全兜底)被守卫拒绝

文件

文件作用
plugins/vision-tool.mjs模型可调用的 vision 工具:给定图片路径,用视觉模型识别并返回文字描述(用于"帮我看看 <路径>"场景)
plugins/vision-inline.mjs自动发图识图:agent/pre-step 钩子里把消息中的图片块替换为视觉模型描述;按模型能力分流;注册 read_image 守卫
install/cordis.patch.insert.yml挂载两个插件到 profile 补丁的 insert 片段
install/settings.model-input.snippet.yamlsettings.yaml 中给纯文本模型声明 input: [text, image] 的示例
examples/vision-test.html测试图源文件(渲染成 PNG 后可用于验证)

安装

~/.dsh 为 DSH home、web profile 为例(dsh web / DeepSeek Harness Desktop 通用):

  1. 复制插件到 profile 目录:

    cp plugins/vision-tool.mjs plugins/vision-inline.mjs ~/.dsh/profiles/web/
    
  2. 挂载插件:编辑 ~/.dsh/profiles/web/cordis.patch.yml,把 install/cordis.patch.insert.yml 里的 insert 块追加进去。

  3. 声明图片输入:编辑 ~/.dsh/settings.yaml,给纯文本主模型(如 deepseek-v4-flash)的条目加上 input: [text, image](参考 install/settings.model-input.snippet.yaml)。多模态模型本来就在目录里声明了 image,无需改动。

  4. 重启服务:Ctrl+C 停掉 npm exec @deepseek-ai/dsh web 后重新运行(或重启桌面 App)。HMR 在 web profile 里被禁用,必须重启。

  5. 验证:新会话里直接粘贴一张图片,或对 vision 工具说"看看 <图片路径>"。

配置

两个插件共用的核心配置(写在 cordis.patch.yml 对应行的 config: 里):

默认值说明
modelmimo-v2.5视觉模型 id(同一网关的其他多模态模型:qwen3.7-plus / minimax-m3 / kimi-k3 / grok-4.5 等)
baseUrlhttps://opencode.ai/zen/go/v1OpenAI 兼容端点
apiKeyEnvOPENCODE_GO_API_KEYAPI key 来源:优先 credentials 服务,其次环境变量,最后 ~/.dsh/.credentials.yaml
timeoutMs120000(tool)/ 60000(inline)视觉模型调用超时
maxImageBytes(tool)16 MB单张图片大小上限
textOnlyModelIds(inline)[]额外指定必须走文字转换的模型 id(覆盖目录判断)

API key

插件不存储密钥。按以下顺序解析 apiKeyEnv 指向的 key:

  1. DSH credentials 服务(~/.dsh/.credentials.yaml,与 DSH 其他凭据同源);
  2. 进程环境变量;
  3. ~/.dsh/.credentials.yaml 直接读取(兜底)。

注意事项

  • read_image 守卫:纯文本模型会话里 read_image 会被拒绝(它会把图片块塞进模型上下文,而"声明了 image 的纯文本模型"会在网关层被 400 拒绝)。看图片统一用 vision 工具或直接粘贴图片。
  • 不要在纯文本模型上真正声明图片能力input: [text, image] 只是让发送闸门放行的配置声明;若图片真的进入 deepseek-v4-flash 的请求,网关会返回 unknown variant 'image_url' 错误。转换插件保证图片永远不会到达纯文本模型。
  • 多模态直通:把会话主模型切成 mimo-v2.5 等原生多模态模型后,图片会直接发给该模型原生识别(不消耗额外的识别步骤)。

测试

examples/vision-test.html 是一张含中文标题、彩色几何图形和数字 42 的测试图源文件,可用 headless Chrome 渲染成 PNG 后验证:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --headless=new --disable-gpu --window-size=800,500 \
  --screenshot=vision-test.png "file://$PWD/examples/vision-test.html"

兼容性

  • 目标环境:DeepSeek Harness 0.1.0-rc.6 web profile(@deepseek-ai/dsh);
  • 插件通过 profile 层 cordis.patch.yml 挂载,host 平面注册,对 dsh web 和桌面 App 分发通用;
  • 视觉网关:opencode.ai(OpenAI-compatible chat/completions,支持 image_url 内容块)。

License

MIT