
上一篇我们讲了GraphRAG的局部搜索。文章如下:
通过扩展特定实体的邻居和相关概念,可以对该实体进行推理。
这种场景旨在通过结合知识图谱中的结构化数据和输入文档中的非结构化数据,增强大型语言模型(LLM)在查询时的上下文,从而更好地回答涉及输入文档中特定实体的问题。这种方法将即用的图谱数据与非结构化文本结合,基于实体进行推理,利用知识图谱中的结构化数据和输入文档中的非结构化数据,以在查询时为LLM提供与查询相关的实体信息。
GraphRAG首先识别与用户输入语义相关的知识图谱中的实体集合。这些实体作为访问知识图谱的入口,帮助提取更多相关信息,如相关实体、关系、实体协变量和社区报告。此外,还从原始输入文档中提取与已识别实体相关联的相关文本块。然后,这些候选数据源将被优先排序和过滤,以适应预定义大小的单个上下文窗口,用于生成对用户查询的响应。
这篇文章介绍GraphRAG的另一个应用场景:全局搜索。
全局搜索:通过利用社区摘要,对整个语料库进行全面的推理分析。借助大型语言模型(LLM)生成的知识图谱来组织和整合信息,从而回答需要跨数据集聚合信息的复杂查询。这种方法不仅提升了信息检索的效率,还提高了回答问题的准确性和深度。
全局搜索方法使用LLM生成的社区报告集合作为上下文数据,以map-reduce方式生成响应。在map步骤中,社区报告被分割成预定义大小的文本块。每个文本块用于生成包含要点列表的中间响应,每个要点都有相应的数值评分,表示其重要性。在reduce步骤中,从中间响应中筛选出最重要的要点,并将它们聚合起来,作为生成最终响应的上下文。
下面介绍一下这个全局搜索案例:
全球搜索方法通过以地图减少的方式搜索所有 AI 生成的社区报告来生成答案。这是一种资源密集型方法,但对于需要从整体上理解数据集的问题,通常可以很好地回答问题(例如,本笔记本中提到的草药的最重要价值是什么?
import osimport pandas as pdimport tiktokenfrom graphrag.query.indexer_adapters import read_indexer_entities, read_indexer_reportsfrom graphrag.query.llm.oai.chat_openai import ChatOpenAIfrom graphrag.query.llm.oai.typing import OpenaiApiTypefrom graphrag.query.structured_search.global_search.community_context import (GlobalCommunityContext,)from graphrag.query.structured_search.global_search.search import GlobalSearch
接下来,进行LLM 设置:
api_key = os.environ["GRAPHRAG_API_KEY"
]llm_model = os.environ["GRAPHRAG_LLM_MODEL"]llm = ChatOpenAI(api_key=api_key,model=llm_model,api_type=OpenaiApiType.OpenAI, # OpenaiApiType.OpenAI or OpenaiApiType.AzureOpenAImax_retries=20,)token_encoder = tiktoken.get_encoding("cl100k_base")
将社区报告加载为全局搜索的上下文:
# parquet files generated from indexing pipelineINPUT_DIR = "./inputs/operation dulce"COMMUNITY_REPORT_TABLE = "create_final_community_reports"ENTITY_TABLE = "create_final_nodes"ENTITY_EMBEDDING_TABLE = "create_final_entities"# community level in the Leiden community hierarchy from which we will load the community reports# higher value means we use reports from more fine-grained communities (at the cost of higher computation cost)COMMUNITY_LEVEL = 2
entity_df = pd.read_parquet(f"{INPUT_DIR}/{ENTITY_TABLE}.parquet")report_df = pd.read_parquet(f"{INPUT_DIR}/{COMMUNITY_REPORT_TABLE}.parquet")entity_embedding_df = pd.read_parquet(f"{INPUT_DIR}/{ENTITY_EMBEDDING_TABLE}.parquet")reports = read_indexer_reports(report_df, entity_df, COMMUNITY_LEVEL)entities = read_indexer_entities(entity_df, entity_embedding_df, COMMUNITY_LEVEL)print(f"Report records: {len(report_df)}")report_df.head()
基于社区报告构建全局搜索:
context_builder = GlobalCommunityContext(community_reports=reports,entities=entities, # default to None if you don't want to use community weights for rankingtoken_encoder=token_encoder,)
执行全局搜索:
context_builder_params = {"use_community_summary": False, # False means using full community reports. True means using community short summaries."shuffle_data": True,"include_community_rank": True,"min_community_rank": 0,"community_rank_name": "rank","include_community_weight": True,"community_weight_name": "occurrence weight","normalize_community_weight": True,"max_tokens": 12_000, # change this based on the token limit you have on your model (if you are using a model with 8k limit, a good setting could be 5000)"context_name": "Reports",}map_llm_params = {"max_tokens": 1000,"temperature": 0.0,"response_format": {"type": "json_object"},}reduce_llm_params = {"max_tokens": 2000, # change this based on the token limit you have on your model (if you are using a model with 8k limit, a good setting could be 1000-1500)"temperature": 0.0,}search_engine = GlobalSearch(llm=llm,context_builder=context_builder,token_encoder=token_encoder,max_data_tokens=12_000, # change this based on the token limit you have on your model (if you are using a model with 8k limit, a good setting could be 5000)map_llm_params=map_llm_params,reduce_llm_params=reduce_llm_params,allow_general_knowledge=False, # set this to True will add instruction to encourage the LLM to incorporate general knowledge in the response, which may increase hallucinations, but could be useful in some use cases.json_mode=True, # set this to False if your LLM model does not support JSON mode.context_builder_params=context_builder_params,concurrent_coroutines=32,response_type="multiple paragraphs", # free form text describing the response type and format, can be anything, e.g. prioritized list, single paragraph, multiple paragraphs, multiple-page report)result = await search_engine.asearch("What is the major conflict in this story and who are the protagonist and antagonist?")print(result.response)# inspect the data used to build the context for the LLM responsesresult.context_data["reports"]# inspect number of LLM calls and tokensprint(f"LLM calls: {result.llm_calls}. LLM tokens: {result.prompt_tokens}")
通过2个案例局部搜索和全局搜索,可以知道GraphRAG 的核心由两个主要图谱构成:一个是文档图谱,另一个是文档内部的实体关系图谱。文档图谱表示系统输入的文档,这些文档可以是CSV中的单独行或独立的.txt文件。文档内部的实体关系图谱则包含以下要素:
文档(Document):表示系统输入的文档,可以是CSV文件中的单独行或单独的.txt文件。
文本单元(TextUnit):表示待分析的文本块。这些块的大小、重叠以及是否遵守任何数据边界都可以进行配置。
实体(Entity):表示从文本单元中提取的实体,如人、地点、事件或您提供的其他实体模型。
关系(Relationship):表示两个实体之间的关系。
协变量(Covariate):表示提取的声明信息,其中包含可能有时间限制的关于实体的陈述。
社区报告(Community Report):表示一旦生成实体,会对它们执行层次化的社区检测,并为这个层次结构中的每个社区生成报告。
节点(Node):包含已嵌入和聚类的实体和文档的渲染图视图的布局信息。
通过这些元素,GraphRAG 能够构建一个详尽的文档和实体关系图谱,帮助更好地组织和分析数据,从而增强大型语言模型的推理和回答能力
GraphRAG的索引构建过程如下:
GraphRAG索引构建过程将文本文档转换为GraphRAG知识模型,包含以下几个主要阶段:
文本单元切分(Compose TextUnits):
输入文档被转换为文本单元,这些文本单元用于图提取技术,并作为提取知识项的源引用。
图谱抽取(Graph Extraction):
实体&关系抽取:识别文本中的实体和关系。
实体&关系总结:通过要求LLM提供一个简短的总结,将实体及关系列表总结成一个单一描述。
实体消歧:确保每个实体在不同上下文中唯一。
声明抽取:提取有关实体的陈述。
分析每个文本单元,提取实体、关系和声明。具体步骤包括:
图谱增强(Graph Augmentation):
社区检测:使用Leiden算法生成实体社区的层次结构。
图嵌入:使用Node2Vec算法生成向量表示,提供额外的向量空间用于搜索相关概念。
通过社区检测和图嵌入增强图谱,以理解实体的社区结构。具体步骤包括:
社区摘要(Community Summarization):
生成社区报告:使用LLM为每个社区生成摘要。
总结社区报告:通过LLM总结社区报告,供简写使用。
社区嵌入:生成社区报告、社区报告摘要和社区报告标题的文本嵌入,生成社区的向量表示。
为每个社区生成报告,提供对图的高层次理解。具体步骤包括:
文档处理(Document Processing):
链接到文本单元:将每个文档与创建的文本单元关联起来。
文档嵌入:使用文档切片的平均嵌入生成文档的向量表示,理解文档之间的隐含关系,并帮助生成文档的网络表示。
表示文档并形成文档图。具体步骤包括:
通过这些步骤,GraphRAG能够构建一个详尽的文档和实体关系图谱,增强大型语言模型的推理和回答能力。
长按下图前往本公众号领取更多学习资料:





