夜雨聆风学习资料网

ARTICLE · 1000746

知识库的召回质量,卡在文档解析这一步:我们把联犀的解析引擎开源了

知识库的召回质量,卡在文档解析这一步:我们把联犀的解析引擎开源了
⬆️关注 联犀,最及时最干货的ai+iot 分享

       联犀开源 · 知识库解析引擎     

       知识库的召回质量,卡在文档解析这一步     

       联犀知识库把文档解析引擎做成了纯 Go 开源库 docling:12 种格式进、4 路输出,图表数据逐格精确还原,OCR 收敛为一个大模型接口。本文从动机讲到架构、实测效果与联犀的完整用法。     

知识库同款引擎纯 Go 单二进制兼容 Docling 协议

做 AI 应用绕不开一件事:把文档变成大模型能吃的结构化数据。合同、标书、论文、报表、邮件……格式五花八门,而 LLM 只认 Markdown、JSON 和向量。这个"翻译层"看着不起眼,却直接决定了 RAG 的召回质量——解析时丢掉的表格和数字,检索和重排再怎么调都救不回来。

一、为什么联犀要自己写解析引擎

联犀是物联网 SaaS 平台,客户往知识库里灌的文档非常杂:设备说明书 PDF、验收文档 Word、汇报 PPT、点位表 Excel、告警通知邮件……最初我们调研了两条路,各有硬伤:

路线一,Python 模型管线(如 Docling):识别质量好,但每个部署环境都要拖一套 Python 服务加数 GB 布局/表格模型文件。联犀支持私有化交付,客户机房的环境里塞不下这些;批量导入十万份文档时,逐页过模型的排队时间也无法接受。

路线二,拼装开源库:PDF 一个库、Office 一个库、网页再一个库。输出格式五花八门,表格和图片的语义对不齐——同一个"表格",在 PDF 库里是坐标列表,在 Office 库里是 XML 结构,进了同一个知识库谁也对不上谁,维护成本失控。

于是我们给自己定了三条硬目标:纯 Go 单二进制,跟着联犀后端一起部署,不新增任何运行时依赖;输出统一为 Docling 官方协议,一套模型对接全部格式;解析不确定的内容交给大模型按页增强,但绝不编造结果。这三条催生了 docling。先看它吃什么、吐什么。

二、吃什么、吐什么:12 种输入,4 路输出

输入侧覆盖 12 种格式,一个入口按扩展名自动分发:

PDFWordPPTExcelCSV纯文本

▲ 蓝色:Office 与文档主战场——PDF 深度解析,Office 三件套含批注/修订/公式/图表

HTMLMarkdownAsciiDoc

▲ 绿色:网页与标记语言——标题平铺、富表格、行内格式与链接保留

EML 邮件图片 PNG/JPEG/BMP/WEBP

▲ 黄色:邮件与图片——RFC 头/multipart 择优/字符集解码;图片走 OCR 钩子

Docling JSON 回读

▲ 紫色:Docling 服务产出的 JSON 可直接回读,与 Python 生态互通

输出侧 4 路,全部由同一份结构化模型按需导出:

① Markdown — 文档就绪

标题层级、GFM 表格、代码块、公式 LaTeX、图表内嵌 SVG 预览,喂 LLM 或直接发布均可。

② HTML — 完整文档

与 Markdown 同构渲染,表格锚点、figure/caption 语义齐全,适合在线预览。

③ Docling JSON — 官方协议,无损

schema 1.10.0,与 Python Docling 互通可往返;页码、bbox、provenance 全保留。

④ content_list — RAG 检索列表

扁平化内容列表,带标题路径/页码/类型标签,知识库切片的直接输入。

知识库场景还内置三种分块器:层级分块(对齐官方 HierarchicalChunker,标题进上下文、列表组保持完整)、Hybrid 分块(token 感知切分+表头重复+同标题合并)和知识库分块(联犀在用:默认 900 字、表格每段 100 行并重复表头、过滤页眉页脚)。

格式覆盖只是入场券,解析效果才是核心——不看宣传看实测,下面全部用真实文档。

三、效果如何:真实文档,原文进什么出来

仓库的 examples 对照集为每种格式提供"样例源文件 ↔ 期望输出"的成对样本,以下全部展示真实世界文档的实际识别结果。

案例① Word · 微软官方测试文档(6 个原生图表)

真实 Office 生成的多系列柱状图/折线图文档(微软 Open XML SDK 官方测试资产,MIT 授权):

识别后的 Markdown(节选)——图表数据按系列精确还原为可检索表格,缺失单元格如实留空,并附 SVG 语义预览:

