手把手教你构建基于知识图谱的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应用中的两种高级检索模式:你还只知道向量检索吗?]),用来适应更多样的应用场景,具体效果可以自行测试。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值