GraphRAG学习小结(2)

 3.GraphRAG原理

吐槽:嗯...还没进入正题就已经花了一万多字。这篇文章通篇文字量也会很可怕吧。

参考:https://juejin.cn/post/7392115478561325083

整个GraphRAG的pipeline如下图所示。

3.1 数据预处理

Source Documents → Text Chunks 源文件到文本块

这一过程与RAG一样,这里就不再赘述。

Text Chunks → Element Instances 文本块到元素实例

这一步的基本要求是从源文本的每个块中识别并提取图节点和边的实例。这是使用多部分 LLM prompt来完成的,首先识别文本中的所有实体,包括它们的名称、类型和描述,然后识别明确相关实体之间的所有关系,包括源实体和目标实体以及它们之间关系的描述。这两种元素实例都会以单个分隔元组列表的形式输出。

Entities(实体):实体指的是现实世界中的具体事物或者概念,它们可以是人、地点、组织、事件、抽象概念等。

例如,在句子“奥巴马出生于夏威夷。”中,“奥巴马”和“夏威夷”是实体。在 GraphRAG 中一个 Entity 包含了实体名称、实体类型和实体描述。

Relationships(关系):关系描述了实体之间的联系。

例如,在上述句子中,“出生于”就是一种关系,它连接了实体“奥巴马”和“夏威夷”。在 GraphRAG 中一个 Relationships 包含了关系两端的实体名称和关系描述。

此外还会提供给 LLM 用于上下文学习的少量实例。

举例来说,虽然我们的默认prompt一般适用于提取人物、地点和组织等 “命名实体 ”的广泛类别,但具有专业知识的领域(如科学、医学和法律)将受益于专门针对这些领域的少量示例。我们还支持二次提取prompt,用于提取与节点实例相关联的其他协变量。我们的默认协变量提示旨在提取与检测到的实体相关联的声明(claims),包括主题、对象、类型、描述、源文本跨度以及开始和结束日期。

Claims(声明):主张通常指的是关于实体及其关系的陈述,它包含了一个或多个实体和关系的信息。

例如:“奥巴马是美国第44任总统”,就是关于实体“奥巴马”的一个声明。

为了在效率和质量之间取得平衡,我们使用多轮 “拾取(gleanings)”(达到规定的最大值),以鼓励 LLM 检测其在前几轮提取中可能遗漏的任何其他实体。这是一个多阶段的过程,在这个过程中,我们首先要求 LLM 评估是否提取了所有实体,并使用 100 的对数偏差来强制做出 “是/否 ”的决定。如果 LLM 回答说遗漏了实体,那么我们会继续指出 “上次提取遗漏了很多实体”,鼓励 LLM 提取这些遗漏的实体。这种方法允许我们在不降低质量或强制引入噪音的情况下使用更大的块大小。

这里可以发现使用2400的chunk在2次拾取后可以和1200的chunk在一次拾取后得到的实体数量相当。

3.2 构建graph数据

Element Instances → Element Summaries 元素实例到元素摘要

使用 LLM 来 “提取 ”源文本中的实体、关系和主张的描述已经是一种抽象总结的形式,它依赖于 LLM 为文本本身可能隐含但未说明的概念(例如,隐含关系的存在)创建独立有意义的总结。要将所有此类实例级摘要转换为针对每个图元素(即实体节点、关系边和协变量)的描述性文本块,需要在匹配的实例组上再进行一轮 LLM 摘要。

这一阶段的一个潜在问题是,LLM 可能无法以相同的文本格式始终如一地提取对同一实体的引用,从而导致实体图中出现重复的实体元素和重复的节点。不过,由于所有密切相关的实体 “社群(communities)”都将在下一步中被检测和总结,而且 LLM 可以理解多个名称变体背后的共同实体,因此只要所有变体都与密切相关的实体共享集有足够的连接性,我们的整体方法就能抵御此类变体。

这是原论文的表述,对于这一点我是存疑的,并且在后续的实验中发现在某些情况下这个论断并不成立。

总之,我们在可能存在噪声的图结构中为同质节点使用丰富的描述性文本,这既符合 LLM 的能力,也符合以查询为重点的全局摘要的需求。这些特性也使我们的图索引有别于典型的知识图谱,后者依赖于简洁一致的知识三元组(主语、谓语、宾语)来完成下游推理任务。

3.3 构建社群结构

Element Summaries → Graph Communities 元素摘要到图社群

目前看到普遍把community翻译成“社区”,但就我个人而言,“社群”更符合中文语境,故后面的community结构的中文翻译都采用“社群”。

上一步创建的索引可以建模为同质无向加权图,其中实体节点由关系边连接,边权重代表检测到的关系实例的归一化计数。给定这样一个图,可以使用各种社群检测算法将图划分为相互之间的连接强于图中其他节点的节点社群。

在graphrag中,使用莱顿( Leiden)算法,因为它能够高效地恢复大规模图的分层群落结构。这种分层结构的每一层都提供了一个社群分区,以相互排斥、集体穷举的方式覆盖图中的节点,从而实现分而治之的全局总结。

