MJorgin/dsh-media-skills
MJorgin/dsh-media-skills面向纯文本模型的免费视觉桥与生图:粘贴读图、GLM-4V-Flash 与 Gemini 引擎故障转移、modlens 同款结构化证据输出,并自动播种免费视觉模型路由。
让纯文本模型也能看图:消息中出现图片占位符时模型调用 vision_describe 工具,插件把本轮图片引用与提问一起转交给多模态视觉模型识别,主模型失败时自动用备用模型重试。配置在设置页完成并通过官方 settings API 持久化到 settings.yaml,热重载不丢。
DeepSeek Harness(DSH)视觉桥接插件:让纯文本模型也能“看图”。当用户消息里出现图片占位符 [image omitted because this model accepts text only; attachment sha256:…] 时,模型调用 vision_describe,插件把本轮图片引用 + 提问交给多模态视觉模型识别;主模型失败时自动用备用模型重试。配置通过官方 settings API 持久化到 profile 条目 dshp-vision-bridge 的 config:,设置页改动即时热更新,重启不丢。
设计原则:配置只留用户真正要决定的。视觉模型只有开关、主模型、备用模型三项;详细度是工具参数,单次图片数固定 4 张。图片只存 leaf 字段的 owned copy,会话级 LRU,无密钥、无外部依赖、卸载即干净。
git pull# 1. 克隆 monorepo(lib/ 构建产物已提交,clone 下来就能用,无需 build)
git clone git@github.com:Yinxe/deepseek-harness-plugins.git
cd deepseek-harness-plugins
pnpm install
# 2. 本地安装到 profile(路径按你执行命令时的 cwd 解析)
dsh plugin --profile web add ./plugins/vision-bridge
# 3. 重启生效
dsh webgit pull + dsh web(lib 已提交,未改 src 无需 build)。pnpm --filter @dshp/vision-bridge build 重打 lib/host.js + lib/client.js,再重启;client 半强刷页面即可。vision_describe。一键 AI 安装:把下面这段发给你的 DSH AI 即可:
帮我安装视觉桥接插件(monorepo Yinxe/deepseek-harness-plugins,子目录 plugins/vision-bridge,包名 @dshp/vision-bridge):
1. git clone monorepo 并 pnpm install
2. dsh plugin --profile web add ./plugins/vision-bridge
3. dsh web 重启,确认无报错,设置页出现「视觉模型」即成功dsh plugin --profile web add \
https://github.com/Yinxe/deepseek-harness-plugins/releases/download/latest/dshp-vision-bridge-latest.tgz
dsh web # 重启生效main 永远跟随最新 DSH。旧版 DSH 用户按 compat.json 的 tag 到 Releases 找对应 Release:
# 以 v0.2.0-rc.2 为例(DSH 0.2.0-rc.2)
dsh plugin --profile web add \
https://github.com/Yinxe/deepseek-harness-plugins/releases/download/v0.2.0-rc.2/dshp-vision-bridge-v0.2.0-rc.2.tgz
dsh web # 重启生效安装方式 · 更新命令 · 说明 方式一 clone(推荐) · 仓库内 git pull + dsh web · 最快;未改 src 免 build 方式二 Release · 重跑同一条 add 命令 + dsh web · URL 直装对 update 免疫 方式三 git 依赖 · dsh plugin --profile web update @dshp/vision-bridge + dsh web · 一条命令;git 解析约 35s/插件
部分 · 内容 Host(src/host/ → lib/host.js) · 注册 vision_describe;监听 agent/inbox/inserted + llm/stream 缓存图片(按 attachmentId 去重,20 张/会话、50 会话 LRU);模型发现走 settings.describe() + llm.listConfigurableProviders() 与 llm.listProviders()/listModels() 两条来源;注入系统提示;启用且选好主模型时接管发送门禁;同源 JSON 路由供设置页。 Client(src/client/ → lib/client.js) · 「设置 → 视觉模型」:启用开关、主/备模型下拉、刷新列表、测试路由。开关/标签/按钮/菜单全部用官方 dsh-client-ui-primitives,颜色走 --dsw-* token。 同源路由 · GET /ext/dshp-vision-bridge/state(模型 + 配置)、POST /ext/dshp-vision-bridge/config(保存补丁)、GET /ext/dshp-vision-bridge/check(探活主/备路由),均带同源校验与 body 上限。 工具 · vision_describe,输出 { description, model },模型侧渲染为纯文本。
vision_describe参数 · 类型 · 必填 · 说明 question · string · ✅ · 主模型结合当前对话上下文生成的看图提示词,写清想从图片确认的具体内容;插件原样转给视觉模型,不追加固定后缀。 image · integer · · 只看第几张图(从 1 开始,多图时用);留空分析本轮最近 4 张。
question是主模型自己生成的提示词:想读报错就写报错,想转录就写“逐字转录”,插件不再提供detail之类的固定模板。
返回:
{ "description": "视觉模型返回的文本", "model": "provider/model" }字段 · 类型 · 默认 · 说明 enabled · boolean · true · 总开关。关闭后 vision_describe 直接报错。 primary · {provider, model} \ · null · null · 主视觉模型;未选择时 vision_describe 临时用候选列表第一项,但发送门禁不会接管。 fallback · {provider, model} \ · null · null · 备用模型,主模型失败时重试一次;与主模型相同则不重试。
候选来自两处并集去重:
llm.listConfigurableProviders() 给出每个 provider 的 settingsNs + settingsPath,再用 settings.describe() 读取 models[] 中 input 含 image 的模型。llm.listProviders() + llm.listModels(provider) 中 inputModalities 含 image 的模型。在 设置 → 模型 中编辑多模态模型,勾选 image 输入即可。等价 YAML:
llm-pi-ai:
providers:
openrouter:
models:
- id: qwen/qwen2.5-vl-32b-instruct
name: Qwen2.5 VL 32B
input: [text, image] # ← 关键:声明支持图片输入保存后回到 设置 → 视觉模型 点「刷新列表」。推荐至少配两个视觉模型,一个主模型、一个备用模型。
vision_describe,把图片和问题一起发给视觉模型。description 以 tool-result 回到模型上下文,模型据此继续回答。进阶:
image: 2 指定第二张。pnpm --filter @dshp/vision-bridge test # node --check 双 bundle + CSS Module 静态检查
pnpm --filter @dshp/vision-bridge build设置页自检:打开 DSH Web → 设置 → 视觉模型,确认:
端到端:发一张截图并问“这张图里有什么?”,观察模型是否调用 vision_describe 且返回非空 description。
用户发图(content: [{type:'image'}, {type:'text'}])
├─ agent/inbox/inserted ─┐
└─ llm/stream ───────────┼─→ 图片缓存 Map<sessionId, Map<attachmentId, ImageRef>>
│ 只存 attachmentId/mediaType/bytes/width/height/name
│ 按 attachmentId 去重;20 张/会话、50 会话 LRU
纯文本模型看到占位符 → vision_describe({question, image?})
├─ 取会话缓存 → image 序号过滤 / 最近 4 张
├─ question 原样透传(不拼固定后缀)
└─ describeWithFallback()
├─ 主模型 → llm.stream({provider, model, messages:[image…, text]})
└─ 失败 → 备用模型重试一次(用户取消不重试)关键细节:
llm.resolveModelInfo,给缺 image 的模型补上 inputModalities,让纯文本模型可以接收图片;请求侧仍由 llm 层按真实能力把图片投影成占位符。探活使用未包装的原函数,避免“自证可用”。get(ns),统一用 settings.describe();provider 的命名空间和路径来自 llm.listConfigurableProviders(),不再硬编码 llm-pi-ai / llm-deepseek。question 由主模型结合当前对话生成,插件只做 trim + 4000 字符截断,不写死“描述这张图片”之类的兜底句,也不追加 detail 后缀。text-delta 增量优先,block-end 只在同一 index 没有增量时兜底;finish 的 error / aborted 转成异常,空返回触发 fallback。POST /config 逐字段校验后调用 settings.update(NS, patch),写入 profile 条目 config: 并原地热更新;配置只认 dshp-vision-bridge,不读旧 key / 旧文件。cordis.patch.yml 覆盖)- id: dshp-vision-bridge
name: '@dshp/vision-bridge'
config:
enabled: true
primary: { provider: 'openrouter', model: 'qwen/qwen2.5-vl-32b-instruct' }
fallback: { provider: 'openrouter', model: 'openai/gpt-4o-mini' }src/host/
index.ts apply 装配:缓存、门禁接管、系统提示、工具、路由
config.ts NS + schemastery Config(3 个 volatile 字段)
types.ts 领域模型 + llm/settings 最小服务接缝
http.ts json / sameOrigin / readBody
cache.ts 会话图片缓存(去重 + LRU)
vision.ts 模型发现、单次调用、主备 fallback、问题拼装
src/client/
index.tsx 只导出 inject / apply,注册 settings.section
VisionSection.tsx 设置页
components.tsx Row + Select
api.ts state / config / check 路由封装
types.ts 协议 + slots/ctx 接缝
styles.module.css 版式(构建期内联)
lib/host.js Host 单文件 ESM(提交物)
lib/client.js Client 单文件 CJS(提交物)
cordis.patch.yml bundle 挂载行config: 里直接写 primary / fallback。agent/inbox/inserted 重新入缓存。package.json 的 dsh.profile.bundles 含 @dshp/vision-bridge,重启后硬刷新浏览器。detail / maxImages / promptTemplate 已移除。旧条目 config: 里残留的这三个键不会被读取,可手动删除;primary / fallback / enabled 原样可用。图片提示词由主模型按上下文生成,单次图片数固定 4 张。dsh plugin --profile web remove "@dshp/vision-bridge"
dsh web配置保存在 profile 条目 dshp-vision-bridge 的 config:,删除该分节即回默认值。
本目录是原 ~/.dsh/plugins/vision-bridge/lib/index.js(JS,816 行)的 TypeScript 重写:
原实现 · 现文件 lib/index.js 的 ctx / 工具 / 路由装配 · src/host/index.ts 图片缓存与 block 扫描 · src/host/cache.ts 模型发现 / llm.stream / fallback · src/host/vision.ts 设置页与同源路由调用 · src/client/VisionSection.tsx、src/client/api.ts
构建:pnpm --filter @dshp/vision-bridge build(lib/ 是提交物,改 src/ 后必须重打并一起提交)。
本插件只做图片转交,不存储图片原图,不写入除 profile 条目 config: 之外的任何用户文件。视觉模型的费用、额度与内容政策由对应 provider 决定。