前言¶
DeepSeek Harness(DSH)在处理论文类文档时,往往需要从 PDF 中提取公式并还原成 LaTeX。论文 PDF 多使用子集化字体,字形名被改写为 g12、cid37 之类,且常无 /ToUnicode 映射,导致传统文本提取难以识别数学符号。dsh-pdf-formula 是一个纯主机端(Host-only)插件,通过读取 PDF 自带的文本层与字形轮廓,将公式还原为 LaTeX,同时提供页面文本与字体信息。
插件定位¶
- 包名:
dsh-pdf-formula - 插件名:
pdf-formula - 维护者:zhangzhichen18
- 分类:模型推理
- 版本:1.0.0
- 许可证:MIT
- 依赖:无(仅使用 Node 内置模块)
插件通过注入 tools 服务注册三个 Agent 工具,没有界面,不注入任何客户端代码。
三个工具¶
pdf_info¶
先体检,再决定怎么读。返回页数、每页尺寸(pt)、每页字体表(baseFont / subtype / embedded),以及某页是否看起来是扫描页(没有文本层、只有图像)。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path |
string | 是 | PDF 路径。绝对路径,或相对会话工作区(exec.agent.session.header.cwd) |
返回
{
"ok": true,
"file": "...",
"pageCount": 10,
"pages": [
{
"page": 1,
"width": 595.28,
"height": 841.89,
"rotation": 0,
"scanned": false,
"glyphCount": 1200,
"imageCount": 0,
"fonts": [...]
}
],
"scannedPages": [],
"note": null
}
pdf_extract_text¶
按页取文本,行内与行间的展示公式直接渲染成 LaTeX;每页同时给出纯文本与 markdown 两种形态。
参数
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
path |
string | — | 必填,同上 |
pages |
string | "all" |
页选择,如 "1-5,9";从 1 开始,闭区间 |
mode |
"text" | "markdown" |
"markdown" |
markdown 保留标题与公式块;text 为纯阅读顺序 |
formulas |
boolean | true |
是否把展示公式渲染为 LaTeX;设为 false 更快 |
返回
{
"ok": true,
"file": "...",
"mode": "markdown",
"formulas": true,
"pageCount": 10,
"pages": [
{
"page": 1,
"text": "线性回归模型:y = wx + b",
"markdown": "线性回归模型:$y = wx + b$",
"formulas": [
{
"index": 0,
"latex": "y = wx + b",
"confidence": 0.95,
"display": true,
"glyphCount": 5,
"uncertain": []
}
],
"glyphCount": 1200,
"uncertain": []
}
],
"note": null
}
pdf_extract_formulas¶
只抽公式:每条给出 LaTeX、页码、整体置信度,以及没能确定的低置信度符号。
参数
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
path |
string | — | 必填,同上 |
pages |
string | "all" |
页选择,如 "1-5,9",也可为 "all" |
minConfidence |
number | 0.5 |
低于该 0..1 置信度的公式被丢弃 |
includeUncertain |
boolean | true |
保留含未解析符号的公式,并把符号列出来 |
format |
"latex" | "json" |
"latex" |
latex 返回公式清单;json 附带完整结构化记录 |
返回
{
"ok": true,
"file": "...",
"format": "latex",
"minConfidence": 0.5,
"includeUncertain": true,
"pageCount": 10,
"formulaCount": 25,
"pages": [
{
"page": 1,
"formulas": [
{
"index": 0,
"latex": "E = mc^2",
"confidence": 0.98,
"display": true,
"glyphCount": 5,
"uncertain": []
},
{
"index": 1,
"latex": "∫_0^∞ f(x) dx",
"confidence": 0.85,
"display": true,
"glyphCount": 8,
"uncertain": [
{
"symbol": "∫",
"code": "U+222B",
"confidence": 0.82,
"source": "shape"
}
]
}
]
}
],
"note": "2 个低置信度符号"
}
识别原理¶
-
不走名字,走形状。 论文 PDF 多用子集化的 CFF/Type1 字体,字形名被改写为
g12、cid37之类,且常常没有/ToUnicode映射。引擎按证据强弱依次尝试:/ToUnicode→ simple font 的/Encoding /Differences→ 标准 14 字体的内置编码 → 把字形轮廓栅格化后与系统数学字体的模板做形状匹配。 -
还原二维结构。 只有字符还不够:分式、根号、上下标、大运算符、矩阵靠的是位置关系。引擎在设备空间里重新解释内容流(CTM/文本矩阵),拿到每个字形的精确包围盒,再找分数线、根号横杠等规则线,分组后组装成 LaTeX。
-
逐页输出。 三个工具入口都在
lib/extract.mjs,插件的index.js用动态import()调用它们,识别引擎即使暂时不可用也不会影响插件加载。
置信度说明¶
每个字符都带 confidence(0..1)与来源 source:
tounicode— 1.0,PDF 自带映射,最可靠differences— 0.97,字形名可解释standard-encoding— 0.9 / 0.85,标准 14 字体的内置编码shape— 形状匹配,由重叠度与「与第二名模板的差距」共同决定,上限 0.95
公式的 confidence 是其字符置信度的平均;低于 minConfidence(默认 0.5)的字符会进入 uncertain 列表,把「这里可能认错了」明确交给模型判断,而不是悄悄给一个看似正确的符号。note 字段会汇总整页的未确定符号数。
已知限制¶
- 扫描件不 OCR。 没有任何文本层(纯图片)的页面抽不出公式与文字;
pdf_info会把这类页面标记为scanned: true并列入scannedPages,此时请改用 OCR 工具,本插件不会去猜像素。 - 单符号可能被近形字误判。 形状匹配对「同一个字形的不同字符变体」做了族归一,但少数近形符号仍可能认错——实测本仓库样张里一个根号被认成了
∨。这类字符会带上偏低的confidence并出现在uncertain/uncertainSymbols里,请以它为准复核,不要默认每个符号都对。 - 公式的完整性是逐页渐进的。 分式、上下标、大运算符能正确组装;横跨多行的长公式偶尔会被拆成两段,或把紧跟其后的正文/图注并进来。遇到可疑结果建议同时用
pdf_extract_text(纯文本兜底)和pdf_extract_formulas对照。 - 生僻字体会退化为低置信度。 非嵌入字体、异常的 Type3 字体,或形状与常见数学字体差异较大的字面,匹配分数会下降,符号会以
uncertain报出,而不是被强行替换。 - 不做版面重建。 多栏排版按栏内阅读顺序输出,不还原图表位置;表格与图注里的零散符号不单独成条。
安装与启用¶
从 npm 安装(推荐)¶
dsh plugin --profile web add dsh-pdf-formula
也可以在 Harness 的「添加插件」对话框里填包名 dsh-pdf-formula,装完重启 Harness 生效。
从本地源码安装¶
这是一个 bundle:package.json 声明 dsh.bundle.patch,cordis.patch.yml 只做一条 insert:
- insert:
- id: pdf-formula
name: 'dsh-pdf-formula'
config: {}
在 Harness 里用 plugin_manager 的 install_bundle 指向本目录即可安装。安装后用 cordis_inspect_query 的 Tool.listTools 确认三个工具已注册,或查看 Config.listConfigs(name 填 dsh-pdf-formula)里的条目。
工具不出现时,先看宿主终端里的 pdf-formula: 警告。 曾经的失败原因不是 Config,而是 candidates() 里对 ctx.tool 的裸属性访问:Cordis 4 对未在 inject 中声明的服务做属性访问会直接抛错,而 apply() 的 try/catch 把它吞成了一条 ctx.logger.warn——插件于是显示为 ACTIVE,却一个工具都没注册。现在该服务改经 ctx.get('tool') 读取(未声明/不存在时返回 undefined,不抛错)。
排查同类问题时:宿主里用 --dump-config 只能证明这一行进了组合树,不能证明它注册成功;真正的证据是会话日志 request/header 里的工具表(宿主发给模型的目录),或设置 →「插件」→「插件列表」里每个条目的运行时状态(active / pending / failed)。
路径类参数必须让 exec 传进来。 宿主把每次调用的上下文作为 execute(args, exec) 的第二个实参传入:exec.agent.session.header.cwd 是会话工作区(相对路径的锚点),exec.signal 是取消信号。任何包装层只要把 execute 写成 (args) => …,就会把 exec 悄悄吃掉——本插件的 makeRun 曾正犯此错,于是相对路径永远退回 process.cwd()(= 启动 dsh web 的目录,通常不是工作区)。
改动 index.js 后必须重启 dsh web 进程。 本 profile 的 hmr 行 root: [],不监视插件模块,所以只刷新浏览器页面或重新开关 bundle 都不会换掉进程里已缓存的旧模块。
为什么没有可配置项: 本插件刻意不导出 Config。Cordis 通过 schemastery 解析插件的配置模式(Config.validate),导出一个普通 JSON Schema 对象会让激活直接失败。所有可调参数都是工具自己的实参并自带默认值,所以「零配置」既是设计也是避免该类激活故障的做法。
典型用法¶
在 Agent 会话中,可以直接调用三个工具:
- 先用
pdf_info检查文件是否包含文本层,确认哪些页是扫描页。 - 用
pdf_extract_text获取页面文本与 markdown,公式会自动渲染为 LaTeX。 - 用
pdf_extract_formulas抽取公式清单,过滤低置信度结果,复核uncertain中的符号。
适用场景¶
- 从 PDF 论文中提取数学公式并转换为 LaTeX
- 检查 PDF 文档的字体信息与页面结构
- 在 DSH Agent 中处理包含数学符号的技术文档
插件以当前 dsh 进程权限运行,安装前应检查源码与许可证。
总结¶
dsh-pdf-formula 通过形状匹配与二维结构还原,将 PDF 中的数学公式转换为 LaTeX,适用于需要从论文中提取公式并继续处理的 Agent 场景。插件不依赖外部引擎,通过三个工具提供体检、文本提取与公式抽取能力,并明确报告置信度与不确定符号,方便后续复核。
- 目录页:https://www.skillhub.cn/plugins/zhangzhichen18/dsh-pdf-formula
- GitHub:https://github.com/zhangzhichen18/dsh-pdf-formula