背景:RAG 管道的解析瓶颈被低估了两年
过去两年,业界对 RAG 的关注集中在分块策略、重排序、嵌入模型------但 2026 年越来越多的团队意识到:检索质量的上限,往往被更上游的「文档解析」卡死。一个被合并单元格抹平成乱码的表格,会污染下游所有 chunk;再聪明的 reranker 也救不回来。
更糟的是这件事没有银弹。.docx 走 mammoth,.xlsx 走 openpyxl,.pptx 走 python-pptx,2003 年的 .doc 和 .xls 要 shell 到 LibreOffice 转换......每个库有自己的依赖树、自己的输出风格、自己的失败模式。光是把它们按统一风格调一致,就是一个 plumbing 项目。
Firecrawl anydoc(github.com/firecrawl/anydoc,MIT,2026-08-03 开源,v0.1.9 2026-08-13)就是冲着这个痛点来的。Firecrawl 把网页抓取做到 LLM 友好 Markdown 的能力延伸到本地文档------开源两周内 GitHub 收获 17k+ Star,跻身 GitHub Trending 周榜。本文从架构、实战、基准解读、避坑清单四个角度做深度拆解。
一、事实表:anydoc 是什么
| 字段 | 值 |
|---|---|
| 仓库 | github.com/firecrawl/anydoc |
| 许可证 | MIT |
| 最新版本 | v0.1.9(2026-08-13) |
| 实现语言 | Rust(from-scratch,非套壳) |
| 产物 | 单一调用返回 GitHub-Flavored Markdown |
| 格式覆盖 | 14 种非 PDF + 文本型 PDF(PDF 旁路走 pdf-inspector) |
| 运行时 | Rust crate / Node.js / Python / WebAssembly / CLI |
| 依赖 | 无系统依赖、无 API Key、无 ML 模型、无 GPU |
| Agent Skill | npx skills add firecrawl/anydoc |
| 官方基准 | 中位 4.4ms / 100 份真实文档 / 14 种格式 / 厂商自测 |
支持的 14 种格式扩展名族:
- Word:
.doc.docx.docm - PowerPoint:
.ppt.pps.pot.pptx.pptm.ppsx.ppsm - Excel:
.xls.xlsx.xlsm.xlsb - OpenDocument:
.odt.ods.odp - 其他:
.rtf.epub.csv - PDF:经
Format::Pdf走 pdf-inspector 旁路
二、架构:每格式一个解析器,共享一个文档模型,只有一个 Markdown 序列化器
图1:anydoc 架构流水线------每种格式解析为同一套 Document 结构,再由唯一的 GFM 序列化器输出;PDF 不进文档模型,直接路由 pdf-inspector(概念示意,非运行截图)
整个流水线可以拆成四步加一个旁路:
- 内容级格式检测:不看扩展名,看内容签名------PDF header、RTF 开组、OLE 流名、ZIP mimetype。CSV 没有可靠签名,所以仍要靠扩展名或显式指定格式。
- 每格式独立解析器 :每个格式有自己的解析实现(例如
.xls*用calamine库),但解析结果都被归一化到同一套Document结构(blocks / inlines / tables / footnotes / assets)。 - 共享 Document 模型:这是 anydoc 整套设计的核心。一处修表格转义,14 种格式全部受益------README 原话「A table-escaping fix for docx is automatically a table-escaping fix for rtf, odt, and everything else」。
- 单一 GFM 序列化器:所有 Document 共用一段序列化代码,标题锚点、列表编号、脚注、链接行为在所有格式下都一致。
- PDF 旁路 :
Format::Pdf走pdf-inspector直接抽文本,不进文档模型,所以对 PDF 调to_document会报Unsupported。
这种「解析器多、模型一、序列化器一」的设计 vs. 业内常见的「每格式一套独立输出」是个根本差异------前者是工程化统一,后者是技术债。
三、实战一:CLI 三分钟上手
bash
# 安装即用:npx 首次运行会下载预编译二进制
npx @firecrawl/anydoc report.docx
# 把 Markdown 输出到文件
npx @firecrawl/anydoc slides.pptx -o slides.md
# 从 stdin 读
npx @firecrawl/anydoc - --format csv < data.csv
CLI 走的是 Node 包预编译二进制,对小脚本很方便;想固定版本就 npm install -g @firecrawl/anydoc。anydoc --help 列出全部选项。
四、实战二:Python / Node / Rust 三种 API 同形
Python(pip install firecrawl-anydoc):
python
import anydoc
文件路径
md = anydoc.to_markdown("contract.docx")
字节 + 自动检测
md = anydoc.to_markdown_bytes(data)
显式指定格式(CSV 必须,因为无内容签名)
md = anydoc.to_markdown_bytes(data, "csv")
拿到结构化文档(注意 PDF 不支持)
doc = anydoc.to_document(data)
格式检测三兄弟
fmt = anydoc.format_from_bytes(data)
fmt = anydoc.format_from_extension("XLSX")
fmt = anydoc.format_from_path("data/q3.xlsx")
Node(npm install @firecrawl/anydoc):
javascript
import { toMarkdown, toMarkdownBytes, toDocument, formatFromBytes } from "@firecrawl/anydoc";
const md = await toMarkdown("contract.docx");
const fromBytes = await toMarkdownBytes(bytes);
const fromCsv = await toMarkdownBytes(bytes, "csv");
const doc = await toDocument(bytes);
const fmt = formatFromBytes(bytes);
Rust(cargo add anydoc):
rust
let md = anydoc::to_markdown("contract.docx")?;
let md = anydoc::to_markdown_bytes(&bytes, None)?;
let md = anydoc::to_markdown_bytes(&bytes, anydoc::Format::Csv)?;
let doc = anydoc::to_document(&bytes, None)?;
let fmt = anydoc::Format::from_bytes(&bytes);
注意:调用前最好先 from_bytes 判一下,再走 to_markdown_bytes(bytes, format)------既给 CSV 这种无签名格式一个明确路径,也方便做日志与降级。
五、实战三:浏览器 WASM + Agent Skill
WebAssembly:
bash
npm install @firecrawl/anydoc-wasm
javascript
import init, { toMarkdownBytes, toDocument } from "@firecrawl/anydoc-wasm";
await init();
const md = toMarkdownBytes(bytes);
const doc = toDocument(bytes);
官方在线演示:anydoc by Firecrawl------拖入文件,本地转换,明确标注「文件永不离开你的机器」。WASM 镜像了 lib API(formatFromBytes / toMarkdownBytes / toDocument),构建命令是 wasm-pack build wasm --release --target web --scope firecrawl。
Agent Skill:
bash
npx skills add firecrawl/anydoc
anydoc 以 Agent Skill 形式发布,兼容 Claude Code、Codex、Cursor、OpenCode 等。安装后,agent 碰到 doc/xls/ppt/epub 等文件时,会自动调用 anydoc CLI 转 Markdown 再读入上下文------把「文档解析」从「上下文组装」阶段剥离出来,由专业库负责。
六、官方基准怎么读------诚实警示
图2:官方基准中位转换耗时(对数刻度)------anydoc 比次快工具快一个数量级,LibreOffice 慢到 1129.5ms(数据来源:Firecrawl 官方博客基准表,2026-08-06;概念示意图,非本文实测)
速度结论(来自 Firecrawl 官方博客 2026-08-06,100 份真实文档,14 种格式):
| 工具 | 格式覆盖 | 中位耗时 |
|---|---|---|
| anydoc | 14/14 | 4.4 ms |
| mammoth | 1/14 | 52.5 ms |
| pandoc | 5/14 | 102.1 ms |
| markitdown | 6/14 | 134.8 ms |
| docling | 4/14 | 513.6 ms |
| unstructured | 8/14 | 572.9 ms |
| libreoffice | 12/14 | 1129.5 ms |
质量结论(LLM 评审,Claude Sonnet 5,双盲打分,共 482 个判定):
图3:质量维度拆解------anydoc 五项(总分/完整性/结构/格式化/整洁度)全部领先,LibreOffice 覆盖广但整洁度仅 24 分(数据来源:Firecrawl 官方博客基准表;概念示意图,非本文实测)
| 工具 | 总分 | 完整性 | 结构 | 格式化 | 整洁度 |
|---|---|---|---|---|---|
| anydoc | 81 | 87 | 79 | 78 | 81 |
| mammoth | 70 | 84 | 71 | 75 | 51 |
| markitdown | 65 | 78 | 66 | 60 | 52 |
| unstructured | 63 | 76 | 59 | 51 | 63 |
| docling | 57 | 60 | 60 | 57 | 51 |
| pandoc | 56 | 74 | 57 | 56 | 38 |
| libreoffice | 40 | 59 | 42 | 40 | 24 |
三句诚实警示------这组数据很好看,但必须照原样看:
- 是厂商自测。基准是 Firecrawl 自己跑的,不是第三方。
- 是 LLM 评审。裁判是 Claude Sonnet 5,质量分本质是「AI 觉得 AI 输出好不好」。
- 语料不公开。README 原话「the corpus is ours」。也就是说「100 份真实文档」是 Firecrawl 选出来的,没法在自家语料上重现。
另外,总分是各自支持格式的平均分------mammoth 70 只覆盖 docx,anydoc 81 覆盖 14 种。跨工具横比应看「逐格式对比」:在那张表里,anydoc 在每个被评判的格式上都最高,doc 87/docm 84/docx 88/epub 77/odp 86/ods 82/odt 80/ppt 80/pptx 74/rtf 88/xls 80/xlsm 76/xlsx 72。
结论:速度优势是数量级的,可信;质量优势是清晰的、有方向的,但绝对分数请保守看待。建议在自己的真实语料上抽样复现。
七、限制清单与避坑
必读 README 后再集成,可少踩 80% 的坑:
-
扫描/纯图像 PDF →
Unsupported:anydoc 不做 OCR。混合 PDF(部分页扫描)需要走pdf-inspector标出的页面 + 外部 OCR 管线;托管 API 用户可走 Firecrawl/parse,它会拼 pdf-inspector 与 OCR。 -
加密文件 →
Encrypted错误。直接放弃,不要试图用空口令。 -
页眉、页脚、页码、日期/时间占位符默认排除 ;但演讲者备注(speaker notes)始终包含------这是 PPT/PDF 转 Markdown 时一个常被忽略的事实。
-
GFM 无非十进制列表语法 。
.docx里的罗马/字母编号会渲染成带字面标记的 bullet,例如- iv. 介绍、- a. 步骤一。 -
嵌入图像/对象 在 Markdown 里只渲染为 alt 文本;原字节保留在 Document 模型的
assets字段里,带媒体类型。需要图片请走to_document。 -
电子表格仍有未关闭的开放项 :
- R17b(数字格式渲染):单元格的自定义数字格式(如百分比、千分位)当前会丢失。
- R17c(超链接):电子表格中的超链接尚未完整提取。
引用自仓库 Phase 16/17 状态「S11 = R17b/c 仍开放」;R18 已延期。
-
基准中 anydoc 仅评判 94/100 份文档------剩下 6 份因格式边缘或工具问题未进入计分。读 100% 全胜时要扣一点。
-
to_document对 PDF 报 unsupported------它只走纯文本旁路。结构化 PDF 提取需要先转 PDF 文本/OCR。 -
错误变体 (仅在无法产出有意义的 Markdown 时返回):
Unsupported/Malformed/Encrypted/ResourceLimit/MissingPart/Io。Node 与 WASM 包用error.code字符串;Python 每一变体对应一个anydoc.ConvertError子类。 -
版本号当前不一致 。GitHub 显示
v0.1.9(2026-08-13),但中间穿插的0.3.0(2026-08-01)版本号更高。pip 装的是firecrawl-anydoc、npm 是@firecrawl/anydoc、crates.io 是anydoc,用pip show/npm view确认当前 release,不要想当然。
八、何时该选它,何时该留下旧栈
适合:
- 你的 RAG / Agent 摄取管道要吃 14 种文档格式,且希望「一处改风格、全部生效」。
- 浏览器侧转换(用户上传的合同/手册不出本机)。
- 给 agent 配
npx skills add firecrawl/anydoc减少上下文失真。 - 不想再为 mammoth + openpyxl + python-pptx + LibreOffice shell 维护拼装。
- 你的 RAG 已经能跑通,只想要更稳的解析层。
暂时别换:
- 主要场景是扫描/纯图像 PDF------anydoc 帮不了你,需要 OCR 方案。
- 强依赖电子表格的数字格式与超链接(财务模型/数据目录):等 R17b/c 关闭。
- 需要 PDF 的版面级结构(标题层级、阅读顺序、表格跨页)------目前 PDF 走 pdf-inspector 旁路,结构化能力有限。
- 已经有跑得很稳的 LibreOffice shell 方案且流量不大(1129ms 对 4.4ms 在 1 万份/月量级下成本差异并不显著)。
九、总结与延伸
anydoc 的核心赌注是:「RAG 时代,文档解析的瓶颈不在某一个格式,而在跨格式的输出不一致性。」用统一 Document 模型 + 单一 GFM 序列化器去解这个一致性,是工程化思维而不是单点优化。再叠加上 4.4ms 数量级的中位转换速度、五个运行时同形 API、Agent Skill 集成,它在 2026-08 这波文档解析趋势里占了相当扎眼的位置。
但要避免被漂亮数据带偏:基准是厂商自测、LLM 评审、语料未公开的;电子表格数字格式、超链接、PDF 结构化都还有未关闭的开放项。先在你的真实语料上抽 50--200 份做 A/B,再决定是否全量替换旧栈。
官方资源:
- 仓库与 README:https://github.com/firecrawl/anydoc
- 配套 PDF 引擎:https://github.com/firecrawl/pdf-inspector
- 官方发布博客:https://www.firecrawl.dev/blog/anydoc-and-pdf-inspector
- WASM 在线演示:anydoc by Firecrawl
- Agent Skill 注册:
npx skills add firecrawl/anydoc - 托管 API:Firecrawl
/parse与/scrape已自动使用 anydoc + pdf-inspector


