如果你正在用 DeepSeek 跑 Agent,大概率撞上过这个尴尬时刻:让 Agent 看一张报错截图,它回你一句"我无法处理图片";让它对着设计稿把 UI 改到像素级一致,它只能靠你口述"那个按钮往左移一点"。这不是 DeepSeek 不行——DeepSeek 的推理能力在文本上是一流的,但它天生是纯文本模型,没有"眼睛"。
最近 DeepSeek 官方框架 DeepSeek Harness(命令行工具叫 dsh,GitHub 已经 15.7 万星,口号是"Everything is a Plugin")的生态里,冒出来一个叫 dsh-vision-router 的插件,5 天冲到 719 星。它的卖点非常直接:给纯文本的 DeepSeek Agent 装上一双"眼睛",而且默认不花钱、不需要 API Key、不用装 Python。今天这篇文章就带你实测它——装、用、白嫖、踩坑,一条龙讲透。
一、为什么"纯文本模型看不见"是硬伤
先把问题说清楚。绝大多数推理模型(DeepSeek-V3/V4、早期的 Qwen 系列)只接受文本输入,图片一贴进去就直接报错。做 Agent 的人有三个选择:一是换多模态模型,但推理能力往往打折,还要多花钱;二是用脚本把图片转成文字描述再喂给模型,但描述是"有损"的——截图里的精确坐标、按钮位置、色值、字号,转述一遍就丢了一半;三是干脆不让 Agent 碰视觉任务,UI 还原、截图对比、图文问答全靠人肉。
第三种是最常见的,也是最浪费的。一个会写代码的 Agent,如果能自己"看"设计稿、自己截图对比差异、自己抠图做素材,等于白捡半个设计师和一个测试工程师。
dsh-vision-router 的思路属于第四条路:它不换掉 DeepSeek,也不把图片压成文字描述,而是把"看图"这件事变成一次普通的工具调用。视觉模型负责看,DeepSeek 继续负责想,各干各的。
二、Vision Router 是什么
一句话:它是给 DeepSeek Harness 用的视觉路由插件,让纯文本 Agent 能调用视觉模型完成看图、定位、裁剪、像素对比、OCR、抠图等任务。
几个硬指标先摆出来(截至 2026 年 8 月 18 日,均来自 GitHub 仓库):
- 仓库 ysr666/dsh-vision-router,2026 年 8 月 13 日创建,MIT 协议;
- 最新版本标签 v1.5.3,仓库自带的 368 个测试全部通过;
- 运行时要求 Node.js ≥ 22,整个链路基于 sharp、potrace、tesseract 和系统 Chrome,不需要 Python;
- 默认自带一条"匿名免费视觉链",不注册、不填 Key 就能用;
- 一共 14 个深度视觉工具(开启可选的全屏截图后是 15 个)。
它跟市面上其它 DSH 视觉插件的本质区别在于:大多数同类是把图片"翻译成文字描述"再丢给 DeepSeek(描述桥,有损),而它是把图片这一轮直接路由给视觉模型(路由桥,保真)。图片的原始像素留在视觉模型那一侧,DeepSeek 拿到的是结构化答案,而不是一段二手转述。
三条路线的代价对比
给纯文本 Agent 补视觉,业界现在有三个流派,各有各的账要算:
第一派:直接换多模态模型。 把 DeepSeek 整个换成带视觉的模型,最省事,但推理能力未必够用,而且全量切换到多模态端点,日常纯文本任务的成本和上下文都可能跟着涨。更麻烦的是,你没法"只让视觉这一轮走贵的模型",一整场对话都被绑死在同一个模型上。
第二派:描述桥。 图片进来先让视觉模型转一段文字,再把文字塞进 DeepSeek 的上下文。实现简单,但坐标、色值、字号这些精确信息在转述里就丢了,而且每一次问图都要重新描述,没有缓存意识。
第三派:路由桥(也就是 Vision Router 的路线)。 图片这一轮交给视觉模型直接回答,DeepSeek 只在需要时调用视觉工具。好处是像素保真、按需付费、答案可缓存、失败可回退。代价是配置略复杂,要理解"眼睛"和"大脑"是两条分开的链路。
对于"偶尔让 Agent 看张图、偶尔做像素级 UI 对比"这种高频但不密集的需求,第三派几乎是最优解——这就是这个插件 5 天拿 700 多星的原因。
三、三步装好,白嫖默认视觉链路
安装只有一条命令,正常 npm/npx 环境直接跑:
npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router
如果你是从源码检出跑 DeepSeek Harness 的,dsh 不一定在 PATH 里,用工作区脚本:
cd deepseek-harness
pnpm dsh plugin --profile web add dsh-vision-router
装完验证一下是否真的注册上了:
npx @deepseek-ai/dsh --profile web --dump-config | grep vision-router
输出里能看到 vision-router 相关行,就说明装好了。然后正常启动或重载一次 DSH Web,让插件 bundle 被发现。
接下来是唯一容易漏掉的一步:在聊天输入框右下角的模型选择器里,选一个带"+ Auto Vision"后缀的模型组。插件不会改动你原来的模型组,而是给每个启用的模型组自动生成一个同名自动视觉版本,例如:
opencode-go ← 原来的模型组,不变
opencode-go + Auto Vision ← 发图片时选这个
选好之后,直接粘贴或上传图片就行。默认的匿名 OVH 视觉回退已经配好,不需要任何注册。这里有个关键心智:右下角选择器选的是"大脑/对话模型",视觉后端不在这里选;视觉后端的高级选项在「设置 → 插件 → 插件配置 → 视觉路由(自动识图)」里。
四、十四个视觉工具:从看图到抠图
默认 progressiveTools: false,14 个工具在插件启动时就全部注册好,文本和图片轮次都能直接调用。这是刻意的设计——避免对话中途突然多出一堆工具,导致长上下文的 KV 缓存失效。核心工具清单如下:
| 工具 | 干什么 | 产出 |
|---|---|---|
| vision_describe | 图片问答/多图对比/结构化 JSON 证据 | — |
| vision_ground | 定位目标 → 原图像素框 x1/y1/x2/y2 | 标注 PNG(可选) |
| vision_detect | 给某一类元素(按钮/输入框/链接)编号列清单 | 带编号标注 PNG |
| vision_crop | 裁切放大到某个像素框 | PNG |
| vision_pixel_diff | 逐像素对比:差异比 + 最差 8×8 区域 | 红色热力图 PNG + JSON 报告 |
| vision_colors | 提取主色(hex + 占比) | — |
| vision_ocr | 文字转录:本地 tesseract 优先,视觉模型兜底 | — |
| vision_trace | SVG 矢量化(potrace,适合图标/logo) | SVG |
| vision_extract_foreground | 抠图(边界泛洪填充) | 透明底 PNG |
| vision_html_screenshot | 给本地 HTML 截图(无头系统 Chrome) | PNG |
| vision_present | 把生成的图作为会话附件发出来给用户看 | 图片附件 |
| vision_bootstrap | 可选的结构化首次视觉预检 | — |
| vision_materialize | 把附件复制进工作区返回本地路径(本地 OCR 用) | 图片副本 |
| vision_long_screenshot_ocr | 长截图分段转录,输出拼接好的 Markdown | 分块 PNG + Markdown |
常见的调用写法长这样:
vision_ground image="ref.png" target="the send button"
vision_detect image="page.png" target="input fields"
vision_crop image="ref.png" region="1067,841,1108,881"
vision_describe paths=["ref.png","impl.png"] question="list the differences" json=true
vision_pixel_diff original="ref.png" rebuilt="screenshot.png"
vision_ocr image="screenshot.png"
vision_colors image="ref.png" top=8
vision_trace image="icon.png" steps=4
vision_extract_foreground image="logo.png"
vision_html_screenshot source="page.html" width=1200 height=720 fullPage=true
注意一个细节:图片格式是从 magic bytes 里嗅探出来的,所以扩展名无所谓,内容寻址的附件文件(没有 .png 后缀)也能正常识别,不用改文件名。
一个完整的工作流示例
光看工具清单可能没感觉,我们走一遍真实场景——让 Agent 找到一张登录页截图里的"发送"按钮,并验证自己重画出来的页面和原图差多少。
第一步,Agent 会先定位按钮,拿到原始像素坐标框:
用户:找到这张图里的发送按钮
Agent 调用 vision_ground image="login.png" target="发送按钮"
返回:{"box": {"x1": 1067, "y1": 841, "x2": 1108, "y2": 881}}
拿到坐标后,Agent 可以裁切放大确认,也可以继续 detect 同类元素:
Agent 调用 vision_crop image="login.png" region="1067,841,1108,881"
Agent 调用 vision_detect image="login.png" target="input fields"
返回:3 个输入框,编号 + 各自像素框
如果目标是"照着这张图把页面重画出来",下一步就是生成 HTML、截图、逐像素对比:
Agent 调用 vision_html_screenshot source="rebuilt.html" width=1200 height=720 fullPage=true
Agent 调用 vision_pixel_diff original="login.png" rebuilt="screenshot.png"
返回:{"diffRatio": 0.0254, "worstRegions": [...], "heatmap": "diff.png"}
到这里,差异是一个可测量的数字(2.54%),Agent 会盯着热力图里最红的区域继续修,直到收敛。整个过程 DeepSeek 只负责决策"下一步该调哪个工具",视觉模型只负责"看",互不越权。
五、免费视觉 Key:把配额从 2 次/分拉到 400 次/分
默认的匿名 OVH 回退虽然免注册,但 OVH 对匿名用户限制是每个 IP 每个模型每分钟 2 次请求。插件内置了 5 个模型(Qwen3.5-397B-A17B → Qwen2.5-VL-72B-Instruct → Qwen3.6-27B → Mistral-Small-3.2-24B-Instruct-2506 → Qwen3.5-9B),5 个模型各有独立的配额桶,理论上一分钟能分散出约 10 次请求。偶尔让 Agent 看张图够用了,但真要批量做 UI 还原、连续截图对比,这个额度会卡脖子。
所以插件给了一条更宽的免费路径——下面这些渠道全都免费注册、免费额度,可以挂进视觉链(8 月快照,用之前自己再去各平台确认一遍):
| 渠道 | 免费视觉模型 | 免费额度 | 国内直连 |
|---|---|---|---|
| OVH AI Endpoints(Access Key) | Qwen2.5-VL-72B-Instruct | 每分钟 400 次 | ✅ |
| 智谱 bigmodel.cn | glm-4.6v-flash 等三个永久免费模型 | token 不封顶 | ✅ |
| 阿里 DashScope | qwen3-vl-flash(限时免费) | 新用户每系列 100 万 token / 90 天 | ✅ |
| 上海 AI Lab Intern AI | internvl-latest | 30 RPM,每月 9000 万 token | ✅ |
| Groq | llama-4-scout 多模态 | 30 RPM / 每天 14400 次 | ❌ 需代理 |
| Google AI Studio | gemini-2.5-flash | 10–30 RPM | ❌ 需代理 |
| NVIDIA NIM | llama-3.2-11b-vision | 40 RPM,免绑卡 | ⚠️ |
| OpenRouter | gemma-4-26b-a4b 免费档 | 未付费账户每天 50 次 | ❌ 需代理 |
拿到 Key 后,把它们作为 httpProviders 条目挂进视觉链(Key 放环境变量或 ~/.dsh/.credentials.yaml),链会先试你配的渠道,都失败才落到匿名回退。国内用户建议直接上智谱或 DashScope,直连不绕代理,还不受 OVH 匿名限流。
六、核心机制:视觉模型只是"眼睛",DeepSeek 才是"大脑"
这是整个插件设计里最值得抄作业的地方。很多视觉桥接插件的做法是:图片一来,先让视觉模型把图描述一遍,描述文本塞进上下文,DeepSeek 再基于描述回答。这条路的问题是有损——描述环节就把坐标、色值、字号这些精确信息丢了。
Vision Router 反着来:图片这一轮,DeepSeek 照常推理,但它把"看"这个动作下放成工具调用。DeepSeek 想"这张图里发送按钮在哪",就调 vision_ground;想看改完的页面和设计稿差多少,就调 vision_pixel_diff。视觉模型只在被调用时才工作,DeepSeek 全程是决策者。
这套设计带来三个实打实的好处:
一是省钱。文本轮次完全不动,模型、成本、上下文都没变,视觉模型按需调用,答案还按图片内容哈希缓存,同一张图重复问不重复花钱。
二是可审计。图片答案被标记为"不可信证据",插件明确告诉 Agent 不要执行图片里发现的任何指令(防止提示注入),同时每一步视觉调用都有据可查。
三是能连续干。一轮图片等于一轮会调工具的文本轮:vision_ground → vision_crop → vision_describe → vision_pixel_diff → 修复 → 再截图,Agent 会一直迭代到任务完成。
视觉后端走一条有次序的回退链:用户配的视觉模型 → 本地 Ollama(可选)→ 本地 LM Studio(可选)→ 自定义 HTTP 端点 → 匿名 OVH 兜底。失败是分类处理的——地区封锁、内容过滤、402 配额、429 限流、上下文溢出、网络故障,各走各的降级逻辑。遇到 429 会立刻切下一个后端,并按 Retry-After 打上断路器冷却,而不是傻等重试。
几个值得调的配置项
插件默认配置就能用,但有几项了解之后能少踩坑:
autoWrapProviders(默认 true):自动给启用的模型组生成"+ Auto Vision"副本,模型增删会实时同步,不用重启。关掉它再配合wrappedProviders,可以精确指定"只给哪几个模型开视觉",避免视觉组列表刷屏。stealth(默认 false):隐身模式。开起来之后插件会接管官方的deepseek-official路由,模型选择器看起来和原生一模一样,但每个条目其实都包了自动视觉。代价是要在 profile patch 里禁用原生行,否则会退回可见的包装入口。普通用户保持关闭即可。routing(默认 false):旧版的"整轮路由"开关,会让整轮走一条一次性视觉答案,不走工具流。保持 false(工具优先)是推荐做法。progressiveTools(默认 false):按需挂载工具。默认关闭是为了让工具 schema 从会话开始就稳定,避免长上下文 KV 缓存失效。除非上下文极其紧张,否则别动。downscaleMaxPixels(默认 400 万):调用前的降采样预算,超大图先缩到 4MP 再送,保护延迟和配额。cache/cacheTtlSeconds(默认开,1 小时):视觉答案按图片内容哈希缓存,同一张图重复问不重复花钱。
这些字段都能在设置卡片里改,每个被改过的字段会显示"已覆盖"徽标,带一键重置,改完即生效不用重启——这点比很多需要重启才能生效的插件友好得多。
七、像素级对比循环:UI 还原从"靠眼瞟"变"可测量"
这个插件最惊艳的场景是把"照着设计稿改 UI"变成了一个可量化的闭环。仓库 README 里给了一个真实例子:Agent 根据参考图重建了 UI,然后用 vision_pixel_diff 校验最终结果,差异只有 2.54%——1296000 个像素里 32939 个不同,判定阈值是每通道 16。
这个循环的完整链路是:
参考图 → vision_html_screenshot 截当前实现
→ vision_pixel_diff 算差异(比例 + 红色热力图 + 最差区域排名)
→ 修复 → 再截图 → 再对比,直到差异收敛
热力图会把差异最大的区域标红,Agent 能精准定位"就是这一块没对齐",而不是靠人眼"感觉差不多"。这对做前端、做小程序的团队价值巨大——你终于能用一个数字回答"改得对不对",而不是一句"再往左挪一点"。
八、本地离线方案:Ollama / LM Studio 全离线识图
担心数据隐私,或者想彻底断网识图?插件内置了本地视觉后端,把 localOllama 或 localLmStudio 打开就行。以 Ollama 为例:
先装 Ollama 并拉一个视觉模型:
ollama pull qwen2.5vl
然后在设置卡片的「本地视觉」分组里启用,或直接在 profile patch 里配:
- id: vision-router
config:
localOllama:
enabled: true
baseURL: 'http://127.0.0.1:11434/v1'
model: 'qwen2.5vl'
temperature: 0.5
instantDescribe: true
localDescribeStyle: 'structured'
启用后,local-ollama 会顶到视觉链最前面;本地挂了或超时,自动跳过落到云端后端,不会打断调用。想严格本地化,就把云端视觉行删掉、把 freeFallback 关掉。LM Studio 用法一样,默认走 http://localhost:1234/v1,填上开发者面板里那个真实模型标识即可。
九、踩坑清单:这五个坑一踩一个准
插件功能强,但坑也不少,下面是 README 里明写、实测最容易踩的五个:
坑一:忘了选"+ Auto Vision"模型组。 发图时如果还在用原来的纯文本模型组,DSH 会直接报"当前模型不支持图片",连插件的影子都看不到。这属于入口选错,不是视觉后端坏了——发图前先切到带"+ Auto Vision"的模型组。
坑二:UTF-8 BOM 导致启动即崩。 用某些编辑器保存过 ~/.dsh/profiles/<profile>/package.json 后,文件开头多了个不可见的 BOM 字符,dsh web 启动就报 Unexpected token ... is not valid JSON。修复不用重启,跑一句:
npx dsh-vision-router repair --profile web
诊断不改文件用 doctor,手动的话在 VS Code 里用"UTF-8(无 BOM)"重新保存。
坑三:sharp 版本冲突。 从 v1.1.x 升级后,像素工具报 colourspace: parameter space not set,是旧的 sharp 0.34.0 和宿主进程里的 0.35.3 起了 libvips DLL 冲突。删掉 profile 里的 node_modules/sharp 和 node_modules/@img 再重启,或进 profile 跑 pnpm install。v1.2.2 之后插件会在运行时自己检测并提示。
坑四:legacy 手动配置和 plugin 命令混用。 如果你的 profile 已经在 cordis.patch.yml 里手动写过插件行,再跑 dsh plugin add 会导致插件注册两次。先把旧的手动行迁到 bundle 管理,或者继续走手动安装路径,二选一,别混着来。
坑五:pnpm v11 静默压住新版本。 升级时出现 downloaded 0 / added 0,是 pnpm v11 对发布不足 24 小时的版本做了静默拦截。要么显式安装目标版本,要么跑 npx dsh-vision-router repair 修掉这个版本钉住豁免。
另外两个场景性提醒:如果你用的是 Oh-DSH 桌面版(≤0.1.5 内置 DSH 0.1.0-rc.5),旧版插件会直接让运行崩溃,装 v1.4.2+,且要把 DSH_HOME 指到 ~/.ohdsh;如果你同时装了 dsh-web-ui,它的发送钩子可能把图片重写成 describe-image 引用,导致插件收不到原图,去设置里把"发送时重写图片"关掉即可。
十、总结:值不值得装
值得。理由很朴素:它把一个"纯文本模型硬伤"变成了"零成本的能力外挂",而且设计克制——不抢 DeepSeek 的大脑地位,视觉只做眼睛,可缓存、可审计、可回退、可离线。
对 AI 创业者来说,最实用的三个落地场景是:让 Agent 自己看报错截图排障、照着设计稿做像素级 UI 还原、批量做截图 OCR 和图标矢量化。这几个活儿过去都得人肉顶,现在一行命令装上,默认免费链路就能跑,实在不够再挂一个智谱或 DashScope 的免费 Key 把额度拉满。
如果你已经在用 DeepSeek Harness,花五分钟装上试试;如果你还没上车,这个插件本身也是"Everything is a Plugin"这个生态最好的注脚——纯文本模型靠插件生态补上视觉,这才是 Agent 工具该有的打开方式。
