你要的增量更新来了:微软GraphRAG 0.4.0
微软GraphRAG自发布以来,引起了很大关注(目前18.7k star),但是一些功能却迟迟没有,比如增量更新。今天微软GraphRAG发布v0.4.0,3小时前,还是新鲜热乎的,带来两项重要更新:
-
添加增量索引
-
添加了 DRIFT 图推理查询模块
增量更新索引逻辑
增量更新逻辑代码在这:https://www.microsoft.com/en-us/research/blog/introducing-drift-search-combining-global-and-local-search-methods-to-improve-quality-and-efficiency/
获取数据变化:get_delta_docs函数用于比较输入数据集和存储中的最终文档,识别出新增和删除的文档。这是增量更新的核心部分,只有变化的部分会被进一步处理。
async def get_delta_docs(
input_dataset: pd.DataFrame, storage: PipelineStorage
) -> InputDelta:
"""Get the delta between the input dataset and the final documents.
Parameters
----------
input_dataset : pd.DataFrame
The input dataset.
storage : PipelineStorage
The Pipeline storage.
Returns
-------
InputDelta
The input delta. With new inputs and deleted inputs.
"""
final_docs = await _load_table_from_storage(
"create_final_documents.parquet", storage
)
# Select distinct title from final docs and from dataset
previous_docs: list[str] = final_docs["title"].unique().tolist()
dataset_docs: list[str] = input_dataset["title"].unique().tolist()
# Get the new documents (using loc to ensure DataFrame)
new_docs = input_dataset.loc[~input_dataset["title"].isin(previous_docs)]
# Get the deleted documents (again using loc to ensure DataFrame)
deleted_docs = final_docs.loc[~final_docs["title"].isin(dataset_docs)]
return InputDelta(new_docs, deleted_docs)
更新数据框架输出:update_dataframe_outputs函数负责更新各种数据框架,包括实体、关系、文本单元、协变量、节点和社区。这个函数会调用其他函数来处理这些更新。
async def update_dataframe_outputs(
dataframe_dict: dict[str, pd.DataFrame],
storage: PipelineStorage,
update_storage: PipelineStorage,
config: PipelineConfig,
cache: PipelineCache,
callbacks: VerbCallbacks,
progress_reporter: ProgressReporter,
) -> None:
"""Update the mergeable outputs.
Parameters
----------
dataframe_dict : dict[str, pd.DataFrame]
The dictionary of dataframes.
storage : PipelineStorage
The storage used to store the dataframes.
"""
progress_reporter.info("Updating Final Documents")
final_documents_df = await _concat_dataframes(
"create_final_documents", dataframe_dict, storage, update_storage
)
# Update entities and merge them
progress_reporter.info("Updating Final Entities")
merged_entities_df, entity_id_mapping = await _update_entities(
dataframe_dict, storage, update_storage, config, cache, callbacks
)
# Update relationships with the entities id mapping
progress_reporter.info("Updating Final Relationships")
merged_relationships_df = await _update_relationships(
dataframe_dict, storage, update_storage
)
DRIFT图推理查询逻辑
DRIFT搜索原理:https://www.microsoft.com/en-us/research/blog/introducing-drift-search-combining-global-and-local-search-methods-to-improve-quality-and-efficiency/
-
在全面性方面,DRIFT 搜索的表现比local search好 78%。
-
在多样性方面,DRIFT 搜索的表现比local search好 81%
DRIFT搜索层级的全景,突出了DRIFT搜索过程的三个核心阶段。A(预处理):DRIFT将用户查询与最语义相关的前K个社区报告进行比较,生成一个广泛的初始答案和后续问题,以引导进一步的探索。B(后续):DRIFT使用局部搜索来细化查询,产生额外的中间答案和后续问题,增强了具体性,引导引擎朝向内容丰富的信息。图中每个节点上的一个符号显示了算法继续查询扩展步骤的信心。C(输出层级):最终输出是一个按相关性排名的问题和答案的层级结构,反映了全局洞察和局部细化的平衡混合,使结果具有适应性和可理解性。
-
预处理:当用户提交查询时,DRIFT会将其与最语义相关的前K个社区报告进行比较。这会产生一个初始答案以及几个后续问题,这些后续问题作为全局搜索的轻量级版本。为了实现这一点,我们使用假设文档嵌入(HyDE)扩展查询,以提高敏感性(召回率),嵌入查询,将查询与所有社区报告进行比对,选择前K个,然后使用这前K个尝试回答查询。目标是利用高级抽象来指导进一步的探索。
-
后续:在预处理就绪后,DRIFT使用局部搜索变体执行每个后续问题。这会产生额外的中间答案和后续问题,形成一个持续细化的循环,直到搜索引擎满足其终止条件,目前配置为两次迭代(进一步的研究将研究奖励函数以指导终止)。这个阶段代表了全局信息引导的查询细化。使用全局数据结构,即使初始查询偏离索引角色,DRIFT也能导航到知识图中的具体、相关信息。这个后续过程使DRIFT能够根据新出现的信息调整其方法。
-
输出层级:最终输出是按与原始查询的相关性排名的问题和答案的层级结构。这个层级结构可以定制以满足特定用户需求。在基准测试期间,一个简单的映射-归约方法聚合了所有中间答案,每个答案的权重相等。
来源 | PaperAgent