Community社群结构是指在一个更大的网络中,节点(如 GraphRAG 中的实体)倾向于形成密集的局部集群,这些集群被称为 Community。Community 内部的节点之间有较多的边(联系),而 Community 之间的边则相对较少。换句话说,Community 结构体现了网络中节点的聚类特性,这些节点基于某种相似性或功能上的关联性而聚集在一起。

如下图:圆圈代表实体节点,大小与其度数(即与之相连的边的数量)成正比。节点颜色代表实体群落,表示了在全部节点中的社区分布结构。

Graph Communities → Community Summaries 图社群到社群摘要

下一步是使用一种可扩展到超大数据集的方法,为莱顿层次结构中的每个社群创建类似报告的摘要。这些摘要本身就很有用,是了解数据集整体结构和语义的一种方法,而且在没有问题的情况下,摘要本身也可以用来理解语料库。

例如,用户可以先浏览某一层次的社区摘要,寻找感兴趣的一般主题,然后通过链接进入较低层次的报告,了解每个子主题的更多细节。不过,现在我们优先关注其作为回答全局查询问题的索引的这一部分的功能。

社群摘要的生成方式如下:

- 叶级社群。叶级社群的元素摘要(节点、边、协变量)会被优先排序,然后迭代添加到 LLM 上下文窗口中,直到达到标记限制。优先级排序如下:按照源节点和目标节点的综合程度(即总体突出度)递减顺序,为每个社群边缘添加源节点、目标节点、关联协变量和边缘本身的描述。

- 高级社群。如果所有元素摘要都在文本窗口的标记限制范围内,则按照叶级群落的方法,对社群内的所有元素摘要进行汇总。否则,将子社群按元素摘要标记递减顺序排列,并用子群落摘要(较短)替换相关元素摘要(较长),直到符合上下文窗口的要求。

总的来说,在此阶段,GraphRAG 会为不同层级的社群建立报告(Report),而这些报告代表了对原始数据不同层次的理解。形象来说,这些社区构成了一个树状结构,更接近根的社区报告通常覆盖了更大的范围,代表了更加全局和概括性的理解。而越接近枝叶的社区通常覆盖面越窄,理解也越微观。

此外,这种报告也可以作为理解数据全局结构的一种方式,可以通过摘要找到有用的社群,然后下潜到包含更详细信息的子社群中。

这部分内容我们在后面可视化例子以及graphrag的原码中再进一步讨论。

3.4 Query过程

GraphRAG 提供了两种不同的查询模式。

Global Query 用于回答更加全局性的问题,例如“请分析故事的主旨”,而 Local Query 则用于回答更加具体的问题。

3.4.1 Global Query

Community Summaries → Community Answers → Global Answer

社群摘要-社群回答-全局回答

给定用户查询后,上一步生成的社群摘要可用于在多阶段过程中生成最终答案。社群结构的分层性质也意味着可以使用不同层级的摘要来回答问题,这就提出了一个问题,即分层社群结构中的某一特定层级是否能为一般感性问题提供摘要细节和范围的最佳平衡。

对于给定的社群层级,用户查询的全局答案生成过程如下图所示

- 准备社群摘要。对社群摘要进行随机洗牌,并按预先规定的标记大小分成若干小块。这样可以确保相关信息分布在不同的块中,而不是集中在一个上下文窗口中(可能会丢失)。
- 映射社群答案。并行生成中间答案,每个分块一个。还要求 LLM 在 0-100 之间生成一个分数,表示生成的答案对回答目标问题的帮助程度。得分为 0 的答案会被过滤掉。
- 还原为全局答案。中间社群答案按照有用性得分从高到低排序,并反复添加到新的上下文窗口中,直到达到标记限制。最终的上下文将用于生成返回给用户的全局答案。

Global Query 方法使用从社区层次结构指定层级中收集的报告作为上下文数据,以类似Map - Reduce的方式生成响应。在 Map 步骤中,社区报告被分割成文本块,每个文本块用于生成中间响应,其中每个点都有一个数值评级。在 Reduce 步骤中,从中间响应中挑选出最重要的点并进行聚合,最终形成用于生成最终响应的上下文。

这种方法的直观理解是:越宏观的问题需要越宏观的视角和信息来回答。

社区层次结构中的每一层代表着不同粒度的信息集合。高层级可能包含更为概括和宏观的观点,而低层级则提供具体和细节化的信息。对于宏观问题,系统倾向于选择较高层级的数据,以捕捉整体趋势和主要观点。

通过 Map - Reduce 过程,系统可以选择对于原始问题的重要性或相关性较高的信息,并进一步提炼和汇总,形成数个精炼的、综合的上下文。这个上下文包含了对原始问题最相关的见解和数据,是生成最终回答的基础。

3.4.2 Local Query

本地查询则基于更加微观的视角,结合知识图谱中的结构化数据与原始文档中的非结构化数据,来增强检索和生成过程中的上下文。因此,Local Query 别适合回答那些需要理解输入文档中特定实体的问题,比如询问“洋甘菊有哪些治疗特性?”这样的问题。

具体而言,Local Query 的过程如图所示:

