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
把几个主流工具放在一起比较:
|
|
|
|
|
|
|---|---|---|---|---|
| GitHub Stars |
|
|
|
|
| 中文支持 |
|
|
|
|
| 公式识别 |
|
|
|
|
| 表格处理 |
|
|
|
|
| 处理速度 |
|
|
|
|
| 硬件要求 |
|
|
|
|
| 开源协议 |
|
|
|
|
根据实测对比:
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. GitHub – microsoft/markitdown -
2. markitdown-skill | LobeHub -
3. MinerU vs Marker vs MarkItDown 实测对比
-
4. Openclaw 中文社区 -
5. Openclaw101
夜雨聆风