dsh-patent-figure-annotation
Verifieddsh-patent-figure-annotation · v1.4.5 · MIT
DSH 插件:只取【说明书附图】页,在附图标记旁叠加中文释义(深红 #B22222、透明底),并在 PDF 末尾追加「附图标记-中文释义对照表」。
Install
dsh plugin add dsh-patent-figure-annotation Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Readme
专利说明书附图附图标记中文加注
一个 DeepSeek Harness(DSH)插件:把「附图标记-中文释义对照表」附在所提供的中文专利原件或中文译文的最后——宿主自带【说明书附图】时把那几页就地替换为加注版(正红 #FF0000、透明底、原图一个像素都不改);中文译文没有附图部分时,用 figuresFrom 指定图纸来源(通常是外文原件),把加注后的附图追加在宿主之后,再放对照表。原文没有定义的标记绝不编造释义。
安装
方式一:npm(推荐,不需要本机安装 git)
DSH 桌面端 → 侧栏「插件」→「添加插件」,输入:
dsh-patent-figure-annotation
方式二:从 Gitee 仓库安装(需要本机已安装 git;地址必须带结尾的 .git)
https://gitee.com/hc905/dsh-patent-figure-annotation.git
不带
.git的裸地址(https://gitee.com/hc905/dsh-patent-figure-annotation)会被 pnpm 当成 tarball 去解包,报ERR_PNPM_TARBALL_EXTRACT;实测 pnpm 11.7.0 必须带.git。
装完重启 DSH。
方式三:本地路径(离线包)
link:<解压目录>/plugins/dsh-patent-figure-annotation
注意:同一台机器不要同时安装
@local/版本和 npm 版本——两者的挂载 id 相同,会冲突。
它解决什么问题
把一份专利 PDF 变成一份可交付的中文加注版整册文件,中间有一堆"人容易做错、机器容易做对"的事:
| 容易出错的地方 | 插件怎么强制 |
|---|---|
| 只交附图、宿主稿件别的内容丢了 | 输出 = 宿主全文 +(必要时)加注附图 + 对照表,宿主页序/尺寸/旋转角不变 |
| 顺手动了宿主里的其他页面 | 未加注页面要求与宿主内容流逐字节一致,并抽样逐像素复核;追加模式下宿主一页都不许变 |
| 中文译文没有附图,只能手拼 | figuresFrom 指定图纸来源,插件自动「宿主 + 加注附图 + 对照表」拼成一份 |
| 二次栅格化把线条弄糊、把原有标记抹掉 | 不重新绘制:页对象整体复制,只在上面叠一个文字对象 |
| AI 自行翻译、意译、缩写术语 | 释义只能由调用方给出,工具不生成任何术语 |
| 原文无定义的标记被"猜"出释义 | 没有 label 就必须 undocumented: true,只登记不加注 |
| 对照表另存成单独文件、或排错位置 | 对照表永远排在全文最后(同一份 PDF),verify 检查位置 |
| 标注压住引线、轮廓线或原标记 | 用 200 DPI 渲染出的墨迹密度给候选位置打分,见下文 |
| 标注互相重叠、出界 | 候选框与页面已占用文字框逐一求交,出框即淘汰 |
| 白底块破坏原图 | 逐算子证明"附图页没有新增任何路径对象" |
| 颜色、字号走样 | 颜色由 enforceStyle 锁定(正红 #FF0000),字号默认取原标记字号 |
提供的工具与技能
| 名称 | 类型 | 作用 |
|---|---|---|
patent_figure_outline |
工具 | 读专利 PDF,判定每页章节归属,给出【说明书附图】起止页与需排除的摘要附图页;同节重复页眉合并成一节,整份没有文字层的扫描件走 72 DPI 像素判定区分图纸/正文 |
patent_figure_inspect |
工具 | 按 ≥200 DPI 渲染附图页为 PNG(供看图),并返回文字层每项的 bbox/归一化坐标与疑似附图标记 |
patent_figure_annotate |
工具 | 生成加注版:宿主全文 +(就地替换或追加的)加注附图 + 末尾对照表 |
patent_figure_verify |
工具 | 交付前自检,10 项校验,见下 |
patent-figure-annotation |
技能 | 完整作业流程:释义来源优先级、标注规范、自检清单、故障处理 |
输出结构
inputPath 是宿主——要附到的那份文件(中文原件或中文译文);figuresFrom 是图纸来源(通常是外文原件),省略时即等于宿主。
宿主自带【说明书附图】(不给 figuresFrom)
输出 = 宿主第 1…页(pages 指定的附图页 → 原位换成"原图 + 正红中文标注")
+ 「附图标记-中文释义对照表」(1..n 页,排在全文最后)
中文译文没有附图部分(给 figuresFrom)
输出 = 宿主第 1…页(一页未改)
+ 图纸来源 pages 指定的附图页(加注后追加)
+ 「附图标记-中文释义对照表」(全文最后)
- 对照表不再单独出文件,标题锁定为「附图标记-中文释义对照表」,永远排在全文最后(附图后面若还有摘要附图等章节,对照表仍在其后)。
- 输出总页数 = 宿主页数 +(追加的附图页数)+ 对照表页数。
- 对照表版式(四列照《对应关系说明-格式规范》第六条的排版规则,插件强制):四列
附图标记|中文释义|出现位置|来源,列宽[1700, 3400, 1900, 2638]twips 按可用宽度等比缩放;标题 14pt 居中;表头与正文 9pt、行距 11.5pt、统一最小行高 29pt;表头浅灰#F2F2F2全列居中,数据行首列居中、其余左对齐;每格四边 0.5pt 灰线;页边距 36pt;一行不跨页,续页重复表头并标「(续)」;表下无任何说明性文字。- 「出现位置」=
第 4 页;同一标记+同一释义出现在多页时合并成一行写第 4、5 页。 - 「来源」=
中文原文/中文译文/原文翻译/用户指定;原文无定义的条目写原文无定义(第二列写「(原文无定义)」);调用方另给的note接在来源后面,如中文原文;原文以"金属壳体 HS"表述。
- 「出现位置」=
- 整份文档统一内嵌宋体(本机可嵌入的是华文宋体
STSONG.TTF;缺字形时按 宋体→仿宋→黑体→等线→楷体 自动退让并在warnings里说明)。
五条硬保证(都由 patent_figure_verify 独立复核)
- 宿主原样保留。 逐页比对内容流字节:每页的原始内容流必须原样出现在输出页里;未加注页面还要求与宿主逐字节一致(就地模式下附图页除外),并抽样做逐像素渲染比对。追加模式下宿主整份必须逐字节不变。
- 附图页只多了文字。 逐像素比对:把本次标注框遮住后,输出页与图纸来源页在 150 DPI 下必须完全一致(默认容差 0,因为页内容是整体复制的)。
- 没有白底/背景色块。 统计源页与输出页的路径类算子(
constructPath/fill/stroke…),附图页不得新增任何一个——加了矩形必然被抓。 - 对照表位置正确。 必须排在全文最后;追加模式下它前面必须正好是追加进来的附图末页。
- 对照表完整。 必须出现表标题、每个标记、每条释义(折行也认),以及原文无定义条目的【原文无定义】。
另有五项:输出页数 = 宿主 +(追加附图)+ 对照表;标注是否齐全且位置与报告一致;颜色算子中出现 #FF0000 的次数是否覆盖全部加注。
标注位置怎么来的
一切都用归一化渲染坐标表示:页左上角为原点,x 向右、y 向下,取值 0..1 —— 与 patent_figure_inspect 输出的 PNG 同一坐标系,所以从图上看中的位置可以直接写进 position。
自动放置时,插件为每个标记生成"右 / 下 / 上 / 左 × 9 圈"的候选框,同一圈内按右 → 下 → 上 → 左取第一个干净的位置,依次淘汰:
- 超出页面边距(默认 18 pt);
- 与任何原有文字框相交(因此永远不会盖住原附图标记),或与本页已放标注的间隙小于 2‰;
- 墨迹占比超过
cleanInk(默认 1.5%)。
所以标注默认落在标记右侧同一行;右侧被引线/轮廓占满或出界时退回标记正下方(左对齐,不会滑到旁边标记下面),再退到正上方、左侧。"下/上"与标记左对齐而不是居中,正是为了避免标注跑到相邻标记底下。长释义(如「最靠近近端的基板」)单行放不下时会自动折成两行再试一次。空间实在不够时才退而求其次,并在 warnings 里说明。
同一页同一标记重复出现(如六个 130)由 occupied 逐条互斥,不会互相覆盖。
扫描件(无文字层)怎么定位
扫描件里标记是像素而不是文字,文字层找不到目标。此时有两种办法,二者可以并用:
near锚点:给该条注解传near:{x,y}(归一化坐标,取自patent_figure_inspect的 PNG 或rasterNumerals),插件把它当作"标记所在位置"的小框,走完全相同的右/下/上/左候选逻辑,并在该条警告里注明"已按 near 锚点放置,请人工确认"。注意near指标记本身的位置,position指标注文本框的位置。detectRasterNumerals:把patent_figure_inspect的该参数设为true,插件对渲染图做连通域分析,返回每页rasterNumerals疑似标记框(尺寸/墨迹密度/周围留白三重过滤)。这是启发式候选、不做 OCR、ref留空:必然有少量漏检与"图注/尺寸数字被当候选"的误检(实测 CNIPA 扫描件单页 19 个候选、命中 18、漏 2、误检 1 个图注),必须对照导出的 PNG 人工确认后再取用。
释义来源优先级(写进技能,工具只记录 source 字段)
user—— 用户单独指定的译法(最高优先,例如 HS 一律"热沉");zh-original—— 中文专利原文的「附图说明」「具体实施方式」;translation—— 配套中文译文中的对应术语;translated—— 无中文译文时,基于原文翻译。
同一标记在不同实施例有多个限定术语时取最上位概念;全文都没有定义 → undocumented: true,只进对照表。
典型用法
patent_figure_outline({ path: "D4-WO2009011218A1.pdf" }) // 图纸来源是外文原件
patent_figure_inspect({ path: "D4-WO2009011218A1.pdf", pages: [60,61,62] }) // 用 read_image 看 PNG
// 情况 B:中文译文没有附图部分 → 把加注附图追加在译文后面,再接对照表
patent_figure_annotate({
inputPath: "D4中文译文.pdf", // 宿主:译文,一页不改
figuresFrom: "D4-WO2009011218A1.pdf", // 图纸来源
pages: [60, 61, 62], // **图纸来源文件**里的附图页码
annotations: [
{ page: 60, ref: "10", label: "密封圈", source: "translation" },
{ page: 61, ref: "HS", label: "热沉", source: "user" },
{ page: 62, ref: "4", undocumented: true },
],
})
// 省略 outputPath → 生成 D4中文译文附图标注版.pdf(宿主文件名 + 后缀,与宿主同目录)
// 输出 = D4中文译文.pdf 全文 + 加注后的第 60-62 页 + 对照表(全文最后)
patent_figure_verify({ inputPath: "D4中文译文.pdf", figuresFrom: "D4-WO2009011218A1.pdf",
outputPath: "D4中文译文附图标注版.pdf", pages: [60,61,62],
annotations: <上一步 annotated + undocumented 条目> })
// 情况 A:宿主自带【说明书附图】→ 不传 figuresFrom,就地替换
patent_figure_annotate({ inputPath: "CN118765432A.pdf", pages: [4,5,6], annotations: [ ... ] })
pages必须是【说明书附图】的完整页集合(漏掉尾部的附图页,那些页就不会加注)。中文公告文本每张附图页页眉都印有「说明书附图」,patent_figure_outline早期版本会把figureTo判得过早,现已按"重复页眉并入同一节"处理;仍请按页脚的「N/M 页」核对后再传pages。插件在"附图末页的下一页文字也很稀疏(且不含摘要)"时会给出提醒。若宿主自身也印有「说明书附图」章节而你又传了figuresFrom,插件会提醒附图可能重复。
扫描件(附图页没有文字层)时,先用光栅候选定位,再用 near 落笔:
patent_figure_inspect({ path: "扫描件.pdf", pages: [4,5], detectRasterNumerals: true })
// rasterNumerals 是启发式候选(无 ref),对照 PNG 确认哪个框是哪个标记
patent_figure_annotate({
inputPath: "扫描件.pdf",
pages: [4,5],
annotations: [
{ page: 4, ref: "10", label: "密封圈", near: { x: 0.681, y: 0.197 } },
{ page: 5, ref: "HS", label: "热沉", near: { x: 0.44, y: 0.36 } },
],
})
patent_figure_annotate 返回的 annotated 数组(含 box,若用了 near 也会原样回显)可以直接当作 patent_figure_verify 的 annotations 传入。
配置(cordis.patch.yml 的 config)
| 键 | 默认 | 说明 |
|---|---|---|
color |
#FF0000 |
标注颜色;规范固定为正红 |
fontPath |
'' |
内嵌中文字体路径(.ttf/.otf;.ttc 不受支持)。留空则宋体优先自动查找(华文宋体 STSONG.TTF),也可用环境变量 DSH_PATENT_FIGURE_FONT |
dpi |
200 |
墨迹采样与预览渲染分辨率 |
margin |
18 |
版心边距(pt),标注不得越界 |
fontSize |
0 |
0 = 自动取原标记字号 |
outputSuffix |
附图标注版 |
默认输出文件名后缀:默认名为「原文件名 + 后缀」原名附图标注版.pdf,与源文件同目录(D1-CN100416828C.pdf → D1-CN100416828C附图标注版.pdf)。文件名里已带该后缀时不重复追加 |
tableTitle |
附图标记-中文释义对照表 |
已锁定,只为兼容旧配置而保留;配置里的值一律忽略 |
enforceStyle |
true |
锁定颜色等样式,忽略单条注解里的 color |
输出命名不再使用
patentNumber:不传outputPath时一律按「原文件名 + 后缀」生成;patentNumber仍可传入,但只作标注信息保留。需要别的名字就直接传outputPath。
安装
plugin_manager({ action: "install_bundle", target: "<本目录的绝对路径>" })
手动安装等价于:
pnpm add <本目录的绝对路径> # 在 profile 目录执行
然后重启 Harness。
设计要点
- 矢量叠加,不是画在图上。 原图一个字节都不重绘:
pdf-lib整体复制页对象,标注是叠加的文字对象;因此线宽、线型、原有文字全部原样保留,且标注是矢量的,放大不糊。 - 文字层是定位依据。
pdfjs-dist提取每个文本项的 transform 与宽度得到 bbox。这里有个容易错的点:transform的a/d已经含了字号,再乘一次宽度会把框放大 12 倍——lib/pdf-util.js里只取它的方向并归一化。 - 中文必须内嵌子集,且整册统一宋体。
pdf-lib+@pdf-lib/fontkit对华文宋体STSONG.TTF做子集化(只嵌入实际用到的字形),一个 12 pt 的"壳体"只让文件增长约 1.8 KB,不依赖阅读器端字体;落笔前用hasGlyphForCodePoint逐字预检,缺字形不会静默画成方框。 peerDependencies是模块解析开关。 profile 装的是符号链接,插件真实路径在 profile 之外;Harness 只有在peerDependencies里看到@deepseek-ai/*名字时才会把裸导入拦截到安装目录。所以三个 Harness 包必须写进peerDependencies,而pdf-lib等运行时依赖写进dependencies(它们从插件自己的node_modules解析)。- 工具的输出也会被校验。 Harness 对
defineTool的入参与返回值都按声明的 schema 校验(additionalProperties: false),少声明一个字段工具就会在运行时报错。 - 遵守会话文件策略。 插件写 PDF/PNG,
fs服务做不到,所以直接用node:fs,但会读ctx.sandboxPolicy:read-only拒绝写出,workspace-write拒绝写到工作区之外。
已知边界
- 章节定位(
patent_figure_outline):以页眉的章节标题为主证据,并把同一节各页重复的页眉标题合并成一节(中文公告文本每张附图页都印「说明书附图」,早期实现会因此把附图范围截成 1 页);收尾依据是下一节标题,或页眉节内页码n/M 页的 M 变化(下一节标题没被识别出来时兜底)。页眉被拆成单字文本项(说/明/书/附/图)时会先按行合并再匹配,所以正文里的「附图说明」不会被误判;孤立一行的「附图」只有在旁边带刊物号或节内页码时才认。 - 纯扫描件(整份没有文字层)的像素判定:标题与页脚页码都读不到时,自动把每页按 72 DPI 渲染、做连通域统计,按「字形样组件数 + 大组件墨迹占比」把图纸页与正文页分开(实测 CN 公告:正文页 809–1192 个字形组件、大组件墨迹 0.8%–39%;图纸页 69–117 个、94%–95%,差 5 倍以上)。结果标
confidence: medium,evidence带上实测数字;紧邻区间的灰区页面单独警告;超过 250 页跳过。正文可读时不启用这一判定——插在正文里的插图同样"少量大轮廓",会被误判成图纸页。可用detectDrawings: false/drawingDpi控制。 - 扫描件/无文字层:文字层里没有标记,
patent_figure_inspect的numerals会是空的。改用detectRasterNumerals:true拿到候选框(或自己看图定坐标),再用near指认标记位置,即可让标注紧贴标记落笔;两者都给出后仍建议人工看一眼。 - 光栅候选是启发式的:不做 OCR、
ref留空,扫描件上必然有少量漏检(字形断裂/偏淡且贴引线时)与误检(图注、尺寸数字);页眉/页脚区(默认 y<4.5% 或 y>95.5%)与超大图形会被排除。 verify的遮蔽:正路径用 annotate 回显的box,逐像素比对是精确的;若调用方不给box,遮蔽靠"同文本 + 最近位置、一对一"配对(同页重复标签不会互相顶掉),但该配对隐含"标注追加在内容流末尾"这一前提。/Rotate非 0 的页:坐标按渲染方向换算,标注方向随页旋转,一般无需干预。.ttc字体不受支持:fontkit 不能直接嵌入 TrueType 集合,请改用同族.ttf。- 纯工程尺寸数字:会被当作"疑似标记"列出,是否加注由使用者判断;未登记的此类数字会出现在
verify的unannotatedNumerals提示里,不影响ok。 - 加密 PDF 会被尽量忽略加密读取,解析失败会明确报错。
- 光栅检测的性能:默认 200 DPI 单页约 50–70 ms;若把
dpi调到 600,detectRasterNumerals会明显变慢(仍可用)。
卸载
# npm 安装的(方式一):
pnpm remove dsh-patent-figure-annotation
# 本地链接安装的(方式三,开发用):
pnpm remove @local/dsh-patent-figure-annotation
再把包名从 package.json 的 dsh.profile.bundles 里删掉,重启 Harness。README.md 不属于运行时,删掉它不影响插件。