首页 > 数据库 >更强的RAG:向量数据库和知识图谱的结合

更强的RAG:向量数据库和知识图谱的结合

时间:2024-10-10 19:33:21浏览次数:1  
标签:RAG index 图谱 数据库 graph query import self 向量

传统 RAG 的局限性

经典的 RAG 架构以向量数据库(VectorDB)为核心来检索语义相似性上下文,让大语言模型(LLM)不需要重新训练就能够获取最新的知识,其工作流如下图所示:

image-20240929145459119

这一架构目前广泛应用于各类 AI 业务场景中,例如问答机器人、智能客服、私域知识库检索等等。虽然 RAG 通过知识增强一定程度上缓解了 LLM 幻觉问题,但是依然面临准确度不高的问题,它受限于信息检索流程固有的限制(比如信息检索相关性、搜索算法效率、Embedding模型)以及大量对 LLM 能力依赖,使得在生成结果的过程中有了更多的不确定性。

下图来自 RAG 领域一篇著名的论文:《Seven Failure Points When Engineering a Retrieval Augmented Generation System》 ,它总结了在使用 RAG 架构时经常会遇到的一些问题(红框部分,原作者称之为7个失败点)。

它们包括:

  • 内容缺失(Missing Content),用户想要的答案并不在知识库中,LLM会给出无意义的回答。
  • 缺失排名靠前的文档(Missed Top Ranked),受限于文本切分方式、大小、嵌入模型等影响,从向量数据库中检索出来的 top-k 不一定是最精确的答案。
  • 不在上下文中(Not in Context),和上一条类似,经过各种处理后最终取出来的上下文质量较低。
  • 格式错误(Wrong Format),检索出来的结果没有特定格式,而 LLM 没有很好地对其识别分析。
  • 未提取(Not Extracted),Prompt 包含大量无关信息影响了 LLM 判断,即上下文包含很多噪音。
  • 答案不完整(Incomplete),生成的答案不够完整。
  • 不正确的差异(Incorrect Speciticity),答案在响应中返回,但不够具体或过于具体,无法满足用户的需求。

以上问题目前都有一些优化方法来提升回答准确度,但依然离我们的预期有差距。

因此除了基于语义匹配文本块之外,业内也探索新的数据检索形式,比如在语义之上关注数据之间的关联性。这种关联性区别于关系模型中的逻辑性强依赖,而是带有一定的语义关联。比如人和手机是两个独立的实体,在向量数据库中的相似性一定非常差,但是结合实际生活场景,人和手机的关系是非常密切的,假如我搜索一个人的信息,我大可能性也关心他的周边,例如用什么型号的手机、喜欢拍照还是玩游戏等等。

基于这样的关系模型,从知识库检索出来的上下文在某些场景中可能更有效,例如“公司里面喜欢使用手机拍照的人有哪些”。

用知识图谱来呈现数据关系

为了有效地描述知识库中的抽象数据关系,引入了知识图谱的概念,它不再使用二维表格来组织数据,而是用图结构来描述关系,这里面的关系没有固定的范式约束,类似下面这种人物关系图:

![](/i/l/?n=24&i=blog/614524/202410/614524-20241010193535967-5879819.png)

上图中有最重要的三个元素:对象(人物)、属性(身份)、关系,对于存储这样的数据有专门的数据库产品来支持,即图数据库。

图数据库(GraphDB)

图数据库是属于 NoSQL 的一种,它有着较为灵活的 schema 定义,可以简单高效表达真实世界中任意的关联关系。图数据库中的主要概念有:

  • 实体(Entity),也称之为顶点或节点,图结构中的对象
  • 边(Edge),连接两个实体的一条路径,即实体之间的关系
  • 属性(Property),用来具体描述实体或边的特征

以上概念可对应到前面的人物关系图。

具体到 schema 定义和数据操作层面,以流行的图数据库 NebulaGraph 为例:

# 创建图空间
CREATE SPACE IF NOT EXISTS test(vid_type=FIXED_STRING(256), partition_num=1, replica_factor=1);
USE test;

