给大模型准备语料最麻烦的一环,是把散落在各种格式里的文档统一成模型能稳定读取的Markdown。Word、PPT、Excel、PDF各有各的内部结构,传统做法是LibreOffice转一遍、再拿Pandoc修一遍,输出风格还不统一。
Firecrawl在2026年8月开源的anydoc,就是冲着这个问题来的:纯Rust实现,覆盖14种办公文档格式,统一输出GitHub-Flavored Markdown,中位转换时间4.4毫秒。它同时也是Firecrawl Parse托管API的底层引擎。
为什么是anydoc
anydoc的核心架构选择很关键:不管什么格式进来,都先解析到同一个共享文档模型,再通过单一Markdown序列化器输出。这意味着给docx修好的表格转义,rtf、odt会自动跟着生效;标题锚点、合并单元格、脚注、列表编号在所有格式下行为一致。
与之相对的是市面上的其他方案:
-
LibreOffice:需要启动庞大的办公套件,单文档中位耗时1129.5毫秒
-
Pandoc:只覆盖5/14种格式,中位耗时102.1毫秒
-
markitdown:6/14种格式,134.8毫秒
-
docling:4/14种格式,513.6毫秒
-
mammoth:只支持docx一种,52.5毫秒
anydoc官方在100份真实文档上做的盲评基准(由Claude Sonnet 5对照LibreOffice渲染图打分,0-100分)结果是这样:
|
工具 |
格式覆盖 |
中位耗时 |
综合得分 |
|---|---|---|---|
|
anydoc |
14/14 |
4.4 ms |
81 |
|
libreoffice |
12/14 |
1129.5 ms |
39 |
|
unstructured |
8/14 |
572.9 ms |
62 |
|
markitdown |
6/14 |
134.8 ms |
64 |
|
pandoc |
5/14 |
102.1 ms |
56 |
|
docling |
4/14 |
513.6 ms |
57 |
|
mammoth |
1/14 |
52.5 ms |
69 |
anydoc是唯一覆盖全部14种格式的工具,在每一个有对比的格式上都拿了最高分,速度比第二名的Pandoc快了一个数量级。
💡 基准语料是Firecrawl自有的,不在仓库里。第三方博主拿自己的206份真实文档复测,194份成功转换,csv/xlsx轻松跑进5毫秒以内,复杂pptx/pdf大约在22毫秒左右——依然远快于传统方案。
支持格式
anydoc处理的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(仅文本型)
格式识别是从文件字节本身读的——PDF头、RTF开组、OLE流名、ZIP包的mimetype,所以扩展名改错了也能正确转换。CSV没有签名,需要显式指定格式或从扩展名推断。
30秒上手
最快的试用方式是不安装、直接用npx:
# 转换并输出到终端
npx @firecrawl/anydoc report.docx
# 输出到文件
npx @firecrawl/anydoc slides.pptx -o slides.md
# 从stdin读取(CSV需指定格式)
npx @firecrawl/anydoc - --format csv < data.csv
首次运行会自动下载对应平台的预编译二进制。要常驻使用就全局安装:
npm install -g @firecrawl/anydoc
各语言集成
anydoc提供Rust、Node.js、Python、WebAssembly四种绑定,API形态在各语言间保持一致。
Node.js
import { toMarkdown, toMarkdownBytes } from '@firecrawl/anydoc';
const markdown = await toMarkdown('report.docx');
const fromBytes = await toMarkdownBytes(bytes);
const fromCsv = await toMarkdownBytes(bytes, 'csv');
Python
import anydoc
markdown = anydoc.to_markdown("report.docx")
markdown = anydoc.to_markdown_bytes(data)
markdown = anydoc.to_markdown_bytes(data, "csv")
document = anydoc.to_document(data)
Rust
let markdown = anydoc::to_markdown("report.docx")?;
let markdown = anydoc::to_markdown_bytes(&bytes, None)?;
let markdown = anydoc::to_markdown_bytes(&bytes, anydoc::Format::Csv)?;
浏览器(WebAssembly)
import init, { toMarkdownBytes } from '@firecrawl/anydoc-wasm';
await init();
const markdown = toMarkdownBytes(bytes);
浏览器端转换完全在本地进行,文件不会上传,官方Demo页就是这么跑的。
给AI Agent用
anydoc内置了Agent Skill,一行命令让Claude Code、Codex、Cursor、OpenCode等兼容Agent原生具备读文档能力:
npx skills add firecrawl/anydoc
装完之后,Agent遇到任意格式的文档都会自动调用anydoc CLI转换,你只需要说"帮我分析这份报告"就行。
生产环境要注意的点
扫描件PDF不在anydoc的处理范围内。文本型PDF通过内置的pdf-inspector在本地转换;扫描件或纯图片PDF会返回Unsupported错误,需要走Firecrawl Parse托管的OCR能力。
错误处理建议区分类型:
try:
return anydoc.to_markdown(path)
except (anydoc.EncryptedError, anydoc.UnsupportedError) as e:
# 加密或不支持,记录并跳过
return None
except anydoc.ConvertError as e:
# 其他转换错误
raise
批量处理时把加密、不支持、损坏的文件单独记录,继续处理其余文件即可。
适用场景
anydoc最适合这三类需求:
-
LLM数据准备/RAG管道——把混合格式的文档批量转成统一Markdown喂给模型
-
Agent文档读取——作为Skill嵌入AI编程助手,让Agent原生支持多格式文档
-
本地批量转换——纯Rust、无ML模型、无外部服务依赖,断网也能跑
如果你不想自己运维,Firecrawl的/parse和/scrape端点已经默认在背后调用anydoc(非PDF文档走anydoc,PDF走pdf-inspector),托管版额外提供扫描件OCR。