dsh-web-ui/packages/dsh-tool-describe-image

5.1kStar310Fork49Issue5Watching

为纯文本模型增加图像理解能力:拖入图片后自动调用视觉模型描述图片内容,仅文本进入会话。

语言
TypeScript
License
Apache-2.0
分支
dev
deepseek-harnessdshdsh-pluginweb-ui

安装

$ dsh plugin --profile web add github:zhu1090093659/dsh-web-ui/packages/dsh-tool-describe-image

在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程

一句话定位

为 DSH Web GUI 增加模型侧的 describe_image 工具:让纯文本模型(DeepSeek V4 等)也能读懂图片——会话里拖入或粘贴一张图,插件自动把图片发给视觉模型(Qwen-VL、GLM-4V、GPT-4o、Claude 风格、本地 Ollama 等),只把返回的文字送回对话,图片本身不进入会话日志。

核心能力

  • 提供 describe_image 模型工具:模型可调用它让视觉模型描述任意图片(本地绝对路径、http(s) URL、附件引用、自描述 Markdown 引用),返回结构化结果 { text, model, image, mimeType, bytes },模型侧只看到 text(src/index.ts:189-232)。
  • 拖拽 / 粘贴图片自动改写:在纯文本会话里把图片块改写成 ![图片](/describe-image/raw/sha256:...?ref=...) 引用,图片字节通过 /describe-image/attach 路由上传(校验 base64、magic bytes 与字节上限),持久化到附件存储,只有引用文本进入会话(src/attach-routes.ts:1-13)。
  • 模型能力自适应:每次发送前通过 /describe-image/capability 探测当前会话模型是否声明 image 输入;声明了直接把原图交给模型原生视觉并隐藏 describe_image 工具(包括 run_code 嵌套调用),未声明则走改写路径(src/model-capability.ts:1-22 / src/client/send-hook.ts:97-103)。
  • 实时配置卡:「设置 → 插件配置 → Web UI 插件 → Image understanding」卡可改 baseURL / apiStyle / model / API key / 默认指令 / 各项上限(走设置服务),即时生效无需重启(README.md:23)。
  • 端点连通与模型枚举:「获取模型」控件调 /describe-image/models 列出端点可用模型 id(解析草稿值以验证未保存的连接),列表切换为下拉选择;「测试连通性」控件以 max_tokens=1 最小补全测模型往返延迟(README.md:24 / src/model-probe.ts)。
  • 多协议视觉端点:内置 chat-completions(默认 /chat/completions)、responses(OpenAI Responses API 的 /responses)、anthropic-messages(Claude 风格 /v1/messages + x-api-key),适配 OpenAI、Qwen、GLM、Kimi、OpenCode Go 等不同厂商(src/config-resolve.ts:29-32 / README.md:75)。

技术实现

  • 语言: TypeScript(host 半区 + 浏览器半区双 program,参照 packages/AGENTS.md:16-19)
  • 关键依赖: @deepseek-ai/dsh-tools(注册 describe_image 工具)/ @deepseek-ai/dsh-settings(设置区与命名空间)/ @deepseek-ai/dsh-credentials(凭证解析)/ @deepseek-ai/dsh-llm(模型路由解析)/ schemastery(配置 schema)
  • 架构模式: cordis bundle 双半区包——host 半区(src/index.ts,注册工具、注册 attach/raw/capability/native-images/models 路由、安装设置区);浏览器半区(src/client/,挂载发送钩子、能力探测、缩略图预览、设置卡 React 组件);两端通过官方 NPM SDK 解耦(package.json:28-42 / cordis.patch.yml:13-15)
  • 入口文件: host 入口 src/index.ts(apply 函数 137-233 行);浏览器入口 src/client/index.ts(apply 函数 72-148 行)

适用场景

用户日常用 DeepSeek V4 这类纯文本模型与 DSH 对话时,遇到需要读图的任务——截屏报错、UI 截图诊断、拍照发图、扫描件 OCR——直接拖入输入框即可。模型看不到图片字节本身,而是收到一段引用与上下文,再调用 describe_image 把图片发给视觉模型,让模型侧既能聊纯文本又能像多模态模型一样读图。

前置依赖与兼容性

