原文 技术博客
GraphRAG 通过从非结构化文本构建知识图谱并将其用于检索,增强了传统的 RAG 系统。与仅依赖向量相似度的标准 RAG 方法不同,GraphRAG 提取实体和关系,执行社区检测,并生成不同层级的报告。这种结构化方法为语言模型提供了更多上下文和关系信息,从而产生更全面、更准确的响应。
实体提取 (Entity Extraction)
从非结构化或半结构化数据(如文本、表格)中识别并抽取出具有特定语义的独立对象(如人名、地点、机构、时间等)。
图谱构建 (Knowledge Graph Construction)
将提取的实体和它们之间的关系组织成结构化网络的过程,形成“节点-边-属性”三元组(如**<人物, 就职于, 公司>
**)。
社区检测 (Community Detection)
在图结构中自动发现紧密连接的子图(社区),使社区内部连接密集,社区之间连接稀疏。
社区报告 (Community Reporting)
对检测到的社区进行统计、分析和可视化,描述其规模、关键节点、语义特征及与其他社区的关系。
向量化 (Embedding)
将知识图谱中的实体和关系映射为低维数值向量(如用[0.2, -0.5, 1.3]表示“北京”),以便机器学习模型处理语义和相似性计算。
pip install graphrag
graphrag init --root ./myproject
上述指令将创建下面3个配置文件:
settings.yaml
:基础配置文件.env
:环境配置文件prompts/
:提示模板可以在.env
文件中配置大模型的API密钥
对于 Azure OpenAI 用户,您还需要**settings.yaml
**使用 Azure 详细信息更新文件:
models:
default_chat_model:
type: azure_openai_chat
api_base: https://<instance>.openai.azure.com
api_version: 2024-02-15-preview
deployment_name: <model_deployment_name>
default_embedding_model:
type: azure_openai_embedding
api_base: https://<instance>.openai.azure.com
api_version: 2024-02-15-preview
deployment_name: <embedding_model_deployment_name>
将自己的数据放在输入目录中:
mkdir -p ./myproject/input
GraphRAG 支持以下输入格式:
.txt
)text
**带有列的 CSV 文件text
**带有字段的 JSON 文件graphrag index --root ./myproject
这个过程:
索引完成后,使用以下几种搜索方法之一查询数据:
graphrag query --root ./myproject --method global --query "What are the main themes in this dataset?"
#全局搜索
graphrag query --method global --query "What are the primary themes?"
#本地搜索
graphrag query --method local --query "Tell me about Entity X and its relationships"
#DRIFT搜索
graphrag query --method drift --query "What is the significance of Entity X in the broader context?"
#基本搜索
graphrag query --method basic --query "Find information about X"
实体和关系提取是 GraphRAG 索引流程中的关键组件,它将纯文本转换为结构化知识图谱。此过程从文本文档中识别关键概念(实体)并确定它们之间的关系,从而实现比传统 RAG 系统更复杂的信息检索和推理能力。
GraphRAG 使用自然语言处理技术从文本单元(文档块)中提取实体和关系。这构成了知识图谱的基础,并支持高级查询功能。
主要代码文件:
graphrag/index/workflows/extract_graph_nlp.py
graphrag/index/operations/build_noun_graph/build_noun_graph.py
GraphRAG 提供了多个提取器来从文本中识别实体,每个提取器在准确性、语言支持和性能方面都有不同的权衡。
#graphrag/index/operations/build_noun_graph/build_noun_graph.py
async def _extract_nodes(
text_unit_df: pd.DataFrame,
text_analyzer: BaseNounPhraseExtractor,
num_threads: int = 4,
cache: PipelineCache | None = None,
) -> pd.DataFrame:
名词短语提取
可用的提取器有:
graphrag/index/operations/build_noun_graph/np_extractors/syntactic_parsing_extractor.py
graphrag/index/operations/build_noun_graph/np_extractors/cfg_extractor.py
graphrag/index/operations/build_noun_graph/np_extractors/regex_extractor.py
实体提取过程遵循以下步骤:
graphrag/index/operations/build_noun_graph/build_noun_graph.py
实体之间的关系是根据同一文本单元内的共现情况来识别的。具体流程如下:
#graphrag/index/operations/build_noun_graph/build_noun_graph.py
def _extract_edges(
nodes_df: pd.DataFrame,
normalize_edge_weights: bool = True,
) -> pd.DataFrame:
使用 PMI 进行权重归一化
PMI 权重计算通过将观察到的共现频率与实体独立出现时的预期频率进行比较来突出显示重要的关系:
PMI(x,y) = log2(p(x,y) / (p(x) * p(y)))
其中:
这种规范化对于区分有意义的关系和巧合的共现尤为重要。
实体和关系提取通过**ExtractGraphNLPConfig
**GraphRAG 配置中的部分进行配置:
名称 | 描述 | 默认 |
---|---|---|
normalize_edge_weights |
是否使用 PMI 作为边权重 | True |
concurrent_requests |
提取线程数 | 4 |
text_analyzer.extractor_type |
提取器的类型:语法、cfg 或正则表达式 | 'syntactic' |
text_analyzer.model_name |
SpaCy 模型名称 | 'en_core_web_sm' |
text_analyzer.max_word_length |
最大字长 | 15 |
text_analyzer.include_named_entities |
包括命名实体 | True |
text_analyzer.exclude_nouns |
要排除的停用词 | (常见停用词列表) |
text_analyzer.exclude_entity_tags |
要排除的实体类型 | [] |
text_analyzer.exclude_pos_tags |
要排除的 POS 标签 | ['DET', 'PUNCT', 'ADP'] |
实体和关系提取的输出由两个数据框组成:
实体数据框:
title
:实体文本(名词短语)frequency
:实体出现的频率text_unit_ids
:实体出现的文本单元的 IDtype
:实体类型(默认:“名词短语”)description
:实体描述(初始为空)关系数据框:
source
:源实体target
:目标实体weight
:关系强度(共现或 PMI)text_unit_ids
:出现关系的文本单元的 IDdescription
:关系描述(初始为空)GraphRAG 中的社群检测功能将知识图谱划分为相关实体的层次化集群。这些社群构成了全局搜索功能的基础,并为检索和查询解答提供了结构化的上下文。
代码文件位置:
该**create_communities
**函数实现了社区检测工作流程,以实体和关系表作为输入,并生成具有层次结构的社区表。
graphrag/index/workflows/create_communities.py
参数配置
社区检测过程可以通过几个参数进行定制:
范围 | 描述 | 默认 |
---|---|---|
max_cluster_size |
集群的最大大小(实体数量) | 在设置中配置 |
use_lcc |
是否仅使用最大的连通分量 | 在设置中配置 |
seed |
随机种子用于重复性 | 无(系统定义) |
这些参数可以在配置文件中设置,如测试装置所示:
#tests/fixtures/text/config.json
"create_communities": {
"row_range": [1, 30],
"max_runtime": 30,
"expected_artifacts": ["communities.parquet"]
}
社区检测算法
实际的社区检测由函数执行**cluster_graph
**。该函数根据网络连接模式将图划分为多个聚类。
代码文件位置:
graphrag/index/workflows/create_communities.py
聚类受以下配置参数的影响:
社区结构
GraphRAG 中的社区采用分层结构组织,允许多层次地组织知识。
每个社区都具有定义其与其他社区关系的属性:
其具体结构模型参数如下:
colum | desc |
---|---|
id |
唯一标识符 (UUID) |
human_readable_id |
与社区号码匹配的数字标识符 |
title |
人类可读的标题(例如“社区 1”) |
level |
层级(0 = 顶部) |
parent |
家长社区ID |
children |
子社区 ID |
entity_ids |
此社区中的实体 ID 列表 |
relationship_ids |
两个端点都属于此社区的关系 ID 列表 |
text_unit_ids |
与此社区关联的文本单元 ID 列表 |
period |
社区创建的 ISO 日期(用于增量更新) |
size |
社区实体数量 |
存储系统负责在整个索引管道中持久保存所有数据工件,并存储搜索操作中使用的向量嵌入。
存储系统负责在整个索引管道中持久保存所有数据工件,并存储搜索操作中使用的向量嵌入。
GraphRAG 采用双层存储架构,包括:
代码文件位置:
graphrag/utils/storage.py
graphrag/index/update/incremental_index.py
graphrag/vector_stores/azure_ai_search.py
GraphRAG 查询系统提供先进的搜索功能,用于从索引过程中创建的知识图谱中检索和生成答案。与传统的基于向量的 RAG 方法不同,GraphRAG 提供了多种针对不同类型问题优化的搜索策略,充分利用了知识图谱、实体关系和社区层级的丰富结构。
代码文件位置:
#文件夹:graphrag/query/structured_search/
graphrag/query/structured_search/base.py
graphrag/query/factory.py
分为下面四种检索方法:
搜索方法 | 类名 | 目的 | 适合场景 |
---|---|---|---|
全局搜索 | GlobalSearch |
利用社区报告提供整体理解 | 关于主题、主题和模式的高级问题 |
本地搜索 | LocalSearch |
专注于以实体为中心的探索 | 关于具体实体及其关系的详细问题 |
DRIFT 搜索 | DRIFTSearch |
灵活遍历的动态推理 | 复杂的问题需要广泛的背景和具体的细节 |
基本搜索 | BasicSearch |
传统向量相似性搜索 | 不需要图形上下文时的简单事实问题 |
全局搜索旨在解决需要了解整体数据集的广泛、高层次问题。它利用索引过程中生成的社区报告,其中包含不同主题集群的摘要。
全局搜索采用 map-reduce 方法:
该实现支持可选的动态社区选择,它使用 LLM 来识别给定查询最相关的社区报告,而不是使用固定社区级别的所有报告。
本地搜索专注于实体相关的问题,通过检查与查询主题相关的实体、关系和文本单元来解决问题。它旨在提供有关特定实体及其联系的详细答案。
本地搜索过程包括:
本地搜索对于有关实体、其属性以及它们与知识图谱中其他实体的关系的特定问题最有效。
DRIFT(动态推理与灵活遍历)搜索结合了全局搜索和局部搜索的优势,能够为复杂问题提供全面的答案。它采用一种新颖的方法来动态生成和跟踪问题,从而探索知识图谱。
DRIFT Search 主要分为三个阶段:
这种方法创建了知识图谱的动态、迭代探索,允许系统在保持整体背景的同时“深入”到特定领域。
基本搜索提供类似于标准 RAG 系统的传统基于向量的检索方法。它比其他方法更简单,并且没有利用完整的知识图谱结构。
基本搜索流程:
基本搜索对于比较简单的问题或当您想要绕过知识图结构并执行直接文本检索时很有用。
API接口
response, context_data = await global_search(
config=config,
entities=entities,
communities=communities,
community_reports=community_reports,
community_level=2,
dynamic_community_selection=True,
response_type="multiple paragraphs",
query="What are the main themes in the dataset?"
)
# Streaming API example
async for chunk in global_search_streaming(
config=config,
entities=entities,
communities=communities,
community_reports=community_reports,
community_level=2,
dynamic_community_selection=True,
response_type="multiple paragraphs",
query="What are the main themes in the dataset?"
):
print(chunk, end="")
CLI界面
# Global Search
graphrag query --root ./project --method global --query "What are the main themes in the dataset?"
# Local Search with specific community level
graphrag query --root ./project --method local --community-level 2 --query "Tell me about Entity X"
# DRIFT Search with streaming
graphrag query --root ./project --method drift --streaming --query "What insights can be derived?"
# Basic Search
graphrag query --root ./project --method basic --query "What does the text say about topic Y?"