乐于分享
好东西不私藏

MarkItDown + OpenClaw 实测: 文档转markdown工具选型与RAG流水线搭建

MarkItDown + OpenClaw 实测: 文档转markdown工具选型与RAG流水线搭建

你有没有遇到过这种情况:手头一堆 PDF、Word、PPT,想喂给 AI 处理,结果格式全乱、表格跑偏、图片丢失?

这大概是 2024-2025 年搞 RAG 和知识库的程序员最头疼的问题之一。

最近微软开源了一个叫 MarkItDown 的工具,配合 OpenClaw,可以完成文档到 Markdown 的转换。今天不只聊工具,还从理论层面讲讲这套方案的适用场景。


先说结论:谁适合用这套组合

这套方案适用于以下场景:做 RAG 或知识库,需要把各种格式的文档转成 Markdown 喂给大模型。经常处理 PDF、Word、PPT,但不想折腾复杂的 OCR 流程。想把 OpenClaw 打造成更强大的本地 AI 助手,能处理各种文档。

如果需要处理大量扫描件、中文古籍这种复杂文档,MinerU 可能更合适——这个后面会详细对比。


一、为什么文档解析在 RAG 架构里这么重要

在说工具之前,先聊聊理论。很多人跑过 LangChain 教程,觉得 RAG 就是”embedding + vector search”两步走。但真正做过生产级知识库的人都知道,真正的瓶颈往往在文档解析这一环。

1.1 RAG 的标准流程

一个完整的 RAG 系统通常包含这几个环节:文档摄入(Ingestion)→ 解析(Parsing)→ 分块(Chunking)→ 向量化(Embedding)→ 存储(Storage)→ 检索(Retrieval)→ 生成(Generation)。

文档解析看起来只是个”前置工作”,但它对最终效果的影响可能是决定性的。

举个具体例子:假设你有一份包含财务报表的 PDF,里面有合并单元格的表格。如果解析时表格结构丢失,embedding 之后的 chunks 就会把原本相邻的数据拆散,检索时根本捞不到完整的信息。再比如学术论文里的 LaTeX 公式,如果转成纯文本的乱码,大模型读不懂,RAG 就白做了。

所以常说:Garbage in, garbage out。文档解析质量直接决定了知识库的上限。

1.2 常见的文档解析方案

目前业界主流的文档解析方案大概分几类:

第一类是基于规则的解析器,比如 Pandoc。这类工具用固定的规则处理特定格式,优点是速度快、依赖少,缺点是对复杂布局和混合内容支持差。

第二类是基于 OCR + 布局分析的解析器,比如 MinerU 和 Marker。这类工具会先做布局检测(文字、表格、图片、公式),再针对性地提取内容,精度更高但资源消耗也更大。

第三类是端到端的深度学习模型,比如 Docling。这类工具用统一的模型处理各种格式,对复杂文档的鲁棒性更好,但需要 GPU 支持。

MarkItDown 属于哪一类?严格来说它是个”大一统”的封装层,底层调了不同的解析器来处理不同格式:PDF 用 pdfminer/pypdf,Word 用 python-docx,图片用 PaddleOCR。它的定位是”通用格式转换”,而不是”PDF 专用解析器”。

1.3 选择文档解析工具的核心考量

选工具之前,先问自己几个问题:

第一,内容类型是什么?是纯文本为主,还是包含大量表格、公式、图片?不同工具的强项不一样。

第二,语言是什么?英文文档和中文文档的解析难度差异很大,中文还需要考虑字符编码和排版方向。

第三,性能要求是什么?实时处理还是批量处理?有没有 GPU 资源?

第四,输出格式是什么?纯 Markdown 够用,还是要保留原始的样式信息(用于后续渲染)?

想清楚这几个问题,再往下看具体的工具对比。


二、MarkItDown 是什么

MarkItDown 是微软 AutoGen 团队开源的一个 Python 工具,核心功能是把各种文件格式转换成 Markdown。

GitHub 上现在已经超过 108K Stars。

支持的文件格式包括:办公文档方面支持 PDF、Word (.docx)、PowerPoint (.pptx)、Excel (.xlsx/.xls);网页文本方面支持 HTML、纯文本、CSV、JSON、XML;多媒体方面支持图片(带 OCR 和 EXIF 元数据)、音频(语音转录)、YouTube 视频字幕;其他还支持 ZIP 压缩包、EPUB 电子书、Outlook 邮件 (.msg)。