首先,系统将依据原始提问,从知识图谱中识别出一组与用户输入语义相关的实体。

然后,利用这些实体作为查询条件,在知识图谱或相关数据库中进行检索,找到与这些实体直接相关的内容,包含:TextUnit、社群报告、实体、关系或协变量(如主张)。

检索的结果经过过滤和重排序后,选择高质量的数据源,并将其整合进一个预定义大小的上下文窗口。这个窗口内的信息用于构建响应,确保回答内容既精确又详尽。

3.5 GraphRAG评估

这部分本来不打算详细说的,但里面有些比较值得关注的点,所以还是借着原论文整理一下。

GraphRAG的评估方式只针对全局性问题,而且问题本身是由大模型自己生成的,而且后面会发现评价也是大模型完成的。给定数据集的简短描述后,要求 LLM 识别 N 个潜在用户和每个用户的 N 项任务,然后针对每个(用户、任务)组合,要求 LLM 生成 N 个需要理解整个语料库的问题。

分析中比较了六种不同的条件,包括使用四级图社群(C0、C1、C2、C3)、直接把map-reduce 方法应用于源文本的文本摘要方法(TS),以及 “语义搜索 ”的朴素RAG 方法

- C0. 使用根级社群摘要(数量最少)回答用户查询。
- C1. 使用高级社区摘要回答查询。这些是C0的子社区,否则 C0 社区向下推算。
- C2. 使用中级社区摘要回答查询。这些是 C1 的子社区(如果存在),否则 C1 社区向下投影。
- C3. 使用低级社区摘要(数量最多)回答查询。这些是 C2 的子社区(如果存在),否则 C2 社区向下投影。
- TS. 只是源文本(而非社区摘要),在 map-reduce 摘要阶段会被洗牌和分块。
- SS. 朴素RAG 的实现,其中文本块被检索并添加到可用的上下文窗口,直到达到指定的标记限制。

使用 LLM 评估器计算的指标如下:
- 全面性。答案提供了多少细节以涵盖问题的所有方面和细节?
- 多样性。答案在提供有关问题的不同观点和见解方面的多样性和丰富程度如何?
- 有效性。答案在多大程度上帮助读者理解题目并做出明智的判断?
- 直接性。答案如何具体、清晰地回答问题?

在评估中,向 LLM 提供了问题、目标指标和一对答案,并要求它根据指标评估哪个答案更好,以及为什么。如果存在获胜者,则返回获胜者,否则,如果两者基本相似且差异可以忽略不计,则返回平局。考虑到 LLM 的随机性,将每次比较运行五次,并使用平均分数。

测试了四种上下文窗口大小: 8k、16k、32k 和 64k。令人惊讶的是,在所有比较中,测试的最小上下文窗口大小(8k)在全面性(平均胜率为 58.1%)方面普遍更胜一筹,而在多样性(平均胜率 = 52.4%)和有效性(平均胜率 = 51.3%)方面的表现与较大的上下文大小相当。考虑到更倾向于更全面、更多样化的答案,因此在最终评估中使用了 8k 标记的固定上下文窗口大小。

实验结果如下图所示

这是一个胜率表,横轴和纵轴的胜率,所以对角线都为50%,因为是自己和自己比。其实对比C0,1,2,3和TS的全面性和多样性这一项可以发现,提供更多增强的可能是map-reduce方法(即TS对比SS),图结构的增强效果有限。另外在Empowerment这一项数据就更尴尬了。

4.GraphRAG测试

这里就参考官方的网站:Get Started

这个网站也有很多原理讲解和代码演示,后续深入代码我们还会细看。

安装graphRAG

pip install graphrag

创建实验用的目录及输入文档的目录

mkdir -p ./ragtest/input

把测试文档传入,目前只支持txt

官方用的是狄更斯的小说《圣诞颂歌》。可以替换成自己熟悉的文档,这样后面可视化和看社群分类会更轻松一些。

这里我使用的是自己写的小说《冬日诗篇》。

接下来初始化graphRAG

python -m graphrag.index --init --root ./ragtest

会得到下面这些文件,之后只要简单修改一下settings文件就可以使用了。

具体需要修改以下几个位置

llm部分

这里我用了deepseek和moonshot(kimi)分别做了测试,都可以跑通。

llm:
  api_key: 填你自己的,我可不会傻傻的发自己的
  type: openai_chat # or azure_openai_chat
  model: moonshot-v1-8k #deepseek-chat
  model_supports_json: false # recommended if this is available for your model.
  # max_tokens: 4000
  # request_timeout: 180.0
  api_base: https://api.moonshot.cn/v1 #https://api.deepseek.com/v1

embeddings部分

这里推荐使用清华的智谱AI,这个embedding用起来也不错。

embeddings:
  ## parallelization: override the global parallelization settings for embeddings
  async_mode: threaded # or asyncio
  llm:
    api_key: 填你自己的,差点就忘了改
    type: openai_embedding # or azure_openai_embedding
    model: embedding-2
    api_base: https://open.bigmodel.cn/api/paas/v4

snapshots部分

snapshots:
  graphml: true
  raw_entities: true
  top_level_nodes: true

