将PDF知识图谱化:graphrag+Doc2X+DeepSeek
微软最近推出的GraphRAG确实让人眼前一亮——官方声称它能从文档中提取出有意义的结构化数据。但有个小遗憾:默认情况下,它只认txt或csv格式。这意味着,那些堆积如山的PDF文档,如果不做处理就无法直接使用。这次,我用了外部库pdfdeal,先把PDF转换成带格式的txt,再结合性价比更高的DeepSeek来构建整个流程。下文会一步步拆解整个过程。
安装与配置:先搭好环境
为了避免不必要的麻烦,建议在虚拟环境中操作。以下是几种常见方式:
- :Conda的轻量版,当然直接上Anaconda也行。
miniconda3
- :用Rust编写的包安装器,速度飞快。
uv
- 或者用我自己写的一个脚本uvv,能配合uv和conda实现多版本Python的虚拟环境管理。
环境激活后,直接安装依赖:
# conda方案
conda create -n rag python=3.12
conda activate rag
pip install --upgrade pdfdeal graphrag
# uv方案
uv venv
source .venv/bin/activate # Linux
source .venv/Scripts/activate # Windows
uv pip install --upgrade graphrag pdfdeal
# uvv方案
uvv create -n rag -p 3.12
uvv activate rag
uvv install graphrag pdfdeal
完成后,找个顺手的文件夹,准备开始干正事。
Step1:把PDF“翻译”成txt
微软的GraphRAG只吃txt或csv,所以第一步就是转换。常见的选项按效果从低到高排列:
- 直接提取纯文本部分保存(效果最次,不推荐)
- 提取纯文本+图片OCR(
pdfdeal干的就是这件事,但遇到表格和公式会抓瞎) - 新型的OCR工具,能识别公式和格式:闭源的有Mathpix、Doc2X、Simpletex;开源的则有Nougat、Marker等。
这里选择了效果最好的Doc2X,而且它每天免费500页,相当于在做慈善。要使用它,需要先获取个人API密钥:进入网站后,点击个人信息,复制身份令牌作为API key。
接下来新建两个文件夹,一个放原始PDF,一个放转换后的txt:
mkdir ./pdf
mkdir -p ./ragtest/input
把PDF文件丢进./pdf。我选了两篇:GraphRAG论文本身,外加一篇我觉得挺重要的参考文献。
使用pdfdeal的CLI工具doc2x进行批量处理,记得加上--graphrag标识,开启对GraphRAG的特殊适配:
doc2x -k "Your Key Here" -o ./ragtest/input -p --graphrag ./pdf

等待处理完成,所有PDF就变成了带格式(Markdown语法)的txt文档:

Step2:用DeepSeek构建知识图谱
首先生成GraphRAG的配置文件:
python -m graphrag.index --init --root ./ragtest
如果只打算用默认的OpenAI LLM和嵌入模型,只需要在
.env里填上Key就行。但提前剧透:GraphRAG的token消耗非常恐怖,建议别用默认的GPT-4来构建。
找到settings.yaml,这是我们需要修改的核心配置文件。
第一部分是LLM设置。DeepSeek并不直接支持输出JSON,需要把model_supports_json设为false:
llm:
api_key: Your DeepSeek Key
type: openai_chat
model: deepseek-chat
model_supports_json: false
max_tokens: 4000
api_base: https://api.deepseek.com/v1
第二部分是嵌入模型设置。这里直接用了OpenAI的text-embedding-3-small。注意,由于LLM部分修改了api_base,嵌入部分的api_base也要相应调整。也可以换成其他兼容OpenAI格式的嵌入模型,比如智谱的:
embeddings:
async_mode: threaded
llm:
api_key: ${GRAPHRAG_API_KEY}
type: openai_embedding
model: text-embedding-3-small
api_base: https://api.openai.com/v1
一切就绪后,运行命令开始构建——这个过程相当漫长(两篇不算长的PDF花了十几分钟)。去喝杯茶吧:
python -m graphrag.index --root ./ragtest

构建完成后,就可以向GraphRAG提问了。它支持两种模式:global和local。
python -m graphrag.query
--root ./ragtest
--method global
# 或者换成:--method local
"你的问题"
总结:效率与成本的权衡
先说说效果。GraphRAG确实有效,尤其适合处理关联性强的问题,配合Doc2X能很好地提取文档内容。但问题在于:
它是个token杀手,无论是构建阶段还是回答阶段。
统计一下这两篇PDF:如果直接作为上下文输入,加起来总共52525 token。但构建阶段消耗了多少呢?
2024-07-14, deepseek-chat, graphrag, 1334747输入token, 344702输出token
没错,133万输入token,34万输出token。好在用的是DeepSeek,总共只花了$0.28(约2元软妹币)。但如果换成OpenAI的模型,即使是最便宜的GPT-4o,也要$11.85(约86元)才能完成构建。
哪怕只是回答一个简单问题,也会消耗85293输入token和1848输出token。还好有DeepSeek这个性能足够又极其便宜的异类撑着。

同时,由于token消耗惊人,实际输出速度也非常慢。因此,现阶段很难把GraphRAG当作一个成熟的RAG解决方案来部署——它更像是一个验证方向可行性的DEMO。
效果展示
从这儿往下是实际效果的对比演示。测试问题:
“讨论使用LLM生成图索引和回答用户查询的局限性。在GraphRAG方法的未来迭代中如何解决这些限制?”
GraphRAG(使用DeepSeek-Chat构建),global模式
DeepSeek-Chat

GPT-4o

GraphRAG(使用DeepSeek-Chat构建),local模式
DeepSeek-Chat

GPT-4o

Dify 对比
作为基准线,加入了Dify的结果。此处的Dify按标准流程配置,使用了带Rerank模型的完整RAG流程,提示词默认,未做改动。
DeepSeek-Chat

GPT-4o

-
- 关于宇宙的好的网名有哪些
- 角色扮演 | 1
- 网名