🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

题图转写 Amethyst-Leafs/dsh-read-figure

DeepSeek Harness
Amethyst-Leafs18 天前有提交已提供中文文档扫描:无法判定

把题图交给视觉模型转写成可引用的文字,并标出噪点与不确定处

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/17 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Amethyst-Leafs/dsh-read-figure
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · vision
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 18 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/11/3) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
⚪ 扫描:无法判定尚无人工评估
展开查看扫描说明与证据 ↓

已尝试扫描但取不到可分析的源码:仓库或包不存在、已删除,或为非 JS/TS 实现、未随包发布源码。无法判定,不代表安全。

  • · 取源不可用(Error: github tarball HTTP 404 @ https:
  • · api.github.com
  • · repos
  • · Amethyst-Leafs
  • · dsh-read-figure
  • · tarball)
扫描于 2026/11/3(1 天前)

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
read-figure 给看不到图的纯文本模型补上一双眼睛,并且规定这双眼睛看到的东西要怎么汇报。 read-figure 是一个 DeepSeek Harness(DSH)插件。它是唯一一件工具 read_figure: 你把磁盘上的题图路径交给它 → 它请一个视觉模型按固定三段式协议转写这张图 → 把转写结果作为纯文本注入你的上下文 → 你据此作答。 它不替你解题,也不该替你解题。它做的是一件更窄、也更难做对的事: 把「图里有什么」这件事,说清楚到可以被引用、被追问、被审计。 为什么需要它 DSH 本身已经能把附件图片送给有视觉能力的模型。但下面这件事没人做: - 纯文本模型(例如 deepseek-v4-pro)拿到了一张图片的路径,它既看不到图,也没有办法让「能看图的模型」帮忙看一眼; - 就算能转述,转述的质量没有契约——哪里没看清、哪里是猜的,读的人无从判断; - 扫描题图里常出现与所有线条都不相连的游离小黑点。 人类一眼判定「扫描噪点」,纯文本模型看不到图,只会把它读成质点、铰点或标注符号,于是凭空多出一个质点,整道题的受力分析全错。 最后那条是本插件立项的直接原因:一张 CPhO 复赛题图右上角有一个 3×3 像素、面积 6 像素 的孤立墨点,图题里专门写了「应视为扫描噪点,不是质点」——而这句提醒,恰恰是看不到图的模型最需要、也最容易漏掉的一句。
展开完整文档(README 剩余 1 节)
read-figure

给看不到图的纯文本模型补上一双眼睛,并且规定这双眼睛看到的东西要怎么汇报。

read-figure 是一个 DeepSeek Harness(DSH)插件。它是唯一一件工具 read_figure:

你把磁盘上的题图路径交给它 → 它请一个视觉模型按固定三段式协议转写这张图 → 把转写结果作为纯文本注入你的上下文 → 你据此作答。

它不替你解题,也不该替你解题。它做的是一件更窄、也更难做对的事: 把「图里有什么」这件事,说清楚到可以被引用、被追问、被审计。

为什么需要它

DSH 本身已经能把附件图片送给有视觉能力的模型。但下面这件事没人做:

- 纯文本模型(例如 deepseek-v4-pro)拿到了一张图片的路径,它既看不到图,也没有办法让「能看图的模型」帮忙看一眼;
- 就算能转述,转述的质量没有契约——哪里没看清、哪里是猜的,读的人无从判断;
- 扫描题图里常出现与所有线条都不相连的游离小黑点。
人类一眼判定「扫描噪点」,纯文本模型看不到图,只会把它读成质点、铰点或标注符号,于是凭空多出一个质点,整道题的受力分析全错。

最后那条是本插件立项的直接原因:一张 CPhO 复赛题图右上角有一个 3×3 像素、面积 6 像素 的孤立墨点,图题里专门写了「应视为扫描噪点,不是质点」——而这句提醒,恰恰是看不到图的模型最需要、也最容易漏掉的一句。

机械像素扫描:不靠模型的眼睛,靠连通域分析

只把图交给视觉模型是不够的。实测里它做对了很多事,却做不对一类事:测量。

同一张 figures/1.jpg,同一个问题「那个孤立黑点在哪、多大」:

| 谁 | 位置 | 尺寸 |
| 视觉模型第 1 次 | 没能看见,只在「不确定」里写了条件句 | — |
| 视觉模型第 2 次 | 滑轮 B 右侧 x≈700~710, y≈1750~1760 | 约 8×8 像素 |
| 连通域分析 | (1124, 225) | 3×3 像素,面积 6 |

模型给出的坐标错了近千像素,而错的坐标比不给坐标更糟——它读起来像实测值。
所以插件自己解 JPEG/PNG、自己做连通域分析,把精确数字塞进提示词,并规定模型只能采用、不能覆盖。

这一层同时承担三件事:

