
当你把扫描书转成 EPUB,最让人出戏的错误之一,是正文里的脚注标记点开后找不到说明,或跳到了另一条注释。字都识别出来了,读者却没法顺着作者的论述读下去。我开发 PDF Craft,是想让扫描书不仅能重新排版、检索和摘录,也能保住正文与注释之间的关系。
旧书、学术资料和个人藏书经常有大量脚注。读者希望在手机上读到能调字号、可搜索的版本,遇到标记时也能找到对应的解释。本文讲的是我们怎样从“让模型检查每一页”,走到“先筛出可疑页再修复”。如果你只想检查自己的转换结果,可以直接看扫描 PDF 转 EPUB 的流程和公式、脚注检查清单。
识出文字后,还要找对脚注
文字识别(OCR)能告诉程序页面上有哪些字,却未必知道它们在书里扮演什么角色。页底的小字可能是脚注,也可能是排到页底的正文;正文右上角的圈号可能是引用标记,也可能是普通序号。一条注释甚至可能被拆成两块,跨到下一页。
只要有一处关系判断错了,输出就会出现古怪的阅读体验:标记点下去没有脚注,两条脚注粘成一条,页码混进句子,或者上一页的末句接到了下一页的栏头。脚注一直是 PDF Craft 中最难处理的老问题之一。
一年前:让 LLM 读过每一页
最初的办法很直接:既然传统程序难以理解语义,就把整页交给大语言模型。它能看出页底的小字是在解释正文,也能理解星号、圈号、罗马数字或汉字序号可能是引用标记。判断跨页句子时,它还可以参照上下文。
单页效果令人期待,整本书的成本却很快显现。几百页意味着几百次模型调用;每一页都要等待,失败后还要重试。跨页判断需要附带相邻内容,输入随之变长。更重要的是,绝大多数页面原本没有问题。为了修复少数页面,却让昂贵而缓慢的模型重新阅读整本书,用户也很难判断处理是否卡在了某一页。
回到传统算法,先把主流程做成闭环
后来的版本逐渐移除了逐页 LLM,改由 OCR 和确定性规则完成主体工作:区分正文与脚注,合并自然段,拆出一条条注释,再把正文标记与注释配对。这条流程速度快、结果稳定,也能重复运行。
对大多数页面,它已经足够好。但书籍排版变化太多:脚注可能在页底或栏间,标记可能是数字或星号,页码、栏头和装饰字符也会混入识别结果。有些异常终究需要理解一句话的意思。完全依赖传统算法,会留下少数难题;让 LLM 接管整本书,又太慢、太贵。
转折:先找出可疑页面
问题不在于 LLM 不够强,而在于分工。已有算法能处理整本书,真正缺少的是一个快速的质检环节:翻过每一页,只挑出值得怀疑的页面,再交给 LLM 精修。
我把 JEV 放在这个位置。你可以把它理解成一个逐页的质检员:它只回答这一页的分析结果能否原样通过,并给出用于筛选的概率。它不重写文字,也不负责修脚注;通过概率高的页面继续走原流程,可疑页面才交给后面的模型修复。
审查单位是整页,而不是现有的每条注释。如果算法彻底漏掉一条注释,逐条审查便没有对象可查;页面级判断仍有机会发现引用缺失、归属错误、跨页异常或页码混入正文。我宁愿多抓几页,也不愿漏掉真正出错的一页:误报增加一次模型检查,漏报则可能让错误进入最终 EPUB。这个取舍仍需要更多样本校准。
flowchart TB
accTitle: 从整页审查到有约束的修复
accDescr: OCR 与传统算法先处理页面;JEV 判断是否原样通过。可疑页交给 LLM 修复,再由程序检查。通过后进入章节组装,不通过则重试。
A[OCR 与传统算法] --> B{JEV:页面可信?}
B -- 是 --> F[章节组装与输出]
B -- 否 --> C[LLM 只修复当前页]
C --> D{程序完整性检查}
D -- 通过 --> F
D -- 重试 --> C
可疑页面交给 LLM,但修改范围有边界
LLM 会看到连续三页的文字结构:上一页、当前页和下一页;它只能修改中间这一页。相邻页面提供上下文,帮助判断句子是否跨页延续。模型不接收页面图片,因为 OCR 已经保留了文字、位置和布局信息;此处要做的是语义校正,而不是再做一次 OCR。
模型也不能自由改写原文或改变页面结构。它可以重新标注正文、脚注和页码,修正段落连接,重新配对正文标记与注释。提交后,程序检查脚注索引是否有序、引用与注释是否对应、跨页连接的两端是否一致,以及标记位置能否在指定文本中被无歧义地找到。如果结果不合格,程序把具体错误交还给模型,请它重新提交完整结果。约束不能为了减少重试而放松。
一份 26 页样本给我的提醒
在一次包含大量脚注的 26 页测试 PDF 上,JEV 挑出 6 页交给 LLM。这 6 页的首次提交都通过了完整性检查;原本正确的 22 组正文引用与脚注关系也全部保留。
真正改动的是几处朴素却影响阅读的问题:印刷页码被 OCR 当成正文;一处页码错误地成为前后段落的“桥”;还有一段引导读者阅读下文的话,被传统算法与后面的缩进引文合并。LLM 根据语义和缩进信息把它们重新断开。
这只是一次样本观察,不能据此推断所有书籍的准确率或成本。它让我看到的是:修复系统不必为了证明自己做了事而大改页面。保留已经正确的关系,只改有明确证据的问题,更符合阅读者的利益。
让昂贵的判断只出现在必要的地方
传统算法完成大多数确定性工作;JEV 快速筛选可疑页面;LLM 处理少数需要语义理解的难题;程序约束守住输出的完整性。修复后的页面回到同一条流水线,后续章节组装、Markdown 和 EPUB 渲染无需为它开辟另一套流程。
这套方案还要在更多语言、排版风格和厚书上检验,尤其要观察 JEV 的漏报率并校准进入 LLM 的阈值。至少方向已经清楚:不必让 LLM 从第一页读到最后一页,只为了寻找藏在书页角落里的几处错误。
如果你正在处理自己的扫描书籍,可以从 PDF Craft 转换页面挑一份含脚注的短样本开始,逐项核对正文标记、注释内容和跨页段落,再决定是否处理整本书。

