DreamRift / dsh-vision-bridge

Listed

DeepSeek Harness 多模态视觉桥(dsh-vision-bridge):贴图经 llm/stream 自动转 VL 文字描述(解决 UNSUPPORTED_CONTENT)+ view_image/ocr_image 主动视觉工具 + 原生多模态路由自动跳过(rc.7);零依赖。Vision bridge for text-only DeepSeek models.

mainModelTool View source

Installation

npm pack # 产出 dsh-vision-bridge-0.4.0.tgz

This command is generated from the GitHub repository address. Inspect the upstream README and source before running it; pin a release or commit when reproducibility matters.

README

Maintainer-authored documentation snapshot.

View on GitHub ↗
Commit a9501e6Synced Aug 18, 2026

DeepSeek 多模态视觉桥(dsh-vision-bridge)

dsh-vision-bridge 是 DeepSeek Harness(DSH)的多模态视觉插件。DeepSeek 官方接口是纯文本的: 在 Web UI 贴图后,dsh-llm-deepseek 适配器会因消息中的图片内容块直接抛 UNSUPPORTED_CONTENT。 本插件借鉴 Qwen-MM-Plugins 的思路(VL 描述注入 + 主动视觉工具),以 DSH 原生插件实现「让纯文本的 DeepSeek 模型看见图片」:

  • 贴图自动代理:拦截 llm/stream 请求,把消息中的 ImageBlock 交给 OpenAI 兼容的视觉模型 (默认 DashScope qwen-vl-max)生成结构化中文描述(含图中文字逐字转录),替换为文本块后放行。 同图跨轮次缓存、描述文本稳定(保 KV cache 前缀);VL 失败进入失败冷却并降级为占位文本, 不阻塞会话;会话标题请求自动跳过视觉解析。
  • 主动视觉工具:注册 view_image(查看本地图片 / 按问题回答)与 ocr_image(逐字转录), 模型可主动查看文件系统中的截图、设计稿、图表。
  • 设置页卡片(v0.2.0 起):设置 → 插件 → 插件配置 → 「视觉模型」,可修改端点(来源)/ 模型 / OCR 模型并保存,热更新生效(无需重启);密钥与 harness 官方一致——write-only 不回显明文, 只显示「已配置 / 未配置」徽标,留空保持。
  • 模型能力桥接(v0.4.0 重构):运行时探测原生多模态路由并自动跳过视觉桥。 DSH rc.7 起官方 llm-pi-ai 适配器(pi-ai 库)原生支持图片,本插件在请求到达时 经 ctx.llm.resolveModelInfo() 查询 inputModalities,含 image 即直通(不调 VL、 不改写消息),让 pi-ai 原生多模态链路零开销工作;text-only 路由(deepseek-official) 仍走 VL 代理。旧版「给 pi-ai 模型补 image 声明」行为已移除(rc.7 中既有害又无必要)。

零硬 npm 依赖(dsh-settings/schemastery/dsh-tools 动态 import,缺包仅降级对应功能)、 不改 DSH 核心源码、不写会话事件,Windows / Linux / macOS 原生可用(无 Python / uvx / WSL 要求)。

部署

方式一:官方安装(推荐)

仓库已打 dsh-plugin topic,可被 DSH 插件商店 等目录自动收录。 一条命令安装:

dsh plugin --profile web add "github:DreamRift/dsh-vision-bridge"

方式二:手动安装(tgz + bundle)

  1. 克隆本仓库,进入项目目录并生成可安装包:

    cd dsh-vision-bridge
    npm pack    # 产出 dsh-vision-bridge-0.4.0.tgz
    
  2. $DSH_HOME/profiles/web/package.json 声明依赖与 bundle(包自带 cordis.patch.yml,无需在 profile patch 手写 insert):

    {
      "dsh": { "profile": { "bundles": ["dsh-vision-bridge"] } },
      "dependencies": {
        "dsh-vision-bridge": "file:<本仓库绝对路径>/dsh-vision-bridge-0.4.0.tgz"
      }
    }
    
  3. 安装 profile 依赖:

    cd "$DSH_HOME/profiles/web"
    pnpm install
    
  4. 默认配置(DashScope qwen-vl-max 等)在包内 cordis.patch.yml;改配置优先走设置页 「视觉模型」卡片(热更新),高级字段见 docs/挂载指南.md §3.2。

  5. 设置页自动暴露(rc.7 起无需 patch):settings.describe() 列出所有已注册 namespace, 注册即暴露。旧版 scripts/patch-api-proxy-namespace.mjs 已删除(rc.7 删除了 WEB_SETTINGS_NAMESPACES 白名单)。

  6. 内置路由图片准入豁免(deepseek-official 等 inputModalities 被 DSH 硬编码为 ["text"] 的路由贴图被拒时必须;DSH 升级后需重跑一次):

    node scripts/patch-api-proxy-image-admission.mjs
    

    详见 docs/挂载指南.md §3.6:deepseek-official 无法声明 image, 会被 api-proxy 的 MODEL_DOES_NOT_SUPPORT_IMAGES 准入检查拦截;本脚本对 providerRoutes 内已接管的 provider 跳过该准入(图片由视觉桥代理转文字)。 改完需重启 DSH 后端生效。

  7. 把 VL 服务的 key 写入 $DSH_HOME/.credentials.yaml(明文不进任何配置文件 / 仓库; 也可重启后直接在设置页「视觉模型」卡片里填,效果相同):

    QWEN_MM_VISION_API_KEY: sk-<your-key>
    
  8. 重启 dsh web,启动日志应出现 [vision-bridge] 已启用:…[vision-bridge] 设置页已就绪:…