1. 给准数:位置(百分比 + 像素中心)、尺寸、面积、最深处灰度、周围纸面灰度。
实测两张题图的孤立墨点一个是 3×3(面积 6)、一个是 31×47(面积 1139),差两个数量级,两张都被准确报出。
2. 防臆造:提示词里逐字写明「无论结论是什么,都不许因为这里列出的任何一块墨而新增质点、铰点、节点或滑轮」,并要求模型自己判断它算噪点还是算标注点、把理由写进「三、不确定」。
3. 挡假阳性:这条比第 1 条更要紧,因为「报出来就会被当真」。已处理的假阳性:
- 贴边残留(扫描裁切出的黑边)单独列为「边缘截断」,绝不作为记号;figures/2.jpg 有 7 处。
- 空心字形用填充率剔除(一个 107×102、填充率 0.25 的圆环不是墨点)。
- 虚线:figures/7.jpg 的中线由一串短实线段组成,与游离墨点在几何上无法区分。
靠「大小相近 + 等间距 + 共线」把竖排和横排的虚线各归成一段,游离墨点数从 9 降到 5。
虚线-点线只识别出一部分,提示词里对此明说了这一限制,并要求模型据实描述未列入的短段。

扫描失败时(解不开的编码、异常文件)不阻断转写:那一节留空,视觉模型照常工作,失败原因记进出处行。扫描是增强,不是前提。

它输出什么

固定三段式,段落标题一字不改:

识图交接件 · 第 1 题

由 read-figure 自动生成,视觉模型 deepseek-flash,<时间>。
源图:figures/1.jpg(1536×2711px,183 KB)分工:图像描述与复述由看图模型完成,物理解答由纯文本模型完成。本文件不含任何解答。

一、图的结构(逐项描述)按「连接方式 → 各构件及其标注 → 几何量与坐标系」逐项写,禁模糊词。

二、复述一段话讲清物理情境,然后分列「已知量 / 待求量 / 图外补充的物理条件」。

三、⚠ 读图置信度声明
- 高置信:…
- 不确定:右上角约 6×10 像素的游离小黑点,与任何线条不相连,判为扫描件噪点。
若纯文本模型看到本条,请勿据此引入额外质点或铰点。

给纯文本模型的执行说明(请一并遵守)
1. 不要凭常识补图 …
2. 符号解优先 …
3. 结论若依赖「不确定」条必须停下指出 …
4. 提出追问清单 …
5. 答案在推导句内收口 …

协议正文是一个 markdown 文件(prompts/figure-handoff.zh.md),不是代码里的字符串。
你可以直接改它,或用 promptFile / extraInstruction 指向你自己的版本—— 这个插件 70% 的价值在协议本身,而不是在那几百行 HTTP 代码。

三份真实输出在 examples/:逐字保留,取自 2026-10-17 的实跑,只把本机绝对路径换成 <本机路径>。它们同时展示了两种模式(整图交接件 / 定向追问),也说明了 maxTokens 为什么缺省 32000——那一页的思考链占了 completion 的 92.8%。

安装

方式一:交给插件管理器(推荐,本仓库就是这么装上去验证的)

让代理调用 plugin_manager,或等价的 CLI 包操作:

plugin_manager install_bundle https://github.com/Amethyst-Leafs/dsh-read-figure
plugin_manager install_bundle ./path/to/read-figure # 本地目录,开发时用

install_bundle 会走 pnpm add 把包装进 profile,并按包里的 cordis.patch.yml 声明把它加进 profile 的 bundle 栈,不需要手工改 profile 文件。

装完必须重启 dsh。 host 插件在进程启动时就挂载好了,重启才会出现 read_figure 工具。
(本仓库在 desktop profile 上的实测结论:第二次安装返回 application: restart-required,说明 mount 期没有报错;装之前那次返回的是 failed,因为当时的 Config 不是 Standard Schema。)

方式二:手工挂载

在 profile 的 cordis.patch.yml 里加一行:

- id: read-figure
name: read-figure
config:
model: deepseek-flash
apiKey: sk-… # 见下面「密钥」

注意这是按 id 覆盖:config 是整块替换、不会深合并,要改就重述你想留的全部字段。
(本包自己的 cordis.patch.yml 故意不写 maxTokens,让它回落代码里的缺省值——行值优先于缺省值,写在那儿就等于给所有人钉死一个数。)

方式二:手工挂载

在 profile 的 cordis.patch.yml 里加一行:

- id: read-figure
name: read-figure
config:
model: deepseek-flash
apiKey: sk-… # 见下面「密钥」

方式三:完全不装(零安装验证)

CLI 与插件共用同一套代码,所以你可以先不装插件就验证协议质量:

node bin/read-figure.mjs --img figures/1.jpg --img figures/2.jpg --out out/handoff.md

配置