| 类别 | Series 1 | Series 2 | Series 3 | | --- | --- | --- | --- | | Category 1 | 4.3 | 2.4 | 2 | | Category 2 | 2.5 | 4.4 |  | | Category 3 | 3.5 | 1.8 | 3 | | Category 4 | 4.5 | 2.8 | 5 |

案例② PPT · 微软官方演示(3D 饼图)

识别后的 Markdown(节选)——3D 饼图的季度数据完整还原:

| 类别 | Sales | | --- | --- | | 1st Qtr | 8.2 | | 2nd Qtr | 3.2 | | 3rd Qtr | 1.4 | | 4th Qtr | 1.2 |

案例③ Excel · 微软官方工作簿(OLE 嵌入对象)

工作簿中的 OLE 嵌入对象按语义分类记录(目标路径、程序标识入 meta,载荷不执行)。

案例④ PDF · 真实学术论文(196 页论文 + 10 页双栏会议论文)

识别后的 Markdown(节选;两份论文 200+ 页纯 Go 解析约 30 秒):

## Evaluating the GO  ## Programming Language with  ## Design Patterns  by  ### Frank Schmager  A thesis submitted to the Victoria University of Wellington in partial fulfilment of the requirements for the degree of Master of Science in Computer Science.  ### Abstract  GO is a new object-oriented programming language developed at Google by Rob Pike, Ken Thompson, and others. ...

右侧的 10 页双栏会议论文展示双栏阅读顺序还原——左右栏内容不再交错串读。

案例⑤ TXT / CSV / EML · 真实文本类文档

《汤姆·索亚历险记》全书(380KB)、x86 指令集表(3700+ 行)、CPython 标准库的真实 MIME 退信邮件:

# Banned file: auto__mail.python.bat in mail from you  From: MAILER DAEMON <>  To: <webmaster@python.org>  Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)  BANNED FILENAME ALERT  Your message to: xxxxxxx@dot.ca.gov, ... was blocked by our Spam Firewall. The email you sent with the following subject has NOT BEEN DELIVERED:

邮件头、multipart 正文择优、收件人列表逐项还原;CSV 表与长文本按原样结构化。

案例⑥ 构造样例(rich-*)——复杂对象的确定性对照

对 SmartArt、OMML 公式、艺术字、组合图等复杂对象提供代码构造、可再生产的确定性对照:公式转 LaTeX({E}^{2}=mc)、SmartArt 流程转语义 SVG 且节点文字进入可检索 caption、组合图按系列类型分列渲染。

各格式真实样例总览(全部有授权来源,可放心复现):

格式
真实样本
来源
PDF
196 页硕士论文 + 双栏会议论文
维多利亚大学公开论文
Word
含 6 个原生图表的官方测试文档
微软 Open XML SDK(MIT)
PPT
含 3D 饼图的官方测试演示
微软 Open XML SDK(MIT)
Excel
含 OLE 嵌入对象的工作簿
微软 Open XML SDK(MIT)
EML
真实 MIME 多段退信邮件
CPython 标准库(PSF)
纯文本
《汤姆·索亚历险记》全书
公版书
CSV
x86 指令集表(3700+ 行)
golang.org/x/arch
HTML
Go net/http 包文档页
Go 官方文档快照

以上每个案例 clone 下来跑一条命令即可逐字复现。这些效果的背后,是一条刻意求简的架构。

四、底层架构创新:五个专用组件,收敛为一个模型接口

传统解析管线的复杂度来自"专用组件堆叠":文字识别配 tesseract、版面配布局模型(LayoutLMv3)、表格配 TableFormer、公式配公式模型、阅读顺序再配一个模型——五套依赖、五份部署,每个环节的质量各自为政,升级要逐个换。

docling 把解析任务切成两类,分别交给最合适的执行者:确定性结构交给规则引擎——字体/CMap 恢复、表格网格、双栏切分、公式转换、图表数据回填、阅读顺序,这些有明确规则可循,不需要模型,精确且快。

识别类任务统一收敛给一个多模态大模型接口——OCR 逐字识别、版面视觉、图片表格与公式理解,全部走 OCRHook/VisualHook 两个钩子。依赖从"OCR 引擎 + 4 个模型文件"变成"0 个内置模型 + 1 个可选模型接口":换更强的大模型,整条识别链路一起升级,架构反而更简单:

▲ 五个专用组件 → 一个通用大模型接口

