基于graphRAG和gpt4omini的知识库与目前主流RAG的对比实验记录
GraphRAG 简单介绍
| ** 论文名** | 《 From Local to Global: A Graph RAG Approach to Query-Focused Summarization 》 |
|---|---|
| ** 地址** | https://arxiv.org/pdf/2404.16130 |
| ⛳** Official repo** | https://github.com/microsoft/graphrag |
论文介绍
今年4月,微软团队就在GitHub和arXiv上提前占了坑,但论文发了,代码却一直拖到7月初才开源。那段时间,我自己这边也是诸事缠身,城市变迁,努力很久的目标也没达成,还破财消灾。所以,4月底看到论文时,心里那个盼啊,就指望它能快点开源,好用在项目里加速商业化落地。可等啊等,等到项目都结束了,代码还没出来。现在回头再看这篇论文,倒是平添了几分“何当共剪西窗烛,却话巴山夜雨时”的感慨。相比后来开源的框架,论文里的数据自然是漂亮又可信的。那么问题来了,为什么非要搞出个GraphRAG?
论文里,作者非常明确地指出了一个常规RAG无能为力的场景:
然而,当面对针对整个文本语料库的全局性问题时,比如“这个数据集的主要主题是什么?”,RAG就失效了。因为这类问题本质上是查询聚焦的摘要(QFS)任务,而不是显式的检索任务。
之前的RAG方法,在面对需要全局理解的复杂问题时,确实力不从心。作者给出的解决思路是这样的:
我们与那些利用图索引的结构化检索和遍历能力的工作不同,转而探索了图在此情境下一个先前未触及的特性:其固有的模块性,以及社区检测算法将图划分为紧密相关节点的模块化社区的能力。由LLM生成的这些社区描述的摘要,为底层图索引及其所代表的输入文档提供了完整的覆盖。然后,通过一个Map-Reduce的方法,就能实现对整个语料库的查询聚焦摘要:首先,用每个社区的摘要独立并行地回答查询,最后,将所有相关的局部答案汇总成一个全局答案。
GraphRAG真正的创新点,就在于它把图的模块化和层次化的社区结构给用上了。通过LLM生成图索引和社区摘要,来实现对大规模文本语料库的高效查询聚焦摘要。这在处理需要全局视野的复杂问题时,生成的答案会更全面、更多样化。而在生成最终答案时,它采用了类似Map-Reduce的流程:Map阶段并行生成社区答案,Reduce阶段再汇总成一个综合性的全局答案。这套机制,大大提升了处理大规模数据集的效率。实现方式大概如下图:
GraphRAG 框架
GraphRAG,你可以把它理解成一个利用图机器学习算法来对数据集进行语义聚合和层次化分析的框架。代码结构在GitHub上一目了然。在微软官方的入门指南里,提到了两个顶级模块:Indexing Pipeline和 Query Engine。
Indexing Pipeline,顾名思义,就是一个数据管道,里面包含了一套转换工具,目的是利用LLM从非结构化的文本中,提取出有意义的结构化数据。这个管道是可配置的,由workflows(微软自研的DataShaper)、prompt templates、input/output适配器等部件组成,整体结构相当复杂。可以参看下面这张图:
(来自 源码解读 - 微软GraphRAG框架 )
相比之下,Query Engine就简单多了。执行查询的语句如下:
# Global search
python -m graphrag.query --root ./ragtest --method global "What are the top themes in this story?"
# Local search
python -m graphrag.query --root ./ragtest --method local "Who is Scrooge, and what are his main relationships?"
这里需要注意一下,它区分了Global/Local search两种模式,具体的调用流程可以看下图:
这两个部分的详细解释,可以参考上面的引用文章,这里就不再展开了。下面直接进入本次实验的步骤。
实验过程
环境安装
graphRAG
$ pip install graphrag
# 创建数据集目录
$ mkdir -p ./ragtest/input
RAGFlow:
- CPU >= 4 cores
- RAM >= 16 GB
- Disk >= 50 GB
- Docker >= 24.0.0 & Docker Compose >= v2.26.1
$ sudo sysctl -w vm.max_map_count=262144
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose up -d
当然,如果本地环境达不到要求,也可以用官方提供的线上部署环境,只需提供API key就行。
然后是准备数据集。这里选用了GraphRAG官方测试用例推荐的小说——查尔斯·狄更斯的《圣诞颂歌》,来自古腾堡计划,是一本免费图书。
curl https://www.gutenberg.org/cache/epub/24022/pg24022.txt > ./ragtest/input/book.txt
整部小说篇幅约189K,长度适中,不过是全英文的,我之前没看过,这也为后续的评价埋下了伏笔。
GraphRAG 使用
使用起来也很简单。截至今天,我用的版本好像比7月初刚发版时少了很多东西。之前听说用Ollama跑本地大模型,报错很多,生成质量也堪忧。但看最近的issue,似乎情况好转了。我这边用的是上一篇文章中走第三方API调用的gpt4o-mini。首先生成工作区变量:
python -m graphrag.index --init --root ./ragtest
这会在`./ragtest`目录下创建两个文件:`.env`和 `settings.yaml`。
- `.env`文件里包含运行GraphRAG管道所需的环境变量,打开就能看到定义好的`GRAPHRAG_API_KEY=`,这是OpenAI API或Azure OpenAI端点的API密钥,把它替换成自己的就行。
- `settings.yaml`文件则包含管道的各项设置,可以按需修改。
修改`.env`:
修改`settings.yaml`:
然后运行pipeline:
python -m graphrag.index --root ./ragtest
部分输出日志如下:
entity_graph
0
确认无误后,就可以使用查询引擎了。首先用全局搜索来查询答案:
python -m graphrag.query --root ./ragtest --method global "What are the top themes in this story?"
输出结果我用谷歌翻译了一下:
INFO: Reading settings from ragtest/settings.yaml
creating llm client with {'api_key': 'REDACTED,len=51', 'type': "openai_chat", 'model': 'gpt-4o-mini', 'max_tokens': 4000, 'temperature': 0.0, 'top_p': 1.0, 'n': 1, 'request_timeout': 180.0, 'api_base': 'xxx', 'api_version': None, 'organization': None, 'proxy': None, 'cognitive_services_endpoint': None, 'deployment_name': None, 'model_supports_json': True, 'tokens_per_minute': 0, 'requests_per_minute': 0, 'max_retries': 10, 'max_retry_wait': 10.0, 'sleep_on_rate_limit_recommendation': True, 'concurrent_requests': 25}
SUCCESS: Global Search Response:
## 故事中的关键主题
故事中有几个突出的主题,这些主题增加了故事的深度和道德教训。这些主题围绕着转变、家庭、同情、遗憾以及贫富之间的对比。
### 转变
故事中的一个中心主题是转变,特别是通过埃比尼泽·斯克鲁奇这个角色来体现。他从吝啬到慷慨的转变很大程度上受到圣诞节精神和鬼魂造访的影响。这种转变强调了个人成长和救赎的潜力,表明无论个人过去的行为如何,他们都有可能变得更好[数据:报告(5、20、18、11、13)]。
### 家庭和社区
家庭和社区的重要性是一个反复出现的主题,特别是通过克拉奇特一家在圣诞节期间的团结和爱。尽管他们经济拮据,但他们的互动凸显了困难时期支持和团结的重要性。这一主题强调了家庭纽带和社区联系对于克服逆境至关重要 [数据:报告 (15、14、16、3、19)]。
### 同情心和慷慨
同情心和慷慨也是关键主题,正如史高治最终理解了关心他人(尤其是那些不幸的人)的必要性所表明的那样。故事批判了自私,提倡善良,尤其是在圣诞节期间。这一主题提醒人们有道德义务去支持那些需要帮助的人 [数据:报告 (5、20、14、12、22)]。
### 遗憾和反思
遗憾和反思的主题很突出,尤其是在史高治与鬼魂的遭遇中。这些遭遇迫使他面对自己过去的行为及其后果,强调了自我意识的重要性。这一主题说明了一个人的选择如何影响他人,以及反思自己的生活以促进个人成长的必要性 [数据:报告(11、18、19、13、4)]。
### 财富与贫穷
最后,整个故事都探讨了财富与贫穷之间的对比,特别是通过鲍勃·克拉奇特的性格和克拉奇特家族的挣扎。这一主题强调了社会问题以及那些有能力支持不幸的人的道德责任。它批判了社会不平等,并鼓励富人有责任感,帮助有需要的人 [数据:报告(15、12、17、14、19)]。
### 结论
总之,这个故事包含了引起读者共鸣的深刻主题,强调了转变、家庭和社区的重要性、同情的必要性、反思的价值以及贫富差距的道德含义。这些主题共同传达了有关人类经验和积极变革潜力的强有力的信息。
第二个问题,我们用本地搜索来询问一个关于特定角色的具体问题:
python -m graphrag.query --root ./ragtest --method local "Who is Scrooge, and what are his main relationships?"
## 谁是史高治?
埃比尼泽·史高治是查尔斯·狄更斯的小说《圣诞颂歌》中的主角。史高治最初被描绘成一个吝啬冷酷的老头,他体现了贪婪和对他人冷漠的精神。他对圣诞节的蔑视和缺乏同情心在他与周围人的互动中显而易见,尤其是他的侄子弗雷德和他的员工鲍勃·克拉奇特。然而,在整个故事中,史高治经历了一场深刻的转变,这是由各种灵魂的来访引发的,包括过去、现在和未来的圣诞幽灵。这些遭遇让他反思自己的人生选择,最终导致性格发生了重大变化,从孤立和自私变成了慷慨和同情[数据:实体(4、18);关系(16、31、41)]。
## 主要关系
### 1. **鲍勃·克拉奇特**
史高治与鲍勃·克拉奇特的关系是阐释财富与贫穷主题的关键。起初,史高治对鲍勃很差,反映出他的吝啬和缺乏同情心。然而,随着史高治的转变,他开始认识到鲍勃的挣扎,并最终决定提高他的薪水并养家糊口,标志着他向善良和同情心的重大转变[数据:关系(16,7)]。
### 2. **弗雷德(史高治的侄子)**
弗雷德代表着家庭的温暖和圣诞节的精神,与史高治的消极态度形成鲜明对比。尽管史高治对他不屑一顾,但弗雷德坚持邀请他的叔叔参加节日庆祝活动,强调了家庭关系的重要性。这种关系强调了史高治最初的孤立以及他最终意识到家庭纽带的价值 [数据:关系 (60, 62)]。
### 3. **雅各布·马利**
雅各布·马利是史高治已故的商业伙伴,也是史高治转变的关键催化剂。马利的鬼魂来访警告了人们没有同情心的生活会带来的后果,敦促史高治改变自己的生活方式。这次遭遇不仅强调了遗憾和救赎的主题,还建立了指导史高治旅程的超自然框架 [数据:关系 (41, 78)]。
### 4. **小蒂姆**
小蒂姆是鲍勃·克拉奇特最小的儿子,他成为史高治转变中的重要人物。史高治对小蒂姆健康和幸福的关心凸显了他改变心态的影响。故事结束时,史高治成为了小蒂姆的第二个父亲形象,展现了他帮助克拉奇特家族的新承诺 [数据:关系 (33)]。
### 5. **费兹威格**
史高治的前雇主费兹威格在史高治的记忆中是一位善良慷慨的老板。这种关系与史高治现在的行为形成了鲜明的对比,并影响了他的转变。费兹威格圣诞派对的快乐回忆让史高治想起了善良的重要性和积极领导的影响 [数据:关系 (12, 48)]。
## 结论
史高治的性格弧线由他与他人的关系定义,这些关系就像一面镜子,反映了他最初的缺点和最终的救赎。通过与鲍勃·克拉奇特、弗雷德、雅各布·马利、小蒂姆和费兹维格的互动,史高治学会了同情、家庭和社区的价值,最终拥抱了圣诞节的真正精神[数据:实体 (4、5、11、14、22);关系 (16、31、41、60、62)]。
RAGFlow
本次实验在本地搭建了RAGFlow环境,使用了内置的`BAAI/bge-large-zh-v1.5` embedding模型,并开启了`RAPTOR`策略,最大聚类数设为64,阈值为0.1。没有使用rerank,而是采用关键词相似度和向量余弦的加权值(权重为0.2),top N设为8。为了与GraphRAG对齐,最大token数设为1200。大模型接口选用的是chatglm4/3.5,提示词均使用默认值:
# knowledge prompt
请总结以下段落。 小心数字,不要编造。 段落如下:
{cluster_content}
以上就是你需要总结的内容。
# chat
你是一个智能助手,请总结知识库的内容来回答问题,请列举知识库中的数据详细回答。当所有知识库内容都与问题无关时,你的回答必须包括“知识库中未找到您要的答案!”这句话。回答需要考虑聊天历史。
以下是知识库:
{knowledge}
以上是知识库。
同样,第一个问题的回答翻译成中文后:
这个故事的主要主题包括:
救赎和转变:主角埃比尼泽·斯克鲁奇在受到过去、现在和未来的圣诞幽灵的拜访后,经历了深刻的转变,从一个吝啬、痛苦的老人变成了一个慷慨、善良的人。
圣诞精神:故事强调了圣诞精神的重要性,包括慷慨、欢乐和家庭团聚。
贪婪和自私的后果:斯克鲁奇的吝啬导致孤独、不快乐的生活,而他转变为一个慷慨的人则带来了幸福和满足。
家庭和人际关系的重要性:故事强调了家庭、朋友和人际关系在给生活带来欢乐和意义方面的重要性。
记忆和反思的力量:圣诞幽灵的来访让斯克鲁奇反思自己的生活和所做的选择,从而实现了他的转变。
财富与贫穷的对比:故事将富有的史高治的吝啬与克拉奇特一家的贫穷与挣扎进行了对比,强调了慷慨和同情的重要性。
故事的永恒性:尽管故事背景设定在 19 世纪,但《圣诞颂歌》的主题今天仍然具有现实意义,强调了救赎、爱和圣诞精神的持久力量。
第二个问题的回答:
埃比尼泽·斯克鲁奇是查尔斯·狄更斯的小说《圣诞颂歌》中的主人公。他是一个吝啬又苦涩的老头,在伦敦做放债人。斯克鲁奇以吝啬、厌恶圣诞节和脾气暴躁而闻名。
故事中斯克鲁奇的主要关系包括:
鲍勃·克拉奇特:斯克鲁奇的雇员,克拉奇特是一个善良勤奋的职员,尽管薪水很低,但他还是为斯克鲁奇工作。克拉奇特有一个大家庭,包括他的妻子玛莎和他们的孩子,其中最小的孩子小蒂姆特别令人难忘。
弗雷德:斯克鲁奇的侄子,弗雷德是一个热情慷慨的人,经常邀请斯克鲁奇和家人一起过圣诞节,但斯克鲁奇总是拒绝。弗雷德开朗、亲切的性格与斯克鲁奇吝啬、孤独的生活方式形成了鲜明的对比。
圣诞幽灵的过去、现在和未来:这些超自然生物被派来向史高治指出他所犯的错误。圣诞幽灵的过去向史高治展示了他过去的场景,圣诞幽灵的现在向他展示了现在的欢乐和挣扎,圣诞幽灵的未到来向他展示了他未来行为的后果。
马利的幽灵:史高治的前商业伙伴雅各布·马利以幽灵的形式出现,警告史高治圣诞幽灵即将来访。马利的灵魂因为他的吝啬而被束缚在地球上,他试图拯救史高治,使他免于同样的命运。
通过这些关系以及幽灵向他展示的经历,史高治经历了深刻的转变,成为一个更善良、更慷慨的人,他重视人际关系和圣诞精神。
鼠标移到这段总结性语录结束句号后的“i”标志上,可以看到知识库具体选择抽取的内容:

对比结果
对比之下,差异就比较明显了。尤其是在第二个问题上。查阅维基百科关于《圣诞颂歌》的介绍可以发现,GraphRAG的答案显然更准确。而RAGFlow在最初的人物关系介绍上,就犯了不少错误。这也正好印证了图谱技术的作用。第一个问题的回答倒是大同小异,两者没有明显差距。另外,`RAPTOR`本质上也是一种接近QFS的方式,但深入垂直领域,似乎落地依然困难。GraphRAG在总结性和关联性上做了优化,如果只看论文,它几乎是一个完美的落地选择。但真正体验过后就会发现,它的短板也异常突出。
根据市场反馈,在gpt4o-mini出现之前,GraphRAG最初的版本,同样是《圣诞颂歌》,用GPT来构建就需要调用449次接口,换算成美元是10刀,查询还要再花1刀。而采用embedding+rerank的RAG方式,即便加入了策略,也只需要调用不到20次。这中间的差距,非财力雄厚者,真是望而却步。我本次实验选用的gpt4o-mini就友好太多了,可能GraphRAG的版本也有更新,计算下来,当前构建完整本书后的调用次数大概是205次左右,换算一下只需要1刀出头。看来GraphRAG和gpt4o-mini是绝配。至于其他本地大模型的方式,没来得及试,感觉还有很多优化的空间。微软这时候把它开源出来,未尝不是“路漫漫其修远兮”,要靠社区一起求索了。
按说,文章最后可以用langsmith和ragas对结果进行量化对比。但书没看过,下午本想搞一套《诡秘之主》的txt文本,发现太大了。另外找书的时候,又被其他小说吸引过去了。所以,emmm,就这样吧。
-
- 关于宇宙的好的网名有哪些
- 角色扮演 | 1
- 网名