| 键 | 缺省 | 说明 |
| baseUrl | https://api.deepseek.com | 任何 OpenAI 兼容的 /chat/completions 端点 |
| model | deepseek-flash | 视觉模型名 |
| apiKey | '' | 空则依次读 READ_FIGURE_API_KEY、DEEPSEEK_API_KEY |
| maxTokens | 32000 | 已高于实测上限(3094×1526 扫描件、effort: high 时思考链约 29k 字符);调低就会重现「正文为空」 |
| reasoningEffort | high | low / high / max |
| timeoutMs | 180000 | 单次请求超时 |
| promptFile | '' | 空则用包内 prompts/figure-handoff.zh.md |
| extraInstruction | '' | 追加到协议末尾,对本次会话的所有调用生效 |
| handoffDir | '' | 非空时,outPath 必须落在该目录内 |
| writeHandoff | false | 保留位:是否默认落盘 |

密钥

运行中的 DSH 读不到你启动之后才导出的 shell 变量。
如果配了环境变量却不生效,请把 apiKey 直写进 cordis.patch.yml 的那一行。

工具用法

第一次转写

{ "imagePath": "output/…/figures/1.jpg", "label": "第 1 题" }

多图:{"imagePaths": ["figures/1.jpg", "figures/2.jpg"], "label": "第 1、2 题"}

定向追问(追问回路)

交接件里有「不确定」项时,不要重跑整份交接件,而是把问题问回去:

{
"imagePath": "figures/1.jpg",
"question": "B 左侧垂下最长的那段绳,末端吊的是 m₂ 还是 m₃?两种读法分别会带来什么差别?"
}

追问只回答这一条,并会要求视觉模型给出位置 + 看到的形状/像素量级作为依据;若两种读法都说得通,它会明说,并写出各自导致的物理图景差别。

设计取舍

- 只做转写,不做推理。 协议里第一条硬性纪律就是「绝对不许解题」。
一旦视觉模型开始算,交接件就从「可审计的观察记录」退化成了「一份质量不明的解答」,而读它的模型既无法验证、也无法追问。
- 不确定项必须显式列出,且必须带防护句。 报出「这里有个小黑点」本身是危险的——如果不说清「它是噪点,别据此引入质点」,纯文本模型会把它当真。所以协议要求:位置 + 像素尺寸 + 判断 + 理由 + 防护句,五件齐全。
- 假阳性比漏报更危险。 这一点来自实测:机械噪点检测器第一轮在一张图上报了 7 处候选,坐标全是 x≈1 或 y≈1——那是扫描边界被裁切留下的黑边。
若原样注入模型,它会以为题目真有 7 个额外标注。
任何「机械证据」交给 LLM 之前,都必须先有假阳性抑制规则。
- 阈值不随分辨率缩放。 看上去该按图像大小缩放像素阈值,其实不该: figures/2.jpg 的孤立墨点(面积 1139)在面积上正好落在字形之间(figures/1.jpg 的字母 A 是 871,figures/2.jpg 的 M 是 6756), 没有任何面积切分能把墨点和字母分开。真正分开它们的是「小而实」:这些图里的字母要么某一维 ≥ 70 像素,要么是空心的(填充率 ≤ 0.47)。
这条教训有测试钉住——按 1.jpg 调出来的上限(面积 ≤ 600)会把 2.jpg 的墨点整个丢掉。
- 尺寸必须来自文件头。 交接件里「某个黑点有多大」是可引用的事实,所以像素尺寸从 JPEG/PNG 头里读出来,不采信调用方的说法,也不依赖 sharp 之类可能没装的原生依赖。
- 机械证据只作为「候选」报出,不作为结论。 提示词里写的是「扫描程序发现了这些痕迹, 它无法判断这是有意画的还是意外」,并且明说「与图形不相连的墨痕仍可能是故意画的」。
把一个模型无法申辩的机器结论塞给它,就是把一次假阳性变成一次凭空的质点。
- 一个共享管线,两扇门。 插件工具与 CLI 都走 lib/describe-figure.mjs,改一次协议只需改一处。
- 没有客户端半边。 工具结果是纯文本,任何会话界面本来就会显示,所以不需要 client bundle。
- 缺省值只有一个来源。 lib/index.mjs 的 Loader Config 是从 DEFAULTS 生成的,不再复述字面量。
手抄的第二份已经漂过一次——schema 写 maxTokens: 8000、规范化器写 32000——而空 config 恰好会落到 schema 那份,于是全新安装拿到的是一份空交接件。
bundle 行同样被断言必须与 DEFAULTS 一致,理由相同。

它真的有用吗?

这个插件的全部意义在于:看不见图的模型也能解出带图的题。所以量的是这件事。
用一对 CPhO 题图(定滑轮+动滑轮;斜面上的滑块)实测:

| 步骤 | 模型 | 结果 |
| 转写图像 | deepseek-flash(有视觉) | 45–78 s,输出 12–15 k token(其中 70–80% 是思考) |
| 仅凭交接件解题 | deepseek-v4-pro(纯文本) | 两题均正确,已独立复核 |

deepseek-v4-pro 的 input_modalities 是 ["text"]——完全没有视觉。
它仅凭交接件就给出:滑轮题 a₁ = 0.2 m/s²(向下)、滑轮 B 0.2 m/s²(向上), T = 48 N、T′ = 24 N;楔子题 a_B = mg sinθcosθ/(M + m sin²θ), N_table = Mg(M+m)/(M + m sin²θ) = 68.17 N。上述每一项都在本仓库里用牛顿法与拉格朗日法两条独立路线对过。

实测还教了两件事:

- 方向是最薄弱的一环。 大小都对了,但楔子的符号约定给反了——因为纯文本读者没有任何办法把朝向对照原图核实。
一份没有把「哪一端更低」写死的交接件,就是一份会被读反的交接件。
- 交接件里的猜测不是证据。 同一处形状问了两次,视觉模型两次都答「三角形」,而像素级目视是矩形。再问一次只会强化误读,不会纠正它。
凡是能靠裁剪放大自己看的问题,就去裁剪放大;数字交给 lib/scan.mjs。

插件市场兼容

本包既是一个普通的 DSH bundle(dsh.bundle.patch),又带一份符合已发布规范 DSH Plugin Manifest Community Draft v0.15 的 dsh-plugin.json。

npm run validate:manifest # 联网取 schema 并校验
node tools/validate-manifest.mjs --offline # 用仓库里那份副本校验

清单里有一个值得记下的决定:schema 的 id 是 namespaced id,正则 ^[a-z]a-z0-9+$ 要求至少含一个分隔符,所以裸的 read-figure 不合规,本包用的是 read-figure.tool。
另外 facets.host.entry 被断言必须等于 package.json 的 exports["."],以免市场以为加载的入口和运行时实际加载的不是同一个文件。

开发

node bin/read-figure.mjs --self-check # 离线自检:协议装配、配置、写盘边界
node tools/check.mjs # 175 项契约自检(含清单、挂载与端到端)
node tools/validate-manifest.mjs --offline # 用真 schema 校验 dsh-plugin.json
node tools/selftest-types-check.mjs # 证明第 13 节不是空断言(见下)
npm run lint # 对每个随包发布的 JS 文件做语法检查

lib/index.d.ts 是手写的:实现是纯 ESM JavaScript,这个文件只是让消费者(以及 harness 自己的工具)不必读源码就能看到形状。手写就会漂移,而它已经漂移过,且方向不止一个:它声明了 defaults、DEFAULTS、probeImage、decodeGray、 decodeGrayPng、findSpecks——但 lib/index.mjs 从来没导出过它们;同时漏掉了实际存在的十二个导出。前者比没有类型声明更糟: TypeScript 会接受这个 import,编辑器会补全它,而运行时拿到的是 undefined,中间没有任何一步会报错。

所以第 13 节把 .d.ts 的导出名与 lib/index.mjs 的活体导出双向对比,并按「值 / 纯类型」分开——interface、type 在运行时被擦除,声明它们不算承诺;const、function、class 才是承诺。
只比对名字,不比对类型(文本解析器判不了类型),但它能抓住改名、删除、以及那些从未兑现的承诺,也就是真正出过事的那三类。

tools/selftest-types-check.mjs 是这一节的变异测试:它把第 13 节从 check.mjs 里提取出来,在一份临时副本上注入五种漂移(凭空声明、改名、删声明、删运行时导出、把 DEFAULTS 改名),要求每一种都被抓住、且未被变异时全绿。它不改仓库里的任何文件——一个「改了再还原」的自检脚本在两次写之间被打断就会弄丢源码,而一个能弄坏被测仓库的自检不算自检。

tools/check.mjs 里的端到端一项会起一个本地 HTTP 桩服务,真跑一遍 execute,检查请求体(模型、max_tokens、reasoning_effort、data URL)与装配出的文本。不联网。

tools/check.mjs 第 10 节用合成图验像素层:合成图由 tools/png-fixture.mjs 现编码,尺寸与位置都已知,所以「6×6 的墨点必须被报成 6×6」是可断言的。
该节还断言两张真实题图的墨点坐标与面积——它们差两个数量级, 一个调错的上限只会让其中一张通过,所以两张都要在测试里。

许可

MIT
预览分享卡片长什么样 ↓Amethyst-Leafs/dsh-read-figure
分享 · DeepSeek Harness Hub
Amethyst-Leafs/dsh-read-figure

把题图交给视觉模型转写成可引用的文字,并标出噪点与不确定处

这是你的仓库?认领条目

回到顶部