手把手教你构建基于知识图谱的GraphRAG之非结构化数据篇【LlamaIndex+Neo4j】

上篇简单介绍了构建GraphRAG的动机与架构。GraphRAG的基础架构源自基于向量的经典RAG的转换:

我们已经演示了如何把传统关系型数据库中的结构化知识转为知识图谱并用于RAG查询。本篇我们将关注非结构化数据,以一个简单的自然语言文本为例,了解如何借助LLM的开发框架来构建GraphRAG应用。

生成基于Graph的知识图谱

构建一个非结构化数据的GraphRAG应用,首要任务是把非结构化数据转换成以图结构表示的知识图谱,并存储到GraphDB如Neo4j,用来提供后续检索与生成的基础。从非结构化文本到知识图谱,借助LLM是一种常见的也是最高效的方法:**利用LLM强大的语义理解与推理能力,从非结构化文本中抽取大量的类似实体-关系-实体的三元组,并借助必要的接口(如GraphDB支持的查询语言)导入到GraphDB中创建对应的实体、关系与属性,形成知识图谱。**如下图:

这里的核心是基于LLM而实现的Extractor,即Graph结构的抽取组件。在不同的框架中有不同的组件实现,这里我们以LlamaIndex框架为例,其实现的核心组件为LLMPathExtractor,一般用最简单的SimpleLLMPathExtractor进行代码实现即可(如果你熟悉LangChain,可以研究类似的LLMGraphTransformer组件):

_为了更好的测试效果,我们用LLM生成了一个架空世界的城市故事作为构建知识图谱的非结构化数据来源。‍_‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

llm = OpenAI(model="gpt-4o")  
embed_model=OpenAIEmbedding(model_name="text-embedding-3-small"),  
  
#加载数据  
documents = SimpleDirectoryReader(input_files=['./dreamcity.txt']).load_data()  
  
#图数据库  
from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore  
from llama_index.core import PropertyGraphIndex  
from llama_index.core.indices.property_graph import SimpleLLMPathExtractor  
  
#neo4j存储  
graph_store = Neo4jPropertyGraphStore(  
    username="neo4j",  
    password="Unycp123!!",  
    url="bolt://localhost:7687",  
)  
  
#知识抽取的提示词  
prompt = '''  
下面提供了一些文本。根据文本,提取最多 {max_knowledge_triplets} 个知识三元组,形式为(实体,关系,实体或属性)。避免使用停用词。仅输出三元组,不要有多余解释和说明。  
---------------------  
示例:  
文本:Alice是Bob的母亲。  
三元组:Alice,母亲,Bob  
文本:Philz是1982年在伯克利创立的咖啡店。  
三元组:  
Philz,是,咖啡店  
Philz,创立于,伯克利  
Philz,创立于,1982年  
--------------------  
文本:{text}  
三元组:  
'''  
  
#抽取结果的解析  
def parse_fn(response_str: str) -> List[Tuple[str, str, str]]:  
    lines = response_str.split("\n")  
    triples = [line.split(",") for line in lines]  
    return triples  
  
#定义知识抽取器  
kg_extractor = SimpleLLMPathExtractor(  
    llm=llm,  
    extract_prompt=prompt,  
    max_paths_per_chunk=50,  
    parse_fn=parse_fn,  
)  
  
#抽取创建图知识库索引(本地化做持久,避免反复抽取)  
if not os.path.exists(f"./index_storage"):  
    index = PropertyGraphIndex.from_documents(  
        documents,  
        embed_model=embed_model,  
        kg_extractors=[kg_extractor],  
        property_graph_store=graph_store,  
        show_progress=True,  
    )  
    index.storage_context.persist("./index_storage")  
else:  
  
    print('Loading index...\n')  
    storage_context = StorageContext.from_defaults(persist_dir="./index_storage",property_graph_store=graph_store)  
    index = load_index_from_storage(storage_context=storage_context)

代码中已经包含了较为详细的注释说明,这里可以注意的是:

  • 抽取过程最重要的工具是LLM与对应的提示词,这里用了少量示例提示模式(few-shot prompt),你可以根据不同语言的需要做优化

  • 借助于PropertyGraphIndex组件,可以快速的基于文档与抽取器生成知识图谱并存储到图数据库中(通过Property_graph_store指定)

  • 在生成知识图谱时,需要指定嵌入模型,这是为了在生成Graph的节点时,对节点的内容或者名称生成向量,用于后续的向量检索

现在,运行这段代码,完成后登录到Neo4j的后端控制台,可以看到基于该文本的知识图谱已经生成。原始的文本将被分割成多个chunk,并用来创建label为"chunk"的多个知识图谱节点,这个节点的text属性用来存放原始的文本,同时embedding属性用来存放生成向量。原始文本的chunk节点和其他抽取生成的节点关系是’MENTIONS’(提到):‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

查看其详细的关联关系,可以看到整个知识图谱的构建情况:

现在你可以使用Cyther语言查看抽取的实体节点及其关系,可以看到抽取工作完成的还不错。如果深入观察,可以发现实体节点也对名字生成了向量(比如下面的亚特兰斯),这也是为后续检索做准备:‍‍‍‍

基于Graph知识图谱的检索与生成