这里是为了可视化做准备,这样修改后在output里会生成几个graphml文件。

在完成settings文件的调整之后执行下面的命令

python -m graphrag.index --root ./ragtest

我的例子(7万字小说)等待全部执行完大概要20min

然后就可以进行提问了

全局问题

python -m graphrag.query \
--root ./ragtest \
--method global \
"请输入全局问题,比如主旨相关的内容。"

局部问题

python -m graphrag.query \
--root ./ragtest \
--method local \
"请输入局部问题,比如xxx是谁?"

这回终于可以问出我们开头的问题了。

请概括小说的故事情节并分析故事的主旨。

### 故事情节概括

小说通过一系列社区和人物的故事,深入探讨了个体在不同社会环境中的情感动态、个人成长和人际关系的复杂性。从学校教育环境到家庭和社交活动,再到个人的情感体验,每个故事都揭示了人物之间的复杂联系和个体在社会中的角色。这些故事涵盖了从学校生活到个人兴趣,从神秘的自然现象到社区的社交活动,展现了人物内心世界的一角。

### 故事主旨分析

1. **人际关系的影响**:小说的主旨之一在于探索人与人之间的关系如何影响个体的行为和决策。无论是在教育、家庭还是社交场合,人物之间的相互作用塑造了他们的个性和生活轨迹。这强调了社会联系对个人成长的重要性以及情感纽带在人际关系中的核心作用。

2. **自我认同与归属感**:故事还着重探讨了个体如何在社会环境中寻找自我认同和归属感。在校园中的学术竞争和情感联系,以及社区中的文化和历史体验中,小说强调了人与人之间相互依存和影响的重要性。

3. **自我认知与成长**:此外,小说通过情感交流、个人反思和社会互动,展现了个体在各种生活场景中实现自我认知和成长的过程。这表明个体与社会的关系是动态的,个体的成长是一个不断与外界互动和内心反思相结合的复杂过程。

通过这些分析,我们可以看到小说不仅仅是一系列事件的叙述,而是一个深入探讨人类情感和社会互动的复杂网络。每个故事都是对人性深层次理解的一次尝试,通过不同的社区和人物关系,作者向我们展示了一个多维度的、充满情感纠葛和个人成长的世界。

这是graphrag的答案,与GraphRAG学习小结(1)-CSDN博客中的对比可以发现故事情节的得到了整体性概括,主旨也丰富了很多。但是同时也可以从回答中发现一些问题,比如总是出现的名词“社区”,显然是由于“社群摘要”里的community被翻译成了社区,这是因为原码用的英文prompt,在后面部分我们尝试用中文prompt重新修改原码,看看会不会有提升。此外在接下来的可视化部分也可以比较清楚的看到原理中展现的各个部分,包括“社群摘要”。

5.知识图谱可视化与分析

5.1 知识图谱可视化过程

首先下载一个可以读取graphml文件的程序gephi

 官网:https://gephi.org

我个人觉得用起来很方便,后面就以此为例展示知识图谱了。

在上面的测试执行结束后,output文件夹会默认输出一个以你执行该程序的时间为命名的文件夹,在artifacts文件内可以找到后缀为graphml的文件。

如下图所示

具体来说有这些文件,用Gephi打开以后会发现除了clustered与别人不一样外,其他几乎都一致,为什么会这样还要具体看代码。

第一步先打开,因为graphRAG生成的是无向图,所以图的类型选择“无向的”即可,这里也可以看到我这个任务生成的知识图谱节点数为352,边数为513。

然后看到的知识图谱如图所示,并不是很美观,具体如何操作完全可以自己摸索,我这里只给出个人比较喜欢的整理方式

首先点击下面状态栏的T,可以将节点的名称显示出来

旁边的选项可以调节汉字的大小以及字体,如果是乱码很可能是因为使用了不支持中文的字体

之后就会变成这个样子

然后我们在左侧选择布局,然后点击运行,如下图所示,这些布局都可以尝试,我选择这个是因为这样汉字看起来比较清楚。

执行结果如下图所示,已经可以看到比较清楚的结构了,不过为了更清楚看各个节点的关系,这里再做一点处理

选择左上的对话框,如图所示,可以将节点按颜色进行分割

执行结果如下图所示,这里的type是指实体的类别,

分类和论文中的阐述一致,

此外,点击左上角的数据资料就可以看到每个节点和边的相关信息,最重要的自然是description一项,graphRAG对每个节点和边都使用大模型生成了相关描述,这也是为什么会耗费如此多token的原因之一,具体如下图所示。

至此,就基本完成了知识图谱的可视化。下面我们针对得到的知识图谱进行简单的分析。

5.2 知识图谱结果的简要分析

按照知识图谱构建的顺序,我们也按同样的顺序来看结果。

5.2.1 实体与实体摘要