依赖最低版本说明
DeepSeek Harness (DSH)0.1.0-rc.8所有 @deepseek-ai/* 依赖锁定 ^0.1.0-rc.8(package.json:61-73)
Node.js^22.19.0 或 >=24.0.0package.json#engines(package.json:7-9)
平台跨平台仅使用 Node 内置模块(node:fs/promises、node:crypto、node:http),无原生模块依赖
原生模块

安装方式

dsh plugin --profile web add github:zhu1090093659/dsh-web-ui/packages/dsh-tool-describe-image

配置项

配置类型说明默认值
baseURL字符串(必填)视觉模型端点根地址,按协议自动追加 /chat/completions / /responses 或归一化为 /v1/messages;末尾斜杠自动去除;仅接受 http(s)
model字符串(必填)视觉模型 id,可带思考控制后缀::off 显式关闭思考,:low :medium :high 开启思考,不带后缀则不发送思考控制字段
apiStyle枚举视觉端点协议:chat-completions(默认,OpenAI 兼容)、responses(OpenAI Responses API)、anthropic-messages(Claude 风格,x-api-key 鉴权)chat-completions
apiKey字符串(密钥)内联 API key,本地调试用,建议用环境变量而非明文
apiKeyEnv环境变量名凭证引用:先看 dsh-credentials 服务,再回退到启动环境VISION_API_KEY
defaultPrompt字符串模型未传 prompt 参数时的兜底指令(OCR、UI 评审、翻译等场景可按需调优)一段描述图片客观内容并转录可见文字的指令
maxBytes整数图片字节上限(本地文件与下载 URL 一致)10485760(10 MiB)
maxOutputTokens整数单次输出 token 上限1024
timeoutMs整数单次视觉请求超时120000(120 秒)
renderImagePreview布尔把会话里图片引用原地升级为缩略图(点击看大图);仅影响本地显示true
interceptImageSend布尔发送时改写图片块为 describe-image 引用;关掉可让其他视觉插件接收原图true

常见问题

Q: 模型本身已经支持图片输入,还需要装这个插件吗?

A: 不需要。插件会在每次发送时通过 /describe-image/capability 探测当前会话模型是否声明 image 输入;声明了就把原图直接交给模型原生视觉能力,并自动隐藏 describe_image 工具,避免重复。

Q: 安装后一定要立即配置 endpoint 吗?

A: 不强制。全家桶聚合包默认无配置挂载,加载不受影响;首次调用会以 describe-image: baseURL must be an absolute http(s) URL 错误退出,到「设置 → 插件配置 → Image understanding」卡填好端点、模型、密钥即可使用,无需重启。

Q: 怎么切换视觉模型协议(OpenAI 风格、Anthropic 风格)?

A: 设置卡的「API style」字段控制:chat-completions(默认)请求 /chat/completionsresponses 适配 OpenAI Responses API;anthropic-messages 用于 Claude 风格端点(OpenCode Go、智谱 GLM、月之暗面 Kimi 等),走 /v1/messages 并使用 x-api-key 鉴权。

Q: 模型 id 后面的 :off / :low / :medium / :high 是什么意思?

A: 思考控制后缀。:off 显式关闭思考,:low :medium :high 开启思考(chat-completions 协议三档都映射为 enabled,因为该协议没有 effort 档);不带后缀则不发送控制字段,沿用端点默认。仅这四个已知后缀会被剥离,其他冒号变体(如 OpenRouter 的 :free)会原样转发。

Q: API key 应该怎么放?

A: 推荐走环境变量:把密钥放到环境变量 VISION_API_KEY(或 apiKeyEnv 自定义名),用 !!js process.env.VISION_API_KEY 注入到 cordis 配置;插件在每次调用时按「内联 apiKey → 凭证服务(dsh-credentials)→ 启动环境」三级回退解析,密钥不会出现在请求体里,也不会进入日志。

Q: 「会话内渲染图片预览」开关要不要开?

A: 默认开(renderImagePreview: true)。开启后客户端会把发送的 describe-image 引用原地升级为缩略图,点击查看大图;关闭则保留原始引用文本。两者都只是显示层差异,对消息文本与模型分析没有影响。如果反向代理没转发 /describe-image/raw 路由,缩略图会加载失败,文本仍按原样保留。

Q: 怎么让其他视觉插件接管图片处理?

A: 关闭设置卡的「发送时改写图片为 describe-image 引用」开关(interceptImageSend: false)。关闭后带图片的发送原样放行,由同会话的其他视觉插件接收原始图片块;此时纯文本模型的改写需要由它们自己负责。

Q: 一个调用能传多张图或获取结构化结果吗?

A: 不支持。插件只支持单图单答:不接受多图输入、不能追问上一张图、不输出坐标或框选这类结构化字段;纯 OCR 场景可以把 baseURL 指向更便宜的 OCR 模型降低单次成本。

上手难度

进阶 — 多数场景安装即用,但要发挥多协议 / 思考控制 / 原生图片切换这些能力需要理解视觉模型协议差异与会话模型能力,零基础用户可能需要先读 README 才能用对设置项。

已知问题与限制

  • 仅 magic-byte 门校验类型、不解码图片:头合法但内容损坏的文件会在视觉端点才报错(README.md:177-178)。
  • 单图单答:不支持多图输入、追问上一张图、结构化输出(坐标 / 框)(README.md:179-180)。
  • 三种协议固定:仅支持 Chat Completions、Responses、Anthropic Messages——其他请求 / 响应形态的厂商需要新增适配器(README.md:182-184)。
  • 思考后缀是插件简写,会向请求注入厂商专用字段(thinking.type / reasoning.effort);不接受这些字段的端点(如普通 OpenAI 视觉模型)应使用不带后缀的模型 id(README.md:185-191)。
  • 模型能力探测保守失败:探测失败时一律按「不接受图片」处理,沿用改写路径,避免误判导致原图被送给纯文本模型后被宿主拒绝(MODEL_DOES_NOT_SUPPORT_IMAGES)(src/model-capability.ts:18-22)。