现在我们已经把非结构化的文本转化为基于Graph的知识图谱进行存储,并构建了必要的索引。那么如何基于这个知识图谱来完成检索与生成呢这里有三种常见的知识图谱检索方法:‍‍‍‍‍‍‍‍‍‍

  • Text-to-Cypher(或其他Graph查询语言)。这在上一篇介绍结构化数据的知识图谱检索时已经介绍,即把自然语言用LLM转化为GraphDB能够理解的查询语言(比如Neo4j的Cypher)后进行检索。‍‍

  • Vector Search。这需要Graph数据库有对应的向量检索技术支持,即在创建Graph时能够对节点或关系做embedding(作为属性);在检索时再根据向量检索相似的节点与关系作为上下文。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

  • Keywords Search。借助LLM从自然语言的输入提取关键词或者同义词,然后使用提取的关键词借助GraphDB的能力检索出关联的节点与关系作为后续生成的上下文。

我们延续上面创建的知识图谱,基于LlamaIndex框架构建RAG检索与生成阶段的程序。这里先创建一个基于关键词的检索器,注意这里的prompt,是用来抽取输入中的关键词:‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

...  
def parse_fn(output: str) -> list[str]:  
    matches = output.strip().split("^")  
    keywords=[x.strip().capitalize() for x in matches if x.strip()]  
    print(keywords)  
    return keywords  
  
prompt = (  
        "给定一些初始查询,提取最多 {max_keywords} 个相关关键词,考虑大小写、复数形式、常见表达等。\n"  
        "用 '^' 符号分隔所有同义词/关键词:'关键词1^关键词2^...'\n"  
        "注意,结果应为一行,用 '^' 符号分隔。"  
        "----\n"  
        "查询: {query_str}\n"  
        "----\n"  
        "关键词: "  
    )  
  
synonym_retriever = LLMSynonymRetriever(  
    index.property_graph_store,  
    llm=llm,  
    include_text=False,  
    output_parsing_fn=parse_fn,  
    max_keywords=10,  
    synonym_prompt=prompt,  
    path_depth=1,  
)

检索器的参数通常包括使用的大模型、提取关键词的提示词、最大提取的关键词数量、检索的路径深度等。需要注意的是include_text参数,由于节点与关系都是从自然语言文本中提取,该参数代表在检索到相关的节点与关系后,是否同时将其原始的文本(也就是关联的chunk节点文本)包含进来作为上下文。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

再创建一个向量的检索器,注意向量检索器需要指定的是嵌入模型而非大模型,因此也无需指定提示词参数:‍‍‍‍‍‍‍‍

...  
vector_retriever = VectorContextRetriever(  
    index.property_graph_store,  
    embed_model=embed_model,  
    include_text=False,  
    similarity_top_k=2,  
    path_depth=1,  
)  

在LlamaIndex中,可以将创建的两种类型检索器作为子检索器进行融合检索,从而形成更加丰富的上下文。借助PGRetriever这个组件即可实现:

......  
retriever = PGRetriever(sub_retrievers=[synonym_retriever,vector_retriever])  
retrieve_nodes = retriever.retrieve("梅林发现的东西最后运用到哪里了?")  
for node in retrieve_nodes:  
    print(node.text)

现在你可以首先对这个检索器的效果进行测试与观察,可以看到知识图谱检索器的检索结果是一些相关的"三元组",即节点-关系-节点;如果指定了include_text,那么还会同时带出生成这些三元组的原始文本:‍‍‍‍‍‍‍

你可以直接基于上述检索器创建查询引擎(类似于Langchain的Chain),即可用来生成查询响应:‍‍‍‍‍‍‍‍‍‍

...  
query_engine = index.as_query_engine(  
    sub_retrievers=[synonym_retriever,vector_retriever]  
)  
  
#查询  
response = query_engine.query("梅林发现的东西最后运用到哪里了?")  
print(response)

观察后台的LLM调用跟踪信息,可以看到输入的完整上下文,以验证检索与生成过程的正确性:‍‍‍‍‍‍‍‍‍‍‍‍

以上就是一个基于非结构化文本的GraphRAG的构建过程。借助于如今的大模型,可以更加快速的抽取非结构化文本中的实体与关系以生成知识图谱,并进而结合向量、关键词等技术进行检索与生成,这对于一些涉及复杂实体间关系理解的查询可以很好的提升生成质量并减少幻觉。

在实际应用中,基于Graph的Index与检索技术也可以结合传统向量检索以实现融合检索(一文说清大模型RAG应用中的两种高级检索模式:你还只知道向量检索吗?),用来适应更多样的应用场景,具体效果可以自行测试。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

2024最新全套大模型学习资料:大模型学习成长路线、书籍&学习文档、视频教程、项目实战、面试题汇总等,免费分享~

有需要的同学可以通过【微信扫描下方二维码】,即可免费领取!!!

一、大模型学习成长路线

学习新技能,方向至关重要。 正确的学习路线图可以为你节省时间,少走弯路;方向不对,努力白费

这里,我们为新手和想要进一步提升的专业人士准备了一份详细的学习成长路线图和规划。可以说是最科学最系统的学习成长路线。

二、大模型书籍&学习文档

书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。(书籍含电子版PDF)

在这里插入图片描述

在这里插入图片描述

三、大模型视频教程

对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识

在这里插入图片描述

四、大模型实战项目

学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

在这里插入图片描述

五、大模型面试题汇总

面试,不仅是技术的较量,更需要充分的准备。在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

在这里插入图片描述

上述的资料已经全部打包好,有需要这份全套的大模型学习资料的同学,可以通过【微信扫描下方二维码】,免费领取!!!

机会总是留给有准备的人。 如果你需要学习大模型,那么请不要犹豫,立刻行动起来!早掌握,早享受。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值