工作原理

DSH 的贴图链路本身完整(拖放 → ctx.attachments → 消息中的 ImageBlock),卡在 DeepSeek 适配器 拒绝图片内容。本插件监听 llm/stream waterfall:由于 cordis 的 waterfall next 不接收替换参数, 插件采用 veto + 重入(DSH 官方插件 dsh-session-checkpoint-policy 示范的合法模式)—— 不调用 next,而是把替换后的请求打上 Symbol.for 标记重新送入 ctx.llm.stream()。 不含图片的请求走同步直通,零开销。会话日志中的 ImageBlock 保持原样(替换只发生在请求侧, 聊天历史仍显示原图)。rc.7 起在重写前先探测当前路由是否原生支持图片(ctx.llm.resolveModelInfoinputModalities):原生多模态(llm-pi-ai 等)直接直通、不调 VL。机制细节与源码依据见 开发计划 §3.1/§5.2 与 src/dsh/proxy.js 头注。

目录结构

dsh-vision-bridge/
├── DeepSeek多模态视觉桥-开发计划.md   # 设计与决策记录(含 DSH 机制调研来源)
├── docs/
│   ├── 挂载指南.md                   # 挂载到 DSH + 配置 + 验证清单 + 常见问题
│   └── Qwen-MM-Plugins调研报告.md    # 上游项目调研
├── package.json                      # dsh-vision-bridge 包(out-of-tree 插件)
├── src/
│   ├── core/                         # 核心库(纯 JS,零依赖,可单测)
│   │   ├── vision-client.js          # OpenAI 兼容 VL 客户端(超时 / 429 重试 / 错误分类)
│   │   ├── prompts.js                # describe / ocr / ask 三类中文 prompt
│   │   ├── image-utils.js            # 格式白名单、扩展名+魔数识别、base64 dataURL
│   │   ├── message-rewrite.js        # 不可变重写:ImageBlock → 文本块
│   │   └── describe-cache.js         # attachmentId → 描述 LRU(保 KV cache 前缀稳定)
│   └── dsh/                          # DSH 适配层
│       ├── index.js                  # 插件入口 apply(ctx, config)
│       ├── proxy.js                  # llm/stream 拦截(veto + 重入 + 原生多模态直通)
│       ├── tools.js                  # view_image / ocr_image 工具注册与执行
│       ├── runtime.js                # 共享运行时(日志 / fetch / 凭据解析 / VL 客户端)
│       ├── model-bridge.js           # 运行时探测原生多模态路由(llm.resolveModelInfo)并跳过
│       ├── settings.js               # 设置页桥接(schema + 热更新)
│       └── config.js                 # 配置解析(默认值 + 归一化,零依赖)
└── tests/                            # node:test,66 个用例(mock fetch,无需 VL key)

测试

node --test tests/*.test.js   # 66 个单元/集成测试全绿

覆盖:消息不可变重写(含冻结输入与 tool-result 内嵌)、缓存稳定性与 LRU、 VL 客户端(成功/401/429 重试/超时/取消/畸形响应/网络错误)、veto+重入链路 (直通/替换/降级/strict/失败冷却/标题占位/原生多模态探测直通)、 模型桥探测(resolveModelInfo 命中/TTL 缓存/降级/热更新清缓存/旧字段兼容)、 工具执行(正常/缺凭据指引/OCR 回退)。

致谢

  • QwenLM/Qwen-MM-Plugins:核心思路 (VL 描述注入、结构化转述、主动视觉工具)的来源;本项目未复用其代码(Python/MCP 实现改为 DSH 原生 Node 插件)。

许可

MIT

Project files and signals

Shown items are public repository signals detected in the directory snapshot.

TestsDetected
DocumentationDetected

Repository information

Language
JavaScript
License
MIT
Latest release
v0.4.0
Last updated
Aug 18, 2026, 12:38 PM

Install deliberately

Review source code, permissions, lifecycle hooks, dependencies and network access. Test untrusted plugins in an isolated environment.