返回案例和资讯
技术分享2026/07/068 分钟阅读华胥星辰团队

支持一百多种文件格式,工程上意味着什么

"上传即问答"听起来是一句话,背后是双引擎解析、格式分流和大量脏活。这篇讲格式覆盖的真实成本,以及怎么在质量和成本之间做分层。

文档解析多模态Markdown工程实践
支持一百多种文件格式,工程上意味着什么

写在前面 "上传任意格式,直接开始问答"是很多 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、图片这三类占绝大多数。把这三类的解析质量做扎实,比支持一百种格式但每种都只能提取纯文本更有价值。

覆盖度是拿来做市场宣传的,解析质量才是决定用户留不留下来的东西。

想在你的业务里试试同样的做法?

告诉我们业务问题与数据现状,我们会给出方案建议与落地路径。