# 创建节点和边
CREATE TAG IF NOT EXISTS entity(name string);
CREATE EDGE IF NOT EXISTS relationship(relationship string);
CREATE TAG INDEX IF NOT EXISTS entity_index ON entity(name(256));

# 写入数据
INSERT VERTEX entity (name) VALUES "1":("神州数码");
INSERT VERTEX entity (name) VALUES "2":("云基地");
INSERT EDGE relationship (relationship) VALUES "1"->"2":("建立了");
...

图数据库的查询语法遵循 Cypher 标准:

MATCH p=(n)-[*1..2]-() RETURN p LIMIT 100;

以上语句从 NebulaGraph 中找到最多100个从某个节点出发,通过1到2条边连接的路径,并返回这些路径。

如果用可视化图结构展示的话,它是这个样子:

GraphRAG

如果借用 VectorRAG 的思想,通过图数据库来实现检索增强的话就演变出了 GraphRAG 架构,整体流程和 VectorRAG 并无差异,只是新知识的存储和检索都用知识图谱来实现,解决 VectorRAG 对抽象关系理解较弱的问题。

借助一些AI脚手架工具可以很容易地实现 GraphRAG,以下是用 LlamaIndex 和图数据库 NebulaGraph 实现的一个简易 GraphRAG 应用:

import os
from llama_index.core import KnowledgeGraphIndex, SimpleDirectoryReader
from llama_index.core import StorageContext
from llama_index.graph_stores.nebula import NebulaGraphStore
from llama_index.llms.openai import OpenAI
from pyvis.network import Network
from llama_index.core import (
    Settings,
    SimpleDirectoryReader,
    KnowledgeGraphIndex,
)

# 参数准备
os.environ['OPENAI_API_KEY'] = "sk-proj-xxx"
os.environ["NEBULA_USER"] = "root"
os.environ["NEBULA_PASSWORD"] = "nebula"
os.environ["NEBULA_ADDRESS"] = "10.3.xx.xx:9669"

space_name = "heao"
edge_types, rel_prop_names = ["relationship"], ["relationship"]  
tags = ["entity"] 

llm = OpenAI(temperature=0, model="gpt-3.5-turbo")

Settings.llm = llm
Settings.chunk_size = 512

# 连接Nebula数据库实例
graph_store = NebulaGraphStore(
    space_name=space_name,
    edge_types=edge_types,
    rel_prop_names=rel_prop_names,
    tags=tags,
   )
storage_context = StorageContext.from_defaults(graph_store=graph_store)

hosts=graph_store.query("SHOW HOSTS")
print(hosts)

# 抽取知识图谱写入数据库
documents = SimpleDirectoryReader(
    "data"
).load_data()

kg_index = KnowledgeGraphIndex.from_documents(
    documents,
    storage_context=storage_context,
    max_triplets_per_chunk=2,
    space_name=space_name,
    edge_types=edge_types,
    rel_prop_names=rel_prop_names,
    tags=tags,
    max_knowledge_sequence=15,
)

# 信息检索生成答案
query_engine = kg_index.as_query_engine()
response = query_engine.query("神州数码云基地在哪里?")
print(response)

VectorRAG 擅长处理具有一定事实性的问题,对复杂关系理解较弱,而 GraphRAG 刚好弥补了这一点,如果把这两者进行结合,理论上能得到更优的结果。

HybridRAG — 新一代 RAG 架构

我们可以把数据在 VectorDB 和 GraphDB 各放一份,分别通过向量化检索和图检索得到与问题相关结果后,我们将这些结果连接起来,形成统一的上下文,最后将组合的上下文传给大语言模型生成响应,这就形成了 HybridRAG 架构。
image-20240929145637811

由英伟达团队Benika Hall等人在前段时间发表的论文《HybridRAG: Integrating Knowledge Graphs and Vector Retrieval Augmented Generation for Efficient Information Extraction》提出了这一设想,并使用金融服务行业中的数据集成、风险管理、预测分析等场景进行对比验证。在需要从相关文本文档中获取上下文以生成有意义且连贯的响应时 VectorRAG 表现出色,而 GraphRAG 能够从金融文件中提取的结构化信息生成更准确的且具有上下文感知的响应,但 GraphRAG 在抽象问答任务或问题中没有明确提及实体时通常表现不佳。