首先来看小说中最常出现的实体“我”,该实体的摘要如下。

 "文中的叙述者,经历了书籍被损坏的事件,感到非常委屈。" "文中的第一人称,对女孩子的行为感到不满,并且因为被叫做幽灵而生气,但后来接受了女孩子的道歉。" "The speaker in the text, who is contemplating whether to return borrowed clothes and recalls a past incident of hiding a broken teapot." "文中的第一人称角色,与'她'有互动,内心有决心和情感波动。"  "文中的叙述者,提出了一个方案并尝试执行,但遇到了沙子冻住的难题。" "我是文中的叙述者,参与了雪屋的建造,对雪屋的舒适度表示满意。" "文中的叙述者,与女主角有对话和互动,表现出幽默和逃避的行为。" "提议去秋千处转换心情,站在她背后轻轻推秋千,观察她的表情和呼吸。" "文中的叙述者,与女性角色进行对话,观察她荡秋千。" "文中的叙述者,观察并描述了女主角荡秋千的场景,对她产生了一种害怕失去的感觉。" "文中的叙述者,一个十岁的孩子,正在享受与某个人共度的时光。" "文中的叙述者,经历了被怪物吓到并哭泣,随后被安慰的过程。" "文中的叙述者,与女性角色一起在夜晚行走,对女性角色的到来表示感谢。" "文中的第一人称角色,承诺会陪伴和保护文中的女性角色。" "我是故事的叙述者,参与了对话并阅读了书。"  "我是被教导的对象,对教导者的性格和教学方式有深刻的感受。" "我是叙述者,与'她'在雪屋中互动,表现出一种反思和自我批评的态度。" "文中的叙述者,与女性角色有约定,对约定的态度较为轻松,但对街上的变化和节日没有注意到。" "文中的叙述者,与爸爸和妈妈一起度过家庭时光,感到开心但也有不安和愧疚。"  "文中的叙述者,对幽灵女孩有着深厚的感情,表现出强烈的不舍和挽留之情。" "文中的叙述者,与女性角色有互动,参与了雪屋的修复工作,并在废弃公园与她有进一步的交流。" "文中的叙述者,对“她”有情感,但对如何表达这份情感感到困惑和随意。" "文中的叙述者,表达了自己的情感和对情感的困惑,以及对与他人建立关系的犹豫。" "我是故事的主角,经历了情感波动,晚上偷偷离家去公园。" "文中的第一人称叙述者,深夜出门,带着盒子来到公园,与'她'有着某种联系。" "主角在公园里尝试给某人一个惊喜,但遇到了困难,表现出情感上的脆弱。" "文中的叙述者,与另一个角色有着深厚的情感联系,对未知的未来感到不安。" "文中的叙述者,与女主角有着情感交流。" "文中的叙述者,与女性角色有互动,表现出对春天和丁香树的喜爱。" "我是指文本的叙述者,他/她通过回忆过去的经历来反思自己的生活和价值观。"

"文中的叙述者,一位女性,与另一个人交流时使用纸条和肢体语言。" "文中的叙述者,被邀请参加她的生日庆祝活动,并在家长会上感到尴尬。" "我是家长会中被讨论的学生,数学成绩有显著提升,但英语成绩被他超过。" "我是叙述者,对聚会的时间和内容有自己的感受和看法。" "文中的叙述者,对同学录持有反对意见,但会认真填写别人给的同学录。" "文中的叙述者,对同学录的准备和收到的内容感到好奇,同时对自己的外貌和成绩感到不自信。" "文中的叙述者,与'他'有对话,表现出对'他'的不满,但具体身份和背景信息不详。" "文中的叙述者,对即将开始的四年学习生活感到安心,对座位的选择有些无奈。" "我是文本的叙述者,与那个女人有孽缘,并且她经常在吃午饭时坐在我旁边。" "我是文中的叙述者,参与了剧本《小王子》的准备,负责灯光控制二号。" "我是参与话剧活动的学生之一,负责灯光控制二号。" "一个观看表演并安慰对方不要紧张的人,之前可能在排练中弄错过顺序。" "文中的叙述者,与'她'关系亲密,参与了学校的社会实践活动,与'她'一起回家,共同参与了调查报告的制作。" "我 is the narrator of the text, asking about the telescope and observing the conversation." "我是对话中的一员,正在询问关于天文望远镜的问题。" "我 is the narrator of the text, attending tutoring classes and has a special interest in the person mentioned as '他'." "文中的叙述者,表现出对某人的关心和自我反思。" "我是故事的叙述者,曾经因为读物理书而感到困倦,选择了文科,并在心中对'他'有着特别的感情。" "我是故事的叙述者,经历了一天的忙碌,体验了使用发令枪,并在寻找丢失的橡皮时表现出对物品的情感价值的重视。"  "文中的叙述者,正在体育场等待,观察着周围的环境。" "文中的叙述者,对“他”有情感依恋,体验了与“他”的互动和情感变化。" "文中的叙述者,与另一个人物有互动,表达了自己的想法和感受。" "我是对话中的另一个角色,住在学校附近的亲戚家,已经逐渐习惯了。" "文中的叙述者,对“他”有情感上的牵挂,正在考虑如何与他在同一所学校。" "文中的叙述者,一年前从妈妈那里得知了某个人的志愿,决定离开小城来到省会城市,现在在名校读书。" "文中的叙述者,经历了从幻想奇迹到接受现实的转变,感受到了成长带来的淡淡伤感。" "文中的叙述者,经历了雪地的重塑和摔倒,对某个破坏乐园的家伙抱有期待。" "文中的叙述者,与男主角有一段情感交流,表现出惊讶和对男主角行为的好奇。" "文中的叙述者,与'他'有着深厚的情感纽带,经常在'他'的陪伴下哭泣。" "文中的叙述者,表达了对某个人的感情和对未来的期待。" "文中的叙述者,与另一个人有特殊的关系,进行了恶作剧并在课堂上期待对方的反应。" "文中的第一人称,表达了对体育测试的恐惧和个人性格特点。" "文中的叙述者,经历了怒火和咳嗽,通过音乐平复心情,与对方进行了对话。"  "文中的叙述者,对图书馆旁的景色有美好的幻想,与男主角一起走在这条路上,并对男主角的恶作剧有所反应。" "文中的叙述者,对个人形象有所改变,参与了初中同学聚会。" "文中的叙述者,对某个人抱有期待,并且为了与对方见面做了精心准备。" "文中的第一人称,等待某人,感到有些冷,对其他人的视线感到不适。" "文中的第一人称,等待他人,后来在图书馆附近与他人相遇。" "文中的第一人称主角,内心挣扎后决定跟踪某人,最终跟随对方进入图书馆。" "文中的'我'是一个跟踪'他'的人物,试图在不被发现的情况下观察'他'。" "对话中的另一个人物,与'他'进行交流,询问他的兴趣和适合的工作。" "文中的第一人称叙述者,与阳一起在绿茵场上,对未来充满憧憬。" "我是指文中的叙述者,一个有着复杂情感和评价的个体,经历了不同的时期和状态。" "文中的叙述者,与女性角色一起在林间空地进行野餐,并向她解释十二星座的起源。" "文中的叙述者,与女性角色有亲密的互动,评价她是否独立可靠。" "文中的叙述者,表达了对身边人的感激之情,以及对未来的不确定性和对幸福的追求。" "文中的叙述者,对女主角有着深厚的情感,期待与她共度未来。" "文中的叙述者,与女主角在桥下有亲密的互动。" "文中的叙述者,对男性角色的行为感到恼火,并采取了惩罚措施。" "I am a person who is described as being focused on science subjects and has a close relationship with '他'." "文中的叙述者,与'他'有较深的关系,共同学习并计划考上同一所大学。"

