【4核8内存搞定】Marker 将 PDF 转换为 Markdown 文档
📁 项目背景与需求
在使用 Dify 做 PDF 文档解析时,发现其在处理部分扫描版 PDF(图像形式)时无法正确识别文字。
尝试使用市面上的 PDF 转 Markdown 工具(如 Textin),发现免费额度(如 100 页)之后都需要付费。
因此,我希望寻找一个免费、可本地部署、支持 OCR 的工具。
目标是将 PDF 文档高质量地转换为 Markdown (.md
) 文件格式。项目需求包括:
- 保留 PDF 原有结构和内容
- 支持 OCR 识别(图像转文字)
- 在可能的情况下使用 LLM 增强转换质量
为满足以上需求,选择了 GitHub 上的开源项目 marker。
并成功在我的腾讯云主机(4 核 CPU、8GB 内存、无 GPU)上运行并转化大体积 PDF 文件为 Markdown 格式,且效果良好。
🛠️ Marker 项目简介
Marker 是一个基于多模型推理、OCR、LLM 增强的 PDF 转换工具。它的主要特点包括:
- ✏️ 将 PDF 转换为结构化 Markdown 文件
- 📝 支持图像类 PDF 的 OCR(光学字符识别)
- ✨ 支持使用大型语言模型(LLM)来优化段落分块、标题判断、排版
- 🌐 支持多语言:英文、中文(简繁)、法语等
- 🔍 支持表格识别、数学公式识别
实现结果展示
一份147页的pdf文件,本地总耗时2h,期间使用Gemini 的gemini-2.0-flash模型 15次,可以到下面的转换效果还是挺好的。
被转化的pdf文件展示
转化后效果展示
PDF 转换为 Markdown:命令执行和日志解析
📋 命令执行说明
执行命令:
systemd-run --scope -p MemoryMax=6.5G -p MemoryHigh=6G marker_single 19.pdf --output_dir ./output --use_llm --force_ocr --languages "zh" --page_range "1-10"
命令解析:
参数 | 解释 |
---|---|
systemd-run --scope | 在 systemd 环境中运行命令,确保子进程在内存和资源管理方面得到限制。 |
-p MemoryMax=6.5G | 设置最大内存为 6.5GB,防止进程占用过多内存导致系统 kill 掉。 |
-p MemoryHigh=6G | 设置内存高水位线为 6GB,当内存使用接近这个值时会触发内存回收。 |
marker_single 19.pdf | 执行 Marker 工具,处理 19.pdf 文件并转换成 Markdown 格式。 |
--output_dir ./output | 输出目录,用于保存 .md 文件和媒体资源 |
--use_llm | 启用 LLM(大语言模型)增强功能,以优化结果和结构化输出。 |
--force_ocr | 强制 OCR 识别,即使文本已识别,仍进行 OCR 处理,适用于扫描版 PDF。 |
--languages "zh" | 设置语言为中文,进行中文文本识别。 |
--page_range "1-10" | 仅处理 PDF 文件的第 1 到第 10 页。 |
📰 日志逐行解析
1. 运行标识:
Running as unit: run-reab57e6c4f214bed978c5c63a78fff91.scope; invocation ID: 6747a63b84f841c49fe352a3d5ab47c4
- 这行表示当前进程是通过
systemd-run
以独立作用域(scope
)执行的。scope
会限制进程的资源使用,确保不会影响其他进程。
2. 加载模型:
Loaded layout model s3://layout/2025_02_18 on device cpu with dtype torch.float32
Loaded texify model s3://texify/2025_02_18 on device cpu with dtype torch.float32
Loaded recognition model s3://text_recognition/2025_02_18 on device cpu with dtype torch.float32
Loaded table recognition model s3://table_recognition/2025_02_18 on device cpu with dtype torch.float32
Loaded detection model s3://text_detection/2025_02_28 on device cpu with dtype torch.float32
Loaded detection model s3://inline_math_detection/2025_02/24 on device cpu with dtype torch.float32
- 这些日志表示加载了不同的 AI 模型,它们用于处理文档的不同部分:
layout model
:用于文档的布局识别。texify model
:用于数学公式的识别。recognition model
:用于普通文本的识别。table recognition model
:用于表格结构的识别。text detection
和inline math detection
:分别用于文本和行内数学公式的检测。
- 这些模型都在 CPU 上运行,使用的数据类型为
torch.float32
。
3. 处理阶段:
布局识别:
Recognizing layout: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:26<00:00, 13.37s/it]
- 这表示布局模型在 2 页 PDF 文件上完成了布局识别,耗时 26 秒,成功解析了 2 页内容。
LLM 布局重标定:
LLM layout relabelling: 1it [00:04, 4.60s/it]
- LLM 重标定阶段使用了大语言模型对文档布局进行增强优化。每个任务耗时 4.6 秒。
OCR 错误检测:
Running OCR Error Detection: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:00<00:00, 21.49it/s]
- 这表示 OCR 错误检测已顺利完成,检测到 3 个 OCR 错误,并在短时间内完成。
检测 Bounding Boxes(文本区域):
Detecting bboxes: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:39<00:00, 13.14s/it]
- 这表示文本区域(Bounding Boxes)检测完成,共检测到 3 个文本区域,耗时 39 秒。
二次检测 Bounding Boxes:
Detecting bboxes: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:36<00:00, 12.09s/it]
- 再次进行文本区域检测,经过 36 秒,成功识别。
识别文本:
Recognizing Text: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 8/8 [08:21<00:00, 62.66s/it]
- 文本识别是最耗时的阶段,共识别了 8 个区域,耗时 8 分 21 秒。该阶段是 PDF 转 Markdown 的核心步骤。
LLM 后处理:
LLM processors running: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:05<00:00, 1.04s/it]
- LLM 后处理阶段对 5 个文本块进行了处理,耗时约 1 秒。
4. 输出结果:
Saved markdown to ./output/19
Total time: 616.6786270141602
- 经过处理,转换结果已保存到
./output/19
文件中。 - 总处理时间为 616.68 秒,约 10 分钟。
📌 总结与解析
- 内存管理:通过
systemd-run
和内存限制(MemoryMax
和MemoryHigh
),确保在内存高负荷情况下仍然能顺利完成任务,避免被系统 kill 掉。 - 模型加载与识别:Marker 自动加载不同的 AI 模型来识别文档的布局、文本、表格、数学公式等内容。每个模型在 CPU 上运行,确保转换质量。
- LLM 增强:LLM 处理通过大语言模型优化文档内容,改善 OCR 输出,提升 Markdown 格式的结构化效果。
- 性能与优化:文本识别阶段耗时最长,尤其是多页文件时,LLM 后处理阶段迅速提高文档质量。
🧵 系统环境说明
硬件环境:
- CPU:4 核
- 内存:8 GB
- 无 GPU
操作系统:基于 Linux 的 OpenCloudOS 9.2
📚 安装步骤
1. 安装 Python 和 pip
sudo yum install -y gcc make wget git
sudo yum install -y python3.11 python3.11-devel
sudo alternatives --install /usr/bin/python python /usr/bin/python3.11 1
curl -sS https://bootstrap.pypa.io/get-pip.py | python
2. 安装 torch(CPU 版本)
参考官网:https://pytorch.org/get-started/locally/
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
验证是否为 CPU:
import torch
print(torch.__version__)
print(torch.cuda.is_available()) # 应返回 False
3. 安装 Tesseract 和 Leptonica(OCR 支持)
安装依赖项:
sudo yum install -y git libtool clang gcc-c++ zlib zlib-devel libjpeg libjpeg-devel libwebp libwebp-devel libtiff libtiff-devel libpng libpng-devel
安装 Leptonica:
cd /usr/local/src
sudo git clone https://github.com/DanBloomberg/leptonica.git
cd leptonica
sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install
安装 Tesseract:
cd /usr/local/src
sudo git clone https://github.com/tesseract-ocr/tesseract.git
cd tesseract
sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install
sudo ldconfig
4. 安装 OCR 语言包(中文、英文)
sudo mkdir -p /usr/local/share/tessdata
wget https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddata -P /usr/local/share/tessdata/
wget https://github.com/tesseract-ocr/tessdata/raw/main/chi_sim.traineddata -P /usr/local/share/tessdata/
wget https://github.com/tesseract-ocr/tessdata/raw/main/chi_tra.traineddata -P /usr/local/share/tessdata/
export TESSDATA_PREFIX=/usr/local/share
验证语言包安装:
tesseract --list-langs
# 应显示 eng chi_sim chi_tra
添加环境变量
编辑永久添加环境变量
vim ~/.bash_profile
添加下面的变量
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
export LIBLEPT_HEADERSDIR=/usr/local/include/leptonica
export TESSDATA_PREFIX=/usr/local/share/
💾 增加 SWAP 和调整 swappiness(大 PDF 推荐配置)
情况说明:
处理超过 700 页的大 PDF 文件时,可能消耗超过 7GB 内存,建议配置:
- 创建 20GB swap 文件
- 设置
swappiness=95
创建并启用 20GB swap:
sudo fallocate -l 20G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
验证:
swapon -s
free -h
设置永久挂载:
echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab
设置 swappiness:
sudo sysctl vm.swappiness=95
echo "vm.swappiness = 95" | sudo tee -a /etc/sysctl.conf
4. 下载并安装 Marker
git clone https://github.com/VikParuchuri/marker.git
cd marker
📦5. 安装 marker 命令行工具
在使用 marker_single
命令之前,必须先通过 pip 安装 marker-pdf
工具包。建议安装完整依赖版本,以便支持 OCR、LLM 等所有功能:
pip install marker-pdf
pip install marker-pdf[full]
如遇到权限问题可加 --user
,或使用虚拟环境安装。
5. 配置 OCR 语言包(中文、英文)
从官方下载语言包:https://github.com/tesseract-ocr/tessdata
放置在 /usr/share/tessdata/
下(视系统而定):
sudo cp chi_sim.traineddata /usr/share/tessdata/
sudo cp chi_tra.traineddata /usr/share/tessdata/
sudo cp eng.traineddata /usr/share/tessdata/
⚙️ 使用 systemd-run 限制内存(防止被 kill)
systemd-run --scope -p MemoryMax=7G -p MemoryHigh=6G marker_single 04.pdf --output_dir ./output --use_llm --force_ocr --languages "zh" --llm_service=marker.services.openai.OpenAIService --openai_api_key=sk-xxx --openai_model=gemini-2.0-flash --openai_base_url=https://openai.newbotai.cn/v1
参数说明:
--scope
:让 systemd 以临时作用域运行MemoryMax
:内存硬限制,超过即 killMemoryHigh
:触发回收阈值
📂 支持的 LLM 模型服务
服务 | 参数 | 是否需代理 |
---|---|---|
Gemini(默认) | --gemini_api_key | 否 |
Gemini via OpenAI 兼容代理 | --llm_service=OpenAIService + --openai_api_key + --openai_model=gemini-2.0-flash + --openai_base_url=https://xxx | 是 ✅ |
OpenAI (gpt-4, gpt-4o) | --openai_api_key , --openai_model | 否 |
Claude | --claude_api_key , --claude_model_name | 是 |
Ollama(本地模型) | --ollama_base_url , --ollama_model | 是 |
Vertex AI | --vertex_project_id | 是 |
📦 示例命令
🧾 参数详解
基本 PDF 转换命令
marker_single test.pdf --output_dir ./output --force_ocr --languages "eng,zh"
参数 | 含义 |
---|---|
test.pdf | 要转换的 PDF 文件路径 |
--output_dir | 输出目录,用于保存 .md 文件和媒体资源 |
--force_ocr | 强制对所有页面进行 OCR(适用于扫描版 PDF) |
--languages | OCR 语言设置,支持多语言,用逗号分隔(如英文 + 简体中文) |
使用 LLM 增强(通过 OpenAI 兼容代理使用 Gemini 模型)
marker_single test.pdf --output_dir ./output --use_llm --force_ocr --languages "zh" --llm_service=marker.services.openai.OpenAIService --openai_api_key=sk-xxx --openai_model=gemini-2.0-flash --openai_base_url=https://openai.newbotai.cn/v1
参数 | 含义 |
---|---|
--use_llm | 启用 LLM 模型辅助格式化、标题、段落结构判断 |
--llm_service | 使用的服务类(此处模拟 Gemini,指定 OpenAI 兼容接口) |
--openai_api_key | LLM 的 API key(用于认证) |
--openai_model | 指定使用的模型名(如 gemini-2.0-flash ) |
--openai_base_url | 使用的代理 OpenAI 接口地址,便于绕过地区限制 |
✅ 提示:如直接使用官方 Gemini 服务,只需配置变量参数,不必配置 OpenAI 兼容参数。
可以直接访问Gemini 服务
在~/.bash_profile 文件中添加API-key
export GOOGLE_API_KEY=sk-
marker_single test.pdf --output_dir ./output --use_llm --force_ocr --languages "eng,chi_sim"
参数 | 含义 |
---|---|
test.pdf | 要转换的 PDF 文件路径 |
--output_dir | 输出目录,用于保存 .md 文件和媒体资源 |
--use_llm | 启用 LLM 模型辅助格式化、标题、段落结构判断 |
--force_ocr | 强制对所有页面进行 OCR(适用于扫描版 PDF) |
--languages | OCR 语言设置,支持多语言,用逗号分隔(如英文 + 简体中文) |
📁 最终输出结果
转换完成后将在指定目录生成:
index.md
:主 Markdown 内容/media
:提取的图像资源- 完整保留标题、段落、图表、数学公式结构
📌 常见问题与建议
- 内存不足被 kill:请使用 swap + systemd-run 控制
- Gemini API 报错 User Location Not Supported:说明你需要使用代理或切换为 OpenAI 类接口调用
- 某些模型响应格式不是 JSON,出现解析错误:说明模型输出格式不兼容,请自行包装或使用支持 JSON 返回的模型
如需进一步使用 Grok 模型、自定义服务类或部署 Web 前端,请参考 marker/services
下的源代码以及 marker_server.py
、marker_app.py
入口。