前言¶
DeepSeek Harness(dsh)是 DeepSeek 开源的智能体运行时,官方定位是开发者预览版,口号是「一切皆插件」:模型适配、工具注册、会话日志、Agent 循环,都可以用插件替换,而不必改运行时源码。启动 Web UI 的官方入口是:
npx @deepseek-ai/dsh web
日常编码里更常见的矛盾是另一面:DeepSeek、GLM 这类主力对话模型是纯文本的,看不见截图。报错界面、设计稿、PDF 页、前端渲染结果,往往只能先口述,再让模型猜。社区目录 deepseek-harness-plugin.com 是独立站点,与 DeepSeek / 幻方没有官方从属关系;它把这类扩展按分类收录,其中「工具与能力」下有一个被标成精选的插件:modlens。
本文按该目录详情页、GitHub 仓库 README / INSTALL.md / 宿主接入文档 / 输出契约,以及 DeepSeek Harness 官方说明核对后整理:它是什么、装完能做什么、命令怎么写、读图结果长什么样。
这是什么¶
modlens 是由 liustack(作者署名 Leon Liu)维护的视觉插件,npm 包名 @liustack/modlens,许可证 MIT,主要语言 TypeScript。写作时仓库 package.json 版本为 3.18.1(2026-08-17),要求 Node.js >= 22.19。社区目录把它分在「工具与能力」,收录日期 2026-08-14;GitHub 仓库页面在 2026-08-17 显示 2384 star(目录页快照为 1548,星标以仓库页面为准)。
目录页和仓库 README 的定位一致:它是 DeepSeek Harness 上的视觉插件,也是纯文本编码 agent 的视觉桥梁——把图片交给外挂视觉引擎,返回带 OCR、版面和语义的结构化 JSON,再交给当前会话里的纯文本模型去推理。
在 dsh 里,它不是一份靠提示词触发的 Skill。仓库 INSTALL.md 写得很明确:只拷贝 skills/modlens 文件夹,用户拿不到 modlens_read_image 工具,也看不到 (modlens vision) 模型条目(相关说明见 issue #32)。正确形态是原生插件(dsh bundle):注册工具、包装纯文本路由、在 Web UI 里接管粘贴。
同一套读图引擎也以 Skill 形式出现在 Claude Code、Codex、Pi、OpenCode 上,配置都写在 ~/.modlens/config.json。本文以 dsh 为主。
核心功能¶
1. 原生工具 modlens_read_image¶
装进 dsh 之后,插件注册 modlens_read_image。工具 schema 随每次请求发给模型,不靠关键词启发式。模型看到图片路径或附件时调用它,插件在包内跑自己的 CLI,把结构化证据作为工具输出返回。
仓库 CHANGELOG 3.16.3 解释过命名原因:dsh 若已有宿主自己的 read_image,分层注册不会报冲突,模型仍会打到宿主工具,而宿主工具对纯文本模型是拒绝的。所以插件改用自己的名字,避免抢注。
2. 两种粘贴路径¶
仓库 README 把 dsh 上的贴图分成两条,走哪一条由宿主根据模型元数据(inputModalities)判断,而不是按名字猜:
-
直接粘贴(paste-to-path)
当前模型被确认是纯文本时,浏览器端把图片发到本机 dsh web 服务器的/modlens/paste(仅回环、校验 magic byte、上限 25 MB),落成私有临时文件,输入框里出现的是文件路径。消息不带图片附件,dsh 的图片准入检查不会拦住。这和 Pi、OpenCode、Claude Code 递给模型的形态接近,也是modlens_read_image的首要触发条件。 -
切到
(modlens vision)变体再粘贴
插件会给每条承载纯文本 DeepSeek / GLM 的 provider 路由自动加包装条目。默认安装下常见的是DeepSeek-V4-Flash (modlens vision)和DeepSeek-V4-Pro (modlens vision);额外路由(如 opencode-go、zai)会各自多一组。两家自己的视觉型号会被排除。这条路径保留缩略图,在发请求时把图片块转成证据文本。选择器有记忆,选一次即可。
元数据确认不了、或模型声明支持图片输入时,粘贴保持原生,视觉模型继续自己读图。插件配置行里设 pasteToPath: false 可以关掉第一条路径。
3. 结构化证据,而不是一段散文¶
每次识别向 stdout 打一个 JSON(输出契约 v2)。外层大致是:
{
"image": "/abs/path/or/url",
"provider": "gemini-api",
"result": { },
"meta": {
"generatedAt": "2026-08-01T12:00:00.000Z",
"model": "gemini-3.6-flash-low",
"durationSeconds": 25.4,
"attempts": [],
"warnings": []
}
}
result 的必填顶层字段是 summary、ocr、layout、semantics、visual、uncertainty:
ocr:全文转录,以及按行切分的文本layout.regions:按阅读顺序划分的区块,type是自由字符串(title、paragraph、table、chart、code、link、nav 等只是文档里的常用词,不是封闭枚举)semantics:场景、实体、关系visual:主色、风格等补充uncertainty:读不清的地方如实列出,而不是填进去
相对 v1,v2 删掉了像素级 bbox 和数值型 confidence。文档的理由是视觉模型最容易把这两项编圆。结构不合格的结果会走故障转移,而不是直接交给上游模型。meta.attempts 记录链上每一次尝试;复用了本机某个 CLI 的额度时,meta.warnings 会标明花的是谁的配额。
4. 多引擎,一条故障转移链¶
modlens 不绑定单一视觉服务。仓库文档列出六个内置 provider,配好其中一个就能用:
| Provider | 需要什么 | 文档给出的单次耗时 |
|---|---|---|
gemini-api |
Gemini API key | 5–10 秒(仓库推荐默认) |
openai |
OpenAI 兼容端点(key + baseUrl + model) | 5–10 秒 |
anthropic |
Anthropic API key | 5–10 秒 |
antigravity-cli |
免费 agy CLI,浏览器登录一次 |
15–45 秒 |
claude-cli |
已登录的 Claude Code | 20–45 秒 |
kimi-cli |
已登录的 Kimi Code,需显式点名 | 20–45 秒 |
不钉死 provider 时,已配置的引擎组成故障转移链:API 快车道先试,agent CLI 兜底,第一个可用结果胜出。openai 在这里是协议插座,不是「只能连 OpenAI」:DashScope 上的 qwen-vl、GLM 开放平台、SiliconFlow、OpenRouter、自建 vLLM / Ollama,只要走 chat-completions 且支持图片输入,都可以用同一组键。
本机已登录的 Codex、OpenCode、Pi、Grok CLI,要先 config set reuse.<name> true 才会进链,不会默认扣别人的订阅。kimi-cli 也是显式点名才跑,因为它会消耗 Kimi Code 订阅。
安装与启用¶
社区目录给出的命令¶
插件详情页上的安装命令原文是:
dsh plugin add github:liustack/modlens
需要可复现安装时,目录页要求固定 commit 哈希:
dsh plugin add github:liustack/modlens#<commit>
目录页同时提示:插件以当前 dsh 进程的权限运行,安装时可能执行代码;安装前应检查源代码仓库和许可证。
仓库针对 dsh 的版本钉死写法¶
INSTALL.md 和 docs/harness-setup.md 给 dsh 用户的命令是另一条。写作时钉在 3.18.1:
npx -y @deepseek-ai/dsh plugin --profile web add @liustack/modlens@3.18.1
仓库刻意不用 @latest:pnpm 11 默认开启 minimumReleaseAge(24 小时),dist-tag 只在过了冷静期的版本里解析,@latest 可能装到一天前的旧版。点名版本号是明确指定。更新也用 add 而不是 update:update 只在已记录的 semver 范围内移动,caret 范围装进来的 2.x 到不了 3.x。
当前版本可用下面命令查询,再把命令里的版本号换成输出值:
npm view @liustack/modlens version
装完重启 dsh,在模型选择器里找带 (modlens vision) 后缀的条目。列表确认可以:
npx -y @deepseek-ai/dsh plugin --profile web list
若出现 declares no dsh.bundle,仓库的判断是发布冷静期装到了旧包,按宿主接入文档的「保持更新」一节处理,不要改去拷贝 Skill 目录。
web 只是文档里的示例 profile。实际 profile 名以本机为准,把 --profile 换成自己的即可。
配置一个视觉引擎¶
插件能挂上工具,但真正读图的是引擎。配置文件是 ~/.modlens/config.json,dsh 和其他 harness 共用。Web UI 用户可以打开 设置 → 插件 → 插件配置 里的卡片:选引擎、填 key / 地址 / 模型、授权本机哪些登录可被借用。卡片通过回环路由读写同一份文件,不会把已保存的密钥送进浏览器;密钥框留空表示保持原值。
仓库推荐的命令行起步是 Gemini API(Google AI Studio 申请,条款和额度以 Google 为准):
modlens config set gemini-api.apiKey
modlens config set provider gemini-api
不跟参数时,apiKey 会隐藏回显提示输入,避免 key 进 argv 和 shell history。想完全免注册,仓库给出的是 Antigravity CLI:
curl -fsSL https://antigravity.google/cli/install.sh | bash
agy
在浏览器完成登录后退出。无图形界面、SSH 无桌面的环境,文档建议不要走这条,改用 API key。
接 OpenAI 兼容的视觉模型(示例来自仓库 README,端点以各平台当前文档为准):
modlens config set openai.baseUrl https://dashscope.aliyuncs.com/compatible-mode/v1
modlens config set openai.apiKey
modlens config set openai.model qwen3-vl-plus
modlens config set provider openai
三个字段都要齐,且模型必须接受图片输入。同一套键可换成其他兼容网关。从 3.17.0 起,某个 provider 一旦写进配置文件,凭据就以文件为准,不再和 OPENAI_API_KEY 这类环境变量按字段混用,避免「地址来自文件、密钥来自环境」拼出一份两边都不存在的凭证。
体检¶
modlens doctor
成功时看两行:Selected provider 下面的名字,以及它在 Providers 列表里是否为 [ok]。其余 provider 显示 [!!] 是正常的。常见问题文档已经列过:Node 低于 22.19、Gemini 没写入 apiKey、agy 不在 PATH。加 --json 可拿到机器可读报告。
端到端试一次(会消耗一次识别额度):
modlens -i /path/to/image.png
典型用法¶
装好之后,在 dsh 里正常对话即可。下面几条都来自仓库文档和目录页,不是另行编造的案例。
1. 纯文本模型下直接粘贴截图¶
选普通的 DeepSeek-V4-Flash / DeepSeek-V4-Pro 这类纯文本条目,把报错界面或 UI 异常粘进输入框。浏览器半边把图片落成临时文件,路径进入 composer,模型调用 modlens_read_image,再根据 JSON 里的 OCR 和版面回答。目录页把这个变化概括成:从「帮我描述这张截图」变成「屏幕上到底有什么」。
2. 切到视觉变体,保留缩略图¶
在模型选择器里选 DeepSeek-V4-Flash (modlens vision)(或本机自动生成的对应条目),再粘贴。缩略图留在消息里,轨迹里可以看到图片在发请求时已被转写。仓库 README 用一张 DeepSeek Harness 贴图演示过这条路径,驱动的是纯文本 DeepSeek-V4-Flash。
注意仓库 issue #40 写明的限制:会话里一旦存在图片附件,dsh 会拒绝切回声明不含图片模态的普通纯文本条目。(modlens vision) 变体能切过去,是因为它在发请求时把图片块转成证据文本。走第一条「粘贴转路径」则不会产生附件,选择器也不会被锁住。
3. 文档页、设计稿、前端还原¶
目录页列出的三类场景:
- 文档提取:长 PDF 页、幻灯片、截图变成可查询的结构化数据
- 前端工作:给智能体看设计稿或渲染后的页面,按布局语义写或改代码
- 用截图调试:报错和 UI 异常直接贴进对话
需要大规模长截图 OCR 时,目录页建议再搭配 dsh-vision-toolkit(相关列表里对应条目是 agent-vision-toolkit)。modlens 自己定位的是「粘贴一张图,拿回一份证据 JSON」,不是长图流水线。
4. 仓库 README 里的实测记录¶
这些是 README 标明的原样记录,驱动模型都是纯文本 DeepSeek-V4-Flash,用来说明输出粒度,不是第三方评测:
- Codex 桌面里读推文截图:作者、配文、照片细节、时间和互动数字
- 一次三张图:逐张读取,并判断是否同属一个视觉家族
- 128 个模型的对比散点图:坐标轴、对数刻度、厂商配色、高亮区域和虚线标注的 DeepSeek 型号
- Claude Code 终端里粘贴幻灯片:标题、版式、背景;文件名被截断时写入
uncertainty,而不是编一个完整文件名
适用场景与注意事项¶
比较适合:
- 在 dsh 里用 DeepSeek / GLM 纯文本模型做编码,但经常要看截图、设计稿、报错界面
- 希望模型引用图上的具体文字和区块,而不是凭空描述
- 已经有 Gemini / 兼容视觉 API,或本机已登录 Claude Code、Codex 等,希望复用而不是再搭一套多模态网关
使用前注意下面几条,均来自目录页或仓库文档:
- 权限与许可证。 插件以当前 dsh 进程权限运行,安装时可能执行代码。安装前检查 源码 和 MIT 许可证。社区目录不是官方应用商店。
- dsh 仍是开发者预览。 插件接口可能变化。modlens 自称接触面很小(工具注册、视觉变体用的 llm 适配层、附件读取、一个 agent 执行前钩子),接口挪了会报错而不是静默失效。
- 图片内容按不可信输入处理。 截图里可以写给模型看的指令。安全文档要求:只分析你愿意打开的图;不信任的图优先钉死
-p gemini-api(由 modlens 下载字节、不跑本地 agent)。远程 URL 由谁抓取因 provider 而异:gemini-api本地下载并做私有地址 / magic-byte / 25 MB 检查;openai/anthropic把 URL 交给对方去抓;agent CLI 则自己去拉。 - 本机运行时。 需要 Node 22.19+。macOS / Linux 在 CI 的 Node 22 和 24 上验证;Windows 跑同一套矩阵,但 Antigravity、Claude CLI 等外部引擎只在有对应 Windows 构建的平台上可用。
- 临时文件。 3.18.1 起,paste-to-path 的文件集中存放并按一周或 1 GB 上限清理(先删最旧的),因为路径会进 composer,请求结束时不能立刻删。目录按不可信地面处理:解析后创建、拒绝符号链接和无法设为私有的目录。
- 不要用
@latest更新。 查出当前版本号再点名安装。Skill 安装流程只适用于 Claude Code / Codex / Pi / OpenCode,不要在 dsh 上走那条路。 - 仓库不接受 Pull Request。 作者说明是单人审阅全部代码。反馈走 Issues;MIT 下可以自行 fork。
- 上游额度自负。 Gemini、OpenAI、Anthropic、Antigravity 以及任何兼容端点,使用受各自条款约束。复用本机 CLI 时,结果里会标注花了谁的配额。
小结¶
modlens 要解决的问题很具体:dsh 背后的纯文本模型看不见图。它以原生插件接入,注册 modlens_read_image,按模型元数据决定是把粘贴变成文件路径,还是走 (modlens vision) 变体在发请求时转写;读图结果是带 OCR、版面、语义和不确定项的 JSON,而不是一段无法核验的描述。引擎可以是 Gemini、OpenAI 兼容端点,或本机已经登录的 agent CLI,配置集中在 ~/.modlens/config.json。
目录页与仓库:
- 社区目录:https://deepseek-harness-plugin.com/zh-CN/plugins/modlens/
- GitHub:https://github.com/liustack/modlens
- dsh 安装说明:https://github.com/liustack/modlens/blob/main/INSTALL.md
- 宿主接入:https://github.com/liustack/modlens/blob/main/docs/harness-setup.md
- 输出契约:https://github.com/liustack/modlens/blob/main/docs/output-schema.md
- DeepSeek Harness:https://github.com/deepseek-ai/deepseek-harness