"文中的叙述者,对触摸对方的喉结表现出好奇,主动提出要求。" "文中的女主角,与男主角有亲密的互动,感受到男主角的关心和保护。" "文中的叙述者,与女性角色有亲密的互动,对她有保护和珍惜的情感。" "文中的叙述者,与女主角有着亲密的关系,表现出关心和对女主角情感的珍视。" "文中的叙述者,与女主角共同经历了许多重要时刻,包括复习、中考、分班和初吻。" "文中的叙述者,与女性角色有深厚的情感联系,同样对即将发生的分离感到不舍。" "文中的第一人称角色,试图安慰对方,表现出理解和关心。" "我是文中的主要人物之一,提议去科技馆,并与她讨论相关计划。" "文中的叙述者,表现出对与女主角相处的期待和兴奋。"

这里我刻意将其分成了三部分(原本输出的摘要并没有划分部分),因为在小说里的我分别对应不同的角色。对于人类读者来说,小说有着明显的章节和标题,即使文中的“我”所代表的角色发生变化也可以轻松地辨别和理解。但是对于大模型来说,或者目前graphRAG使用的实体提取和摘要生成方法并没有办法解决。

问题1:同名称不同意义的实体无法分辨,尤其是抽象名词,如“我”,“她”,“它”等人称代词。

不过这里我们再来看好的一些实体提取和摘要。

比如小说中第一个故事的主人公,“雪做的女孩”。摘要如下。

"雪做的女孩是一个由雪构成的神秘人物,出现在公园中,与叙述者进行交流。" "雪做的女孩是一个由雪制成的人物,具有与正常女孩相似的外观,但全身由雪构成,穿着雪做的裙子,没有鞋子,看起来非常精致且虚幻。" "雪做的女孩是主角期待再次相遇的对象,但文中没有提供更多关于她的信息。" "雪做的女孩是一个神秘而未知的存在,具有可怕的个性,但并不让叙述者感到害怕。"

信息基本正确,而且相对比较有概括性,从外貌到性格都有描述。

再来看一个抽象一些的名词,比如贯穿小说的自然现象“雪”,摘要如下。

"雪是讲述者提到的一种自然现象,发生在使用天文望远镜的那天,导致望远镜没有用上。" "雪是故事中的重要元素,覆盖了外面的世界,给少女带来了触感上的享受。" 

虽然同样糅合了两个故事,但在local问题上这段摘要依旧可以为回答提供帮助。

再看一个“EVENT”实体,“中考”,摘要如下。

"中考是中国的中学毕业考试,说话者和同桌需要准备参加,以决定他们未来的学习道路。" "中考是中国的中学入学考试,是男女主角进入同一所高中的途径,也是他们关系发展的一个重要节点。"

