dsh-pdf-formula:PDF 公式识别插件

前言

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 个低置信度符号"
}

识别原理

  1. 不走名字,走形状。 论文 PDF 多用子集化的 CFF/Type1 字体,字形名被改写为 g12、cid37 之类,且常常没有 /ToUnicode 映射。引擎按证据强弱依次尝试:/ToUnicode → simple font 的 /Encoding /Differences → 标准 14 字体的内置编码 → 把字形轮廓栅格化后与系统数学字体的模板做形状匹配。

  2. 还原二维结构。 只有字符还不够:分式、根号、上下标、大运算符、矩阵靠的是位置关系。引擎在设备空间里重新解释内容流(CTM/文本矩阵),拿到每个字形的精确包围盒,再找分数线、根号横杠等规则线,分组后组装成 LaTeX。

  3. 逐页输出。 三个工具入口都在 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 会话中,可以直接调用三个工具:

  1. 先用 pdf_info 检查文件是否包含文本层,确认哪些页是扫描页。
  2. 用 pdf_extract_text 获取页面文本与 markdown,公式会自动渲染为 LaTeX。
  3. 用 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
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