该论文最后给出了 VectorRAG、GraphRAG和 HybridRAG 的测试结果:

表格中F代表忠实度,用来衡量生成的答案在多大程度上可以从提供的上下文中推断出来。AR代表答案相关性,用来评估生成的答案在多大程度上解决了原始问题。CP代表上下文精度,CR代表上下文召回率。

实现简单的 HybridRAG

以下示例用 Llama_index 作为应用框架,用 TiDB Vector 作为向量数据库,用 NebulaGraph 作为图数据库实现了简单的 HybridRAG 流程:

import os
from llama_index.core import KnowledgeGraphIndex, VectorStoreIndex,StorageContext,Settings
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.graph_stores.nebula import NebulaGraphStore
from llama_index.llms.openai import OpenAI
from llama_index.vector_stores.tidbvector import TiDBVectorStore

TIDB_CONN_STR="mysql+pymysql://xx.root:[email protected]:4000/test?ssl_ca=isrgrootx1.pem&ssl_verify_cert=true&ssl_verify_identity=true"

os.environ["OPENAI_API_KEY"] = "sk-proj-xxx"
os.environ["NEBULA_USER"] = "root"
os.environ["NEBULA_PASSWORD"] = "nebula"
os.environ["NEBULA_ADDRESS"] = "10.3.xx.xx:9669"

llm = OpenAI(temperature=0, model="gpt-3.5-turbo")

Settings.llm = llm
Settings.chunk_size = 512

class HybridRAG:
    def __init__(self):
        # 初始化向量数据库
        tidbvec = TiDBVectorStore(
            connection_string=TIDB_CONN_STR,
            table_name="semantic_embeddings",
            distance_strategy="cosine",
            vector_dimension=1536, # The dimension is decided by the model
            drop_existing_table=False,
        )
        tidb_vec_index = VectorStoreIndex.from_vector_store(tidbvec)
        self.vector_db = tidb_vec_index
        
        # 初始化知识图谱
        graph_store = NebulaGraphStore(
            space_name="heao",
            edge_types=["relationship"],
            rel_prop_names=["relationship"],
            tags=["entity"],
        )
        storage_context = StorageContext.from_defaults(graph_store=graph_store)
        kg_index = KnowledgeGraphIndex.from_documents(
            [],
            storage_context=storage_context,
            max_triplets_per_chunk=2,
            max_knowledge_sequence=15,
        )
        self.kg = kg_index
        
        # 初始化语言模型
        self.llm = llm
        
        # 初始化嵌入模型
        self.embeddings = OpenAIEmbedding()
        
    def vector_search(self, query):
        # 在向量数据库中搜索相关文本
        results = self.vector_db.as_retriever().retrieve(query)
        print(results)
        return [result.node for result in results]
    
    def graph_search(self, query):
        # 在知识图谱中搜索相关信息
        results = self.kg.as_retriever().retrieve(query)
        print(results)
        return [result.node for result in results]
    
    def generate_answer(self, query):
        vector_context = self.vector_search(query)
        graph_context = self.graph_search(query)
        combined_context = "\n".join(vector_context) + "\n" + graph_context
        
        prompt = f"Question: {query}\nContext: {combined_context}\nAnswer:"
        return self.llm.generate(prompt)

# 使用示例
hybrid_rag = HybridRAG()
question = "TiDB从哪个版本开始支持资源管控特性?"
answer = hybrid_rag.generate_answer(question)
print(answer)

以上实现中只是简单的拼装了从向量数据库和图数据库中的检索结果,实际应用中可引入相关reranker模型进一步做精排提高上下文精准度。不管最终使用什么样的 RAG 架构,我们要达到的目的始终是保障传递给大语言模型的上下文是更完整更有效的,从而让大语言模型给出更准确的回答。

总结

RAG 架构已经是提升大语言模型能力的有效方案,鉴于在不同的业务场景中正确率无法稳定保持,因此也衍生出了一系列变化后的 RAG 架构,如 Advanced RAG、GraphRAG、HybridRAG、RAG2.0 等等,它们之间有的是互补关系,有的是优化增强,也有另起炉灶的路线,可以看出在 LLM 应用优化上依然处于快速变化当中。