对内容概括比较准确,同样在local问题上会有帮助。

最后看一下“GEO”实体,也就是地点,“海底深处”“夜空”摘要如下。

"海底深处是文中提到的一个地点,象征着宁静和沉重。"

"夜空是故事发生的背景,被描述为被点亮,像烟花一样,并且有星星相互碰撞,泛起涟漪。"

除了场景本身外还外加了大模型自己进行的情感性分析,对于场景相关的local问题可以提供比较好的信息支持。

总体来看实体的提取效果还不错,除了偶尔有错误分类外,还会发现小说的某些章节标题被单独提取出来了,并且分类为“ORGANIZATION”。

此外很显然相同含义的不同实体并没有被识别为同一实体,这点我们在3.2中就有提到,先来看一下具体例子。

如图所示,分别为“雪做的女孩”和“她”的关系网图,根据实体关系图我们可以判断很显然这个“她”就是“雪做的女孩”,而这两个实体之间甚至没有关系线,至于社群能否解决这一问题我们再后面的分析再谈。但是很显然,在知识图谱中,无法知道“她”就是“雪做的女孩”。

问题2:同对象不同名称单独作为实体

可以发现基本问题1和问题2本质上都属于实体混淆,graphRAG在提取实体时并没有合理的运用文本本身的结构(分章节)。理论上引入文本本身结构可以缓解这一问题,但与此同时过于注重结构也会导致小说中的伏笔无法被辨识出来,同样会让大模型无法真正理解故事。

5.2.2 关系与关系摘要

整体的关系分类在我看来还是很成功的,我们分别来看三个实体的关系图,“她”,“少女”,“他”。

这三个实体的关系图按顺序依次对应了三个故事的主要情节和出场人物,这个知识图谱是相对准确且具有内在逻辑的。

而“我”实体的关系图则和摘要相同,融合了三个故事。

接着具体看一下关系的摘要。

先举几个具体例子,以下为摘要具体内容,加粗的为实体,因为是无向图,所以无前后顺序之分。最后的数字为二者的关系权重。

"《八十天环游地球》是故事中人物在公园阅读的书籍之一。"1

"春天的坡道有情感联系,象征着希望和新生。"1

"爸爸小镇上出生、长大,对小镇有深厚的感情,但由于工作原因不能一直待在家里。" "爸爸与小镇有联系,他们曾讨论过离开小镇的话题,这影响了叙述者对小镇的看法。" "爸爸是小镇上的居民,与小镇的新年庆祝活动有联系。"3

"班主任在学生毕业时会回忆起自己的学生时代,并与学生分享自己的经历。"1

"图书馆是叙述者和'他'在高中时期就曾一起前往的地方,现在他们再次一同前往,形成时间上的联系。"1

"叙述者()担心自己会变成一个平凡而无趣的大人,这反映了他对成长的恐惧和无奈。"1

"晚上偷偷离家前往公园,表现出对这个地方的熟悉。" "'我'深夜来到公园,这个地点对'我'来说有着特别的意义,是'我'和'她'共有的空间。" "主角在公园里尝试给惊喜,公园是他们共享的世界的一部分。" "叙述者在公园中与女主角有着情感交流。" "叙述者最终回到公园,可能是他常去的地方,表现出对公园的偏爱。" "叙述者与女主角在公园的长椅上并肩坐着,公园成为他们情感交流的背景。"6

可以说关系的摘要很好的利用了大模型的语言理解能力,关系的权重也符合人类读者的直观感受,具体是如何实现的就在后面的代码部分再详细阐述。

很多关系并不是人类读者会提取的,但这也是大模型的优势,可以通过遍历进行更强的联想。关系摘要除了偶尔会有幻觉现象外实用性很强,对于后续社群的划分有很大的帮助。

5.2.3 社群结构与社群摘要

社群结构如下图所示。

社群摘要并没有直接保存在graphml文件中,最方便的方式是看./ragtest/output/20240723-143610/artifacts/create_final_community_reports.parquet文件。

我使用的这个vscode插件,可以直接查看parquet文件。

可视化的结果如下所示。

社群一共分了0,1,2(2为最“大”社群,即最高层级)三个层级,这里由于原码的prompt使用的是英文,而处理的文本是中文,所以社群摘要和社群标题大多数都是英文。这里我们每个层级挑选几个具体看看结果如何。

先从大层级2入手,为了便于读者阅读和理解,这里将英文翻译成中文展示。rank是指这个社群的重要程度。所以针对不同层级,我们选择rank大的和小的分别来看。

「同学 “意外损坏 ”宇宙的书 rank2
影响严重性评级较低,反映了事件的个人和情感性质,而非更广泛的社区影响。
社区围绕着一个学生(被称为 “同学”)不小心损坏了叙述者(被称为 “宇宙的书”)珍爱的一本书的事件展开。这一事件给叙述者造成了情感上的痛苦,因为他对这本书有着强烈的感情。关系和事件的影响是这个社区的核心焦点。」