安装命令:

pip install 'markitdown[all]'

基本用法:

# 转换单个文件markitdown document.pdf > output.md# 或者指定输出路径markitdown document.pdf -o output.md# Python API 调用from markitdown import MarkItDownmd = MarkItDown()result = md.convert("document.pdf")print(result.text_content)


三、MarkItDown + OpenClaw:怎么配合使用

安装 MarkItDown skill 的方法:

# 首先确保安装了 markitdown CLIpip install 'markitdown[all]'# 然后在 OpenClaw 里安装 skillopenclaw skills install markitdown

安装完成后,可以在 OpenClaw 里直接说:”帮我把这个 PDF 转成 Markdown””把这个 Word 文档转成文本””把这段音频转成文字”。OpenClaw 会自动调用 MarkItDown 来处理。

批量转换示例:

# 使用 skill 自带的批量脚本python ~/.openclaw/skills/markitdown/scripts/batch_convert.py docs/*.pdf -o markdown/ -v# 或者用 shell 循环for file in docs/*.pdf; do  markitdown "$file" -o "${file%.pdf}.md"done

四、理论 + 实操:搭建一个完整的文档处理流水线

下面演示怎么把 MarkItDown 集成到一个完整的 RAG 流水线上。

4.1 整体架构设计

一个典型的文档处理流水线包含:文档输入 → 格式检测 → MarkItDown 转换 → 内容清洗 → 分块处理 → 向量化 → 存入向量数据库。

# 完整的文档处理流水线示例from markitdown import MarkItDownfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain_community.embeddings import OllamaEmbeddingsfrom langchain_community.vectorstores import Chromaimport osclass DocumentPipeline:    def __init__(self, chunk_size=1000, chunk_overlap=200):        self.md = MarkItDown()        self.splitter = RecursiveCharacterTextSplitter(            chunk_size=chunk_size,            chunk_overlap=chunk_overlap,            separators=["\n\n", "\n", "。", " ", ""]        )    def process_file(self, file_path: str) -> list:        """处理单个文件,返回 chunks"""        # Step 1: MarkItDown 转换        result = self.md.convert(file_path)        raw_text = result.text_content        # Step 2: 内容清洗        cleaned_text = self._clean_text(raw_text)        # Step 3: 分块        chunks = self.splitter.split_text(cleaned_text)        # Step 4: 添加元数据        documents = []        for i, chunk in enumerate(chunks):            documents.append({                "page_content": chunk,                "metadata": {                    "source": os.path.basename(file_path),                    "chunk_id": i                }            })        return documents    def _clean_text(self, text: str) -> str:        """简单的文本清洗"""        # 移除多余的空白字符        text = '\n'.join(line.strip() for line in text.split('\n'))        # 移除连续的空行        import re        text = re.sub(r'\n{3,}', '\n\n', text)        return text    def build_vectorstore(self, file_paths: list, persist_dir: str):        """构建向量数据库"""        all_docs = []        for path in file_paths:            all_docs.extend(self.process_file(path))        embeddings = OllamaEmbeddings(model="nomic-embed-text")        vectordb = Chroma.from_documents(            documents=all_docs,            embedding=embeddings,            persist_directory=persist_dir        )        vectordb.persist()        return vectordb

4.2 分块策略的理论依据

分块策略的选择要考虑几个因素:第一个是语义完整性,一段代码块不要从中间切断,一个段落不要拆成两半。第二个是信息密度,如果一块内容大部分是无意义的装饰性文字,实际有用的信息密度就很低。第三个是检索粒度,太大的 chunk 容易引入噪声,太小的 chunk 缺少上下文。

常见的分块策略有按固定字符数分块(简单但粗暴)、按段落/句子分块(保留语义但大小不均)、按语义分块(用模型判断但计算成本高)。

对于中文文档,经验值是 chunk_size 设置在 800-1200 字符之间,overlap 设置在 100-200 字符,能取得不错的平衡。

4.3 特殊内容的处理技巧

表格处理:MarkItDown 输出的表格是 Markdown 格式,可以保留原始结构。但对于复杂的合并单元格,建议提前转成 CSV 格式再处理。

