写在前面 "上传任意格式,直接开始问答"是很多 AI 知识产品的宣传语。这篇文章讲的是这句话背后的工程量,以及我们怎么把它做得成本可控。
一、格式覆盖不是"支持"或"不支持"
外界看到的是一个格式列表。实际情况是每种格式都有解析质量的层次:
| 层次 | 含义 |
|---|---|
| 能提取纯文本 | 最低要求,丢失所有结构 |
| 保留结构 | 标题层级、段落、列表关系完整 |
| 保留表格 | 行列关系可还原 |
| 保留公式与图表 | 公式可转为可编辑格式,图片可定位 |
| 保留版面位置 | 知道每个元素在页面上的坐标 |
同样是"支持 PDF",做到第一层和做到第五层,工程量差好几个量级。
而下游任务对层次的要求不同:纯问答对第二层就够;表格数据分析需要第三层;版式保留翻译必须要第五层。
所以格式支持不是一个开关,是一张任务与质量层次的对应表。
一个典型的用户场景
用户上传了一份学术论文 PDF,期望的体验是:
- 能问答 → 需要层次二
- 表格数据能被准确引用 → 需要层次三
- 公式能被正确识别 → 需要层次四
如果系统声称"支持 PDF"但只做到层次一,用户问"表 3 的数据是多少"就答不出来——不是模型的问题,是解析层根本没把表格提取出来。
二、双引擎分流
我们的做法是按需求分两条路:
轻量引擎——处理结构相对规整的格式(Word、Excel、PPT、EPUB、网页、邮件等),统一转成 Markdown。速度快、资源占用小,同步返回。这条路覆盖了大部分日常文档。
重型引擎——处理扫描件、复杂排版 PDF、含公式和复杂表格的文档。用深度学习模型做版面分析和结构化提取,质量高但慢、且需要模型权重。走异步队列。
分流规则不复杂:能用轻量引擎解析好的就用轻量的,解析结果质量不达标或者格式本身就属于难处理类别的,才走重型引擎。
为什么不全用重型引擎? 因为九成以上的文档用不着,全走重型意味着九倍的成本和延迟,换来的质量提升接近于零。
引擎选型的决策树
文件上传
├─ 是不是扫描件?(无文字层)
│ └─ 是 → 重型引擎(需要 OCR)
├─ 有没有复杂表格/公式?
│ └─ 有 → 重型引擎
├─ 是不是多栏排版?
│ └─ 是 → 重型引擎
└─ 其他 → 轻量引擎这个决策树的关键在于:判断工作在解析之前做,而不是解析完了再判断质量。 通过文件元数据(是否有文字层、页面布局复杂度)做预判,避免"先解析一遍发现不够好,再走重型引擎解析一遍"的重复工作。
三、统一到 Markdown 这个中间格式
不管来源是什么格式,我们都先转成 Markdown,后面所有环节都只面对 Markdown。
这个决定的好处:
- 下游只需要写一套逻辑。 切片、摘要、图谱抽取都只处理 Markdown,不用为每种格式写分支。
- 人可读。 排查问题时能直接看到解析结果对不对,这一点在调试期极其有用。
- 结构信息得以保留。 标题层级、列表、表格、代码块在 Markdown 里都有对应表达。
代价是有损失——精确的字体、颜色、页面坐标在 Markdown 里表达不出来。所以版式保留翻译那条链路不走 Markdown,它需要直接在原始版面上操作。中间格式解决大部分问题,但不是所有问题。
Markdown 表达的边界
Markdown 能做好的:
- 标题层级、段落、有序/无序列表、代码块、引用块
- 行内格式(加粗、斜体、链接)
- 简单的表格
Markdown 做不了的:
- 合并单元格的表格
- 页面坐标和分页信息
- 字体、字号、颜色、行高
- 图片在文本中的精确对齐位置
知道这个边界很重要:当需求是"把 PDF 转成可以问答的文本"时,Markdown 完全够用。当需求是"翻译后排版跟原来一模一样"时,Markdown 不够,需要直接操作页面对象。
四、脏活清单
真正吃时间的是这些没法讲得很漂亮的事:
- 编码检测。 中文文本文件的编码问题至今仍然存在。UTF-8、GBK、GB2312、Big5——自动检测说出来很简单,但识别准确率做不到 100%,错一次就是满屏乱码。
- 加密和损坏文件。 需要优雅地失败并告诉用户原因,而不是抛一个栈。用户看到一个栈 trace 只会觉得"这产品有问题"。
- 超大文件。 需要限制、分片或拒绝,不能让一个文件拖垮整个队列。我们设了 200MB 的单文件上限和 50MB 的文本提取上限。
- 同一格式的方言。 不同工具生成的 PDF 差异巨大,扫描件、纯文本 PDF、混合型各有各的坑。Acrobat 和 wkhtmltopdf 生成的 PDF 内部结构完全不同。
- 表格跨页。 一张表被分页切开,还原时需要判断这是同一张表的延续。判断的依据是表头是否重复、列数是否一致。
- 多栏排版。 学术论文的双栏排版,按坐标顺序读出来是错乱的,需要先做栏位识别。识别的依据是页面中间的纵向空白带。
这些问题没有一个可以靠"换个更好的模型"解决,只能一个一个处理。格式覆盖度是靠时间和真实样本堆出来的,没有捷径。
五、失败要给用户看得懂的反馈
解析失败是常态,不是异常。我们的处理原则:
- 明确告诉用户失败原因,而不是"处理失败请重试"。文件加密、格式损坏、超出大小限制,是三种完全不同的处理方式——加密的让用户输密码,损坏的建议换文件,超大的建议压缩。
- 部分成功也要能用。 一份一百页的 PDF 里有两页解析失败,不应该让整份文件不可用。我们标记失败的页码,其余内容正常进入问答。
- 保留原文件。 用户随时可以下载原始文件,这是最基本的信任。
六、给同类产品的一条建议
如果你在做类似的产品,我们的经验是:不要一开始就追求格式覆盖数量。
先把用户真正高频上传的那几种格式做到高质量——通常是 PDF、Word、图片这三类占绝大多数。把这三类的解析质量做扎实,比支持一百种格式但每种都只能提取纯文本更有价值。
覆盖度是拿来做市场宣传的,解析质量才是决定用户留不留下来的东西。
想在你的业务里试试同样的做法?
告诉我们业务问题与数据现状,我们会给出方案建议与落地路径。
需要帮助?
联系我们的团队,获取贴合你业务场景的方案建议。