「公园社区: 个人与集体经历的联系 rank7.5
由于公园是各种活动和互动的中心聚集地,会对社区的社会结构和情感景观产生重大影响,因此影响严重性评级较高。
公园社区是一个多层面的环境,是各种个人和集体体验的中心枢纽。公园是 “我”、“她 ”和 “叙述者 ”等个人互动和分享时刻的焦点。此外,公园还是 “雪屋计划 3 号 ”和 “俱乐部活动 ”等活动的场所,这也增加了公园的重要性。太阳 "的存在进一步丰富了社区的动态,为公园的宁静和时间的流逝提供了背景。」

「校内外 “我 ”与 “他 ”的复杂关系 rank7.5
由于主人公之间深厚的情感联系和共同经历可能会影响他们的学业和个人发展,因此影响严重性评级较高。
社区围绕着 “我”(叙述者)和 “他”(他)之间复杂的关系展开,这两个学生在学业和个人生活中游刃有余。他们的互动主要以学校环境为背景,图书馆和舞台等关键地点都扮演了重要角色。这段关系的特点是混合了竞争、合作和情感联系,两个人有着共同的目标和经历。」

「神秘的 “少女 ”世界和她的旅程 rank6.5
由于 “少女 ”丰富的叙事和象征性的互动可能会引起观众的共鸣和情感反应,因此影响严重程度评级为中等。
社区以神秘人物 “少女 ”为中心,她开始了一段充满象征性互动和体验的旅程。她与 “少年”、“蝴蝶 ”和 “小镇 ”等各种实体的关系构成了叙事的核心。少女 "被描绘成一个涉及音乐、自然和个人发现的故事中的关键人物,她的行为和经历是社区动态的主要焦点。」

具体来看我们可以发现这一层级所选择的对象关系也可能很简单,如第一个例子。此外还需要注意的一点是,因为prompt中选择community一词,可能会被大模型理解为对社区的影响,比如第二个例子对rank的解释。

最后一个例子对情节和主旨的出色总结也让人对社群摘要充满了信心。

问题3:rank的打分方式和描述存在漏洞

这部分在原码部分我们再详细研究一下,目前也还是先标记一下。

然后是层级1的例子。

「小圣诞与邻镇的联系 rank 3.5
影响严重性评分为3.5,因为小圣诞与邻镇的关系以及新开商场可能对社区产生一定的经济和文化影响。
本报告涉及的社区以小圣诞和邻镇为中心,小圣诞是一个与去年圣诞节购物活动有关的可爱小熊,而邻镇则是小圣诞的来源地,并且拥有一个新开的大型商场。社区的联系主要通过小圣诞与邻镇的关系以及与新开商场的潜在联系来体现。」

「下周文艺演出 - 学生表演社区 rank 3
该社区的IMPACT严重性评级为3.0,因为这是一个学生表演活动,可能对参与者和观众产生积极影响,但不太可能引起重大社会动荡或冲突。
下周文艺演出是一个即将发生的活动,涉及两个班级的学生表演节目。这个社区由'我们班'和'另一个班级'的学生组成,他们将共同参与表演。'我们班男孩'和'坐轮椅那个女孩'是两个关键的表演者,他们将一起表演钢琴节目。」

「秋千与少女的梦境 rank7.5
该社区的IMPACT评分较高,因为少女的情感表达和与秋千的互动可能对读者产生深刻的影响。
本文通过一系列人物和地点的描述,构建了一个以秋千和少女为中心的社区。秋千不仅是少女的娱乐场所,也是她情感表达的载体。少女与男孩、原野、石头等元素的互动,展现了她的内心世界和生活状态。社区中的每个成员都以不同的方式与秋千和少女产生联系,共同构成了一个充满情感和故事的社区。」

最后是层级0的例子。

「科技馆探访与情感联系 rank 3.5
由于该社区注重文化和情感体验,这可能对个人生活产生重大影响,因此影响严重程度评级为中等。
该社区围绕科技馆展开,科技馆是参观计划和讨论的中心地点。博物馆位于省城,与《小王子》一书的情感叙事相关联。个人与博物馆以及这本书之间的关系表明,这是一个有着共同兴趣和情感联系的社区。」

「学校社团和文化活动
由于活动的教育和文化意义、各利益相关方的参与以及对学生发展的潜在影响,影响严重 程度评级较高。
学校社区围绕着一位敬业的教师和一系列文化教育活动展开,包括《小王子》话剧演出、社会实践活动,以及对春节和高考等重大事件的期待。在这些活动中,教师发挥着核心作用,而学生则扮演着从参与者到领导者的各种角色,展现了社区的活力和协作性。」

可以看出社群摘要本身还是有比较强逻辑性的,可还是存在比较明显的幻觉,捏造事实的情况,还有就是社群摘要反复出现的“community(社区)”导致大模型对摘要内容产生误解,这也侧面说明高层级摘要对于回答的影响很大。

问题4:社群摘要有错误容易导致全局回答出现严重问题

整体来看生成的结果和过程,GraphRAG还有很多值得探索和研究的问题,下一部分就仔细来看看GraphRAG的内部代码以及对于可能存在的研究方向的一些思考。

  • 29
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值