路由不是拍脑袋:解析器对每一页计算质量信号——乱码率、表格候选、公式密度、栏位歧义,只有命中疑难信号的页(扫描件、图片表格、公式密集页)才真正调用模型:

doc, err := docling.ParsePDFWithOptions(data, docling.PDFOptions{     GarbageThreshold: 0.4,  // 乱码率超 40% 触发 OCR     OCRHook: myLLMOCR,       // 逐字识别(接任意大模型)     VisualHook: myVision,    // 带 bbox 的结构化视觉     MaxVisualPages: 20,      // 单文档页数预算 })

模型返回的结果要过强校验——标签、置信度、表格拓扑、单元格几何、防拒答防复读,无效自动重试一次;有效结果与规则文本按几何去重合并,失败则保留纯 Go 结果。模型增强永远不破坏既有输出。架构简单的第一个红利,就是速度。

五、快多少:34~153 倍

同一台机器、同一批真实 PDF 的实测(Python Docling CPU 管线,同进程预热后计时,对它更公平的口径):

▲ 论文场景提速 34 倍,书稿场景提速 153 倍

196 页论文约 30 秒完成解析入库——对联犀的批量导入场景,这意味着不需要为解析单独准备算力池。说了这么多能力与原理,最后回到它真正的生产环境:联犀知识库是怎么用它的。

六、联犀知识库的完整链路

文档从上传到被 AI 用上,一共六步,docling 站在第二步:

▲ 联犀知识库架构:docling 是第②层解析引擎,质量决定 ③⑤⑥ 的上限

① 上传归档:单文件或 ZIP 批量导入,原文、解析产物、内容列表三层落 OSS 私有桶,SHA256 哈希做增量——没变过的文档不重复解析,变了只重编增量部分。

② 双引擎解析:解析网关优先走 docling(纯 Go,12 种格式全量);对像素级版面要求高的场景可选挂 docling-serve Python 服务做副引擎,失败或超载自动降级,互为兜底。

③ 编译流水线:导入后的异步批处理——切片(知识库分块策略)、LLM 文档摘要、图片/表格/公式生成多模态描述、embedding 向量化入 pgvector、构建切片关系图(向量召回+LLM 判定关系类型)。

④ 存储:PostgreSQL + pgvector(每知识库一个向量索引)+ OSS(原文/产物/图片资产)+ Redis(编译分布式锁)。

⑤ 混合检索:向量召回 + 关键词召回 → RRF 融合 → Cross-Encoder 精排(ONNX),再沿切片关系图扩展上下文、保证文档多样性。

⑥ 消费:Agent 对话注入 RAG 上下文;或模型在推理中自主调用知识检索工具(ReAct);图片命中还能现场调视觉模型生成针对当前查询的描述。联犀侧对大模型钩子做了三层工程保护:结果强校验(防拒答/防复读/表格拓扑)、页数预算(单文档上限)、费用按租户归账。

七、和 Python 官方版的差距,如实说

不回避短板:扫描件 OCR 官方版开箱即用,docling 需配置钩子(配好后能力相当);像素级版面理解(复杂非矩形版面、极端旋转扫描)官方模型管线仍是上限;输入覆盖上音频 ASR、EPUB、XML 系列(XBRL/JATS/USPTO)还在路线图。所以联犀的答案是双引擎——默认纯 Go 跑量,高保真场景挂 Python 副引擎,互为兜底。README 里有完整的差距对照表,两者是互补,不是替代。

八、开源了,欢迎共建

这个引擎已经在联犀生产环境跑了多轮迭代,现在以 MIT 协议开源。如果你也在做知识库、RAG 或 Agent 的文档摄入,上手只要几行:

import docling "github.com/unitedrhino/docling"  // 一行完成"解析 → Markdown" md, err := docling.ParseByExtToMarkdown("报告.pdf", data)  // 或拿到结构化模型再消费 doc, _ := docling.ParseByExt("报告.docx", data) items := docling.ToContentList(doc, docling.SourceGolight) // 检索列表 chunks := docling.HierarchicalChunks(doc)                  // RAG 分块

仓库自带真实文档对照集:微软官方测试文档、196 页论文、双栏会议论文、《汤姆·索亚历险记》全书、x86 指令集表、真实退信邮件——每格式一组"原文 ↔ 识别结果"成对样本,clone 下来跑一条命令即可逐字复现全部效果。

GitHub:github.com/unitedrhino/docling

你的知识库正在被哪种文档卡住——扫描件、表格还是公式?留言告诉我们,这决定下一个版本优先补什么。


⬆️关注 联犀,最及时最干货的ai+iot 分享

相关学习资料