# 表格特殊处理示例def process_table_heavy_doc(file_path: str) -> str:    md = MarkItDown()    result = md.convert(file_path)    # 提取 Markdown 中的表格    import re    tables = re.findall(r'\|.+\|\n\|[-:| ]+\|\n(?:\|.+\|\n)*', result.text_content)    # 对表格内容做额外处理(比如转成 JSON)    table_data = []    for table in tables:        rows = table.strip().split('\n')        headers = [c.strip() for c in rows[0].split('|')[1:-1]]        for row in rows[2:]:            values = [c.strip() for c in row.split('|')[1:-1]]            if len(values) == len(headers):                table_data.append(dict(zip(headers, values)))    return table_data

图片处理:MarkItDown 会把图片提取到临时目录,Markdown 里用相对路径引用。如果要做多模态 RAG,可以在这里接入图像描述模型。

代码块处理:对于包含代码的文档(技术文档、API 文档等),可以用更细粒度的分块策略,比如按代码块单独提取。


五、横向对比:MarkItDown vs MinerU vs Marker

把几个主流工具放在一起比较:

维度
MarkItDown
MinerU
Marker
Docling
GitHub Stars
108K
59K
15K
14K
中文支持
⭐⭐⭐⭐
⭐⭐⭐⭐⭐
⭐⭐⭐⭐
⭐⭐⭐⭐
公式识别
⭐⭐⭐
⭐⭐⭐⭐⭐
⭐⭐⭐⭐
⭐⭐⭐⭐
表格处理
⭐⭐⭐
⭐⭐⭐⭐⭐
⭐⭐⭐⭐
⭐⭐⭐⭐
处理速度
⭐⭐⭐⭐⭐
⭐⭐⭐
⭐⭐⭐⭐⭐
⭐⭐⭐⭐⭐
硬件要求
CPU 即可
建议 GPU
中等配置
CPU 即可
开源协议
MIT
AGPL
GPL
GPL

根据实测对比:

MinerU 适合处理中文技术文档、学术论文,尤其是包含大量数学公式和复杂表格的场景。它在布局检测和表格解析方面是目前最强的,但需要 GPU 支持。

Marker 适合需要快速批量处理、对图片质量要求高的场景。它速度快、资源占用低,但对复杂表格支持一般。

MarkItDown 的优势是格式覆盖最广(支持音频、YouTube 视频转录),MIT 协议对商业使用限制较少。但它的强项不是 PDF 解析,而是 Office 文档和多媒体处理。

Docling 是 IBM 开源的项目,轻量级、资源占用低,适合纯 CPU 环境下的 RAG 预处理。


六、实际效果测试

拿一个包含文字、表格、图片的 Word 文档测试 MarkItDown 的效果:

文字部分:识别准确,格式基本保留。

表格部分:简单表格能转成 Markdown 格式,复杂合并单元格会降级为文本。

图片部分:能提取图片并生成 Markdown 引用,但图片质量一般。

跟 MinerU 对比,MarkItDown 在 Office 文档处理上表现相近,但 PDF 解析能力较弱。微软对 MarkItDown 的定位是 Office 文档处理的补充工具,不是 PDF 专用解析器。


七、企业级部署方案

生产环境部署有两种方案:

Docker 容器化

# 构建镜像docker build -t markitdown:latest .# 运行docker run --rm -i markitdown:latest < input.pdf > output.md# 配置资源限制docker run --rm -i --memory=2g --cpus=1 markitdown:latest < large.pdf > output.md

HTTP 服务部署(基于 MCP 协议)

# 基础启动python -m markitdown_mcp --http# 自定义端口python -m markitdown_mcp --http --host 0.0.0.0 --port 8080

通过 HTTP 请求调用文档转换功能,方便集成到现有系统。


总 结

MarkItDown + OpenClaw 这套组合的特点:

格式覆盖广,支持 PDF、Word、PPT、Excel、图片、音频、YouTube 视频等多种格式,安装后开箱即用。

MIT 协议对商业使用限制较少。

OpenClaw skill 把文档处理变成了对话式操作,降低了使用门槛。

不足之处:PDF 解析不是它的强项,复杂表格和公式的处理效果不如 MinerU。如果核心场景是处理中文 PDF 文档,建议直接用 MinerU。

工具选型需要根据实际需求决定,没有通用最优解。


参考资料

  1. 1. GitHub – microsoft/markitdown
  2. 2. markitdown-skill | LobeHub
  3. 3. MinerU vs Marker vs MarkItDown 实测对比
  1. 4. Openclaw 中文社区
  2. 5. Openclaw101