ARTICLE · 1066110
如果你在做 RAG,这个 PDF 解析库可以看看
最近在做 RAG,发现 PDF 这一关其实比想象中麻烦很多。
产品手册、论文、研究报告这些资料想放进知识库,第一步肯定是把内容解析出来。以前很容易把这件事理解成“PDF 转文字”,但真正碰到资料以后会发现,PDF 里面可能是原生文字,也可能是图片,可能整页都是扫描件,更常见的是一页里面文字、产品图、截图、表格全部混在一起。
最近看到 Firecrawl 开源的 pdf-inspector,感觉它比较适合放在 RAG 最前面的文档解析这一层。核心是 Rust 写的,Node.js、Python 和浏览器都可以接,主要负责判断 PDF 的内容情况、提取原生文字、整理页面结构,再输出 Markdown。
像 Word、WPS、网页直接导出来的 PDF,里面通常本身就存着文字。比如页面上写着“电池容量 5000mAh”,PDF 内部真的存在这些字符,同时还保存了字体、位置这些信息。这种内容直接解析就行,完全没必要把页面先转成图片,再拿 OCR 重新识别一遍。
这也是我觉得 pdf-inspector 比较有意思的地方。它可以直接利用 PDF 已经存在的信息,把文字拿出来,再根据文字的位置去整理阅读顺序。像双栏论文、标题、段落、表格这些内容,最终可以尽量整理成更适合后续处理的 Markdown。
但 PDF 里面有图片,并不意味着这整页就变成了扫描件。
比如一页产品说明书,上面是产品介绍文字,下面放了一张产品照片。这一页其实同时存在两种内容。正文还是原生文字,可以正常解析,下面那张图依然只是图片,两者并不冲突。
如果图片只是产品照片,对知识库没什么实际信息,可能正文提取出来就够了。如果图片里面还有参数、流程图、软件截图,那就要看这些信息要不要进入 RAG。截图里的文字可以考虑 OCR,流程图、结构图这种内容如果真的需要理解,就已经不只是 OCR 了,可能还需要视觉模型。
所以这里其实是三件不同的事情。
PDF 原生文字可以直接解析。
图片本身可以从页面结构里识别出来,但“知道这里有一张图片”和“理解图片里面表达了什么”不是一回事。
扫描版 PDF 则是另外一种情况。纸质资料扫描成 PDF 以后,人眼看起来满页都是文字,但对解析器来说,整页可能只是一张大图片,里面根本没有可以直接读取的字符,这时才需要 OCR。
实际文档往往还会更混合一点。
比如一份 100 页的产品手册,前 70 页都是正常导出的文字,中间夹着几页产品图片,最后 20 页又是扫描进去的合同附件。甚至某一页本身就是左边原生文字,右边一张扫描图片。
这种情况下,最不划算的做法就是把 100 页全部转成图片,然后统一做 OCR。
能直接读出来的文字就直接读,需要 OCR 的页面或者区域再单独处理,图片里如果真的有知识库需要的信息,再决定要不要继续做图片理解。
这时候 pdf-inspector 的 pagesNeedingOcr 就比较有用了。它可以把原生解析结果和还需要进一步处理的页面区分开,而不是把所有东西混在一起。
Node.js 里面看它的结果也比较直接。
npm install @firecrawl/pdf-inspector
然后随便拿一份 PDF 跑一下。
import { readFile } from'node:fs/promises'
import { processPdfAsync } from'@firecrawl/pdf-inspector'
const pdf = await readFile('./manual.pdf')
const result = await processPdfAsync(pdf)
console.log(result.pdfType)
console.log(result.pagesNeedingOcr)
console.log(result.markdown)
我比较关心的其实就是这三个东西。
pdfType 可以先看这份 PDF 整体是什么情况,pagesNeedingOcr 告诉后面的流程哪些页面还不能只靠原生解析解决,markdown 则是已经能够正常提取出来的正文和结构。
放到 RAG 里面,这样分开以后整个链路就很清楚了。
PDF 进来以后,先尽量读取里面已经存在的原生文字。一页同时有文字和图片,文字照常解析,图片按实际价值决定要不要继续处理。碰到整页扫描件或者文字无法可靠提取的页面,再进入 OCR。最后把真正需要的内容整理好,再继续做切片、Embedding 和检索。
成本上的区别也在这里。
原生 PDF 解析主要就是本地 CPU、内存这些计算资源,不需要为了每一页去调用 OCR 或视觉模型。OCR 如果自己部署,需要额外的图片渲染和模型推理;如果调用第三方服务,还会多出按页或者按调用量计算的费用。图片如果还要交给视觉模型理解,成本又会继续往上加。
所以假设 100 页里面只有 10 页真正需要 OCR,就没必要为了这 10 页,把另外 90 页也重新识别一次。
对我来说,pdf-inspector 最有价值的地方并不是“它能把 PDF 转成 Markdown”这么简单,而是它让 PDF 进入 RAG 之前多了一层判断。
文字能直接拿就直接拿,图片单独看,扫描内容再做 OCR。一页里面几种内容都有,也不用强行选择一种处理方式,而是分别处理。
这比一上来就把所有 PDF 全部转图片、全部 OCR,要合理得多。