标签:RAG,index,图谱,数据库,graph,query,import,self,向量
From: https://www.cnblogs.com/hohoa/p/18456986

相关文章

  • 支持向量机
    一、SVM基本原理SVM(SupportVectorMachine)SVM是机器学习中常用的分类算法。SVM算法可以将......
  • 磁盘整理工具 IObit Smart Defrag Pro 免安装版
    IObitSmartDefragPro是一款功能强大的磁盘碎片整理工具。IObitSmartDefragPro最新版具有世界领先的碎片整理能力,IObitSmartDefragPro最新版不仅可以提供碎片整理功能,还可以根据使用频率智能地简化文件,从而加快磁盘速度并提高整个系统的性能,软件还能够对磁盘的文件系......
  • 一文彻底搞懂大模型 - Dify(Agent + RAG)
    **Dify是一个用于构建AI应用程序的开源平台。****Dify融合了后端即服务(BackendasService)和LLMOps理念。它支持多种大型语言模型,如Claude3、OpenAI等,并与多个模型供应商合作,确保开发者能根据需求选择最适合的模型。**Dify通过提供强大的数据集管理功能、可视化的Prompt......
  • GIS、向量、文字检索... 火山引擎 ByteHouse 集成全场景分析能力
    企业业务场景增多、规模扩大,对于底层数据架构来说,可能也会愈加复杂。 比如,某企业因自身业务发展,需要引入向量检索能力,但前期选型的技术架构并不能直接支持,只能重新引入向量数据库。这意味着,研发团队要维护多个组件,让底层架构非常复杂,不仅带来数据冗余,也给数据运维带来压力,造成......
  • 【RAG论文精读3】RAG论文综述1(2312.10997)-第1部分
    收录于我的专栏:AI修炼之路简介论文中英文名Retrieval-AugmentedGenerationforLargeLanguageModels:ASurvey面向大型语言模型的检索增强生成:综述论文地址arxiv地址:https://arxiv.org/abs/2312.10997精读理由这篇综述论文对RAG在大型语言模型中的应用进行了......
  • 大模型2-初试大模型+RAG
    任务使用大模型+RAG技术,缓解大模型幻觉问题。RAG介绍在实际业务场景中,通用的基础大模型可能存在无法满足我们需求的情况,主要有以下几方面原因:知识局限性:大模型的知识来源于训练数据,而这些数据主要来自于互联网上已经公开的资源,对于一些实时性的或者非公开的,由于大模型......
  • RAG系统评测实践详细版:Coze及相关产品评测对比,以及下一代RAG技术
    AIRAG系统评测实践:Coze及相关产品评测对比RAG(检索增强生成)是一种AI框架,它将传统信息检索系统(例如数据库)的优势与生成式大语言模型(LLM)的功能结合在一起,通过将这些额外的知识与自己的语言技能相结合,AI可以撰写更准确、更具时效性且更贴合您的具体需求的文字。RAG通过几个......
  • 文盘rust--使用 Rust 构建RAG
    作者:京东科技贾世闻RAG(Retrieval-AugmentedGeneration)技术在AI生态系统中扮演着至关重要的角色,特别是在提升大型语言模型(LLMs)的准确性和应用范围方面。RAG通过结合检索技术与LLM提示,从各种数据源检索相关信息,并将其与用户的问题结合,生成准确且丰富的回答。这一机制特别适用于需......
  • Chromium 中Window.localStorage对象c++实现分析
    一、前端定义Window.localStorage只读的localStorage 属性允许你访问一个Document 源(origin)的对象 Storage;存储的数据将保存在浏览器会话中。localStorage 类似 sessionStorage,但其区别在于:存储在 localStorage 的数据可以长期保留;而当页面会话结束——也就是说,当页面......
  • 大模型学习----什么是RAG
    大模型快速定制的RAG(Retrieval-AugmentedGeneration)方法一、什么是RAGRAG(Retrieval-AugmentedGeneration)即检索增强生成,它是一种结合了检索和语言生成的技术,旨在利用外部知识源来增强大型语言模型的输出。通过在生成过程中引入检索步骤,可以为模型提供更准确、更相关的信......