跳到主要内容
GraphRAG:基于 PolarDB、通义千问和 LangChain 的知识图谱与大模型融合方案 | 极客日志
Python AI 算法
GraphRAG:基于 PolarDB、通义千问和 LangChain 的知识图谱与大模型融合方案 综述由AI生成 GraphRAG 结合知识图谱与向量检索提升大模型问答准确性。基于 PolarDB、通义千问和 LangChain 搭建系统,利用 PolarDB 同时支持 AGE 图引擎和 pgvector 插件的特性,实现图数据与向量数据的统一存储。通过对比单独使用向量检索、图检索及联合搜索的效果,验证了图 + 向量联合搜索在复杂查询中的优势,能有效减少幻觉并增强上下文理解,提供高质量的 RAG 问答结果。
黑客帝国 发布于 2025/2/6 更新于 2026/6/3 18 浏览
本方案介绍如何使用 PolarDB、通义千问和 LangChain 搭建 GraphRAG 系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图 + 向量联合搜索增强了问答准确性。PolarDB 支持 AGE 图引擎和 pgvector 插件,实现图数据和向量数据的统一存储与检索,提升了 RAG 系统的性能和效果。
业务场景
知识图谱
知识图谱 (KG) 是谷歌提出的一种知识表示形式,它通过互联的节点和实体捕捉知识,以结构化的形式表示关系和信息。
知识图谱具有以下优势:
结构化信息 :知识图谱将信息以节点(实体)和边(关系)的形式组织,使得复杂信息结构化,便于存储和查询。
语义理解 :通过明确的关系定义,知识图谱可以帮助系统更好地理解信息之间的语义关系,提升信息检索和自然语言处理的效果。
知识关联性 :知识图谱能够将不同的知识点联系起来,形成更丰富的知识网络,帮助用户发现隐藏的关联。
支持推理 :基于知识图谱,系统可以进行逻辑推理,从已知的信息推导出新的信息,提高智能应用的能力。
可视化 :知识图谱通常可以通过图形化的方式展示,使得复杂关系一目了然,便于用户理解和分析。
知识图谱被广泛应用于金融风控,企业知识管理以及社交网络分析等多种业务场景中。
RAG
检索增强生成(Retrieval Augmented Generation, RAG)作为一种强大的技术,它结合了信息检索与生成模型的创新方法,用来解决大语言模型 (LLM) 的局限性问题。
RAG 通过利用从各种来源检索到的相关数据来增强 LLM 提示,来实现更为准确和上下文相关的文本生成。RAG 系统的准确性在很大程度上依赖于它们获取相关、可验证信息的能力。
RAG 中信息检索通常使用诸如关键词匹配或语义相似性等技术来实现的。在语义相似性中,例如,数据被表示为由 AI 嵌入模型生成的数值向量,这些向量试图捕捉其含义。前提是,相似的向量在向量空间中相互靠近,然后通过近似最近邻(ANN)搜索获取相似的信息;关键词匹配则更为简单,使用准确的关键词匹配来查找信息,通常使用诸如全文检索等算法。
但是,基于关键词或相似性搜索构建的简单 RAG 系统在需要推理的复杂查询中表现不佳。简单的相似度的检索无法对实体之间的关系进行推理和判断。
GraphRAG
GraphRAG 是一种新的 RAG 系统,它结合了知识图谱和大型语言模型(LLM)的优势。在 GraphRAG 中,知识图谱作为事实信息的结构化资源库,LLM 将自然语言转换为知识图谱的查询信息,从图谱中检索相关知识,并生成针对问题的回答。
GraphRAG 解决了上述许多局限性,因为它能够对数据进行推理。
GraphRAG 具有以下优势:
改善信息检索 :通过理解实体之间的基本联系,GraphRAG 可以更准确地识别相关信息。
增强上下文理解 :知识图谱为查询理解和响应生成提供了更丰富的上下文。
减少幻觉 :通过将响应建立在事实知识上,GraphRAG 可以减轻生成错误信息的风险。
最佳实践
本文以一个开源的股票知识图谱为例,介绍如何使用 PolarDB+ 通义千问+LangChain 搭建一个 GraphRAG 系统。
技术实现
PolarDB
PolarDB PostgreSQL 版(下文简称为 PolarDB)是一款阿里云自主研发的云原生关系型数据库产品,100% 兼容 PostgreSQL,高度兼容 Oracle 语法;采用基于 Shared-Storage 的存储计算分离架构,具有极致弹性、毫秒级延迟、HTAP 的能力和高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB 具有大规模并行计算能力,可以应对 OLTP 与 OLAP 混合负载。
PolarDB 具备高度兼容 apache AGE 的图引擎,支持对知识图谱的存储和查询检索。同时 PolarDB 具备 pgvector 增强插件,支持对向量数据的存储与检索。
通义千问 通义千问是由阿里云自主研发的大语言模型,用于理解和分析用户输入的自然语言,在不同领域和任务为用户提供服务和帮助。
在 RAG 场景中,通义千问基于用户的查询或上下文,结合用户兴趣或历史交互相关的信息,生成更加个性化的回复。
LangChain LangChain 是一个开源的工具包和框架,旨在简化和加速基于语言模型的应用程序开发。LangChain 的核心在于将强大的语言模型(如 OpenAI 的 GPT 系列、阿里云的通义千问等)与实际应用结合起来,帮助开发者构建诸如聊天机器人、文本生成、知识管理、代码辅助等多种自然语言处理(NLP)相关应用。
LangChain 中实现了 apache age 图插件和 pgvector 插件的支持,可以支持对于知识图谱和向量两种检索方式。
查询流程
用户提出相关问题
RAG 系统在知识图谱中检索相关的答案
RAG 系统把知识图谱的检索结果作为向量检索的相关信息,用向量相似性检索的方式检索相关的文档
RAG 系统将多种结果输入给大语言模型
大语言模型根据输入的信息组织问答结果
RAG 系统将问答结果返回给用户
建议配置 项目 推荐配置 PolarDB 版本 标准版 兼容 PostgreSQL 14 CPU >16 Core 内存 >64 GB 磁盘 >100GB (AUTOPL) 版本 >2.0.14.23.1
实战步骤
准备工作
环境准备 申请阿里云灵积模型 api key(如已有 key 可略过此步骤)
该 api key 是访问灵积模型服务的凭证,需要妥善保管。
pip install langchain
pip install langchain-community
pip install python-dotenv
pip install dashscope
pip install psycopg
如遇到一些安装失败的问题,需要升级 python 版本 > 3.7。
age_graph.py 位于 /site-packages/langchain_community/graphs/age_graph.py 下,需要修改两处地方:
LOAD 'age'; sql 语句修改为 select * from ag_catalog.get_cypher_keywords() limit 0; 确保 PolarDB 可以正确加载对应的扩展
MATCH ()-[e]-() RETURN collect(distinct label(e)) as labels 修改 MATCH ()-[e]->() RETURN collect(distinct label(e)) as labels 加速对图的 schema 的获取
数据库准备
创建 AGE 插件 AGE 是一个为 PostgreSQL 系列数据库打造的扩展,旨在增强其处理图数据的能力。AGE 旨在结合关系型数据库与图数据库的优势,提供一个高性能、灵活且易于扩展的解决方案。
创建 vector 插件 Vector 是一个 PostgreSQL 的扩展插件,用于高效地处理和查询高维向量数据。vector 插件提供了高维向量的存储以及基于向量的近似最近邻(Approximate Nearest Neighbor, ANN)搜索功能。
数据入库 将数据进行下载。数据分为两部分,一部分为图数据 (data/import 目录),包含了人员 (Executive), 产业 (Industry), 股票 (Stock), 概念(Concept)等点以及人员 - 股票,股票 - 概念,股票 - 产业之间的关联关系,这部分数据以图的方式存储到 PolarDB 中。
另一部分为每个股票的介绍信息(data/stockpage),原始数据为股票的网页信息,切分后以向量的方式存储到数据库中以提供进一步的信息。
图数据 创建一个名为 stock_graph 的图用于存储该知识图谱:
SELECT create_graph('stock_graph' );
附录 1 中脚本可以将数据转换为 Cypher SQL 脚本,配合客户端工具,如 psql 等可完成数据导入。转换后的 sql 脚本示意如下:
SELECT create_vlabel('stock_graph' ,'person' );
SELECT * FROM cypher('stock_graph' , $$ CREATE (:person {person_id:'dddbd3ad0f2e3fca80da88296298bb51' ,name:'杜玉岱' ,gender:'男' ,age:'58' }) $$ ) as (n agtype);
SELECT * FROM cypher('stock_graph' , $$ CREATE (:person {person_id:'2f867939e123f10437a15a127799248e' ,name:'延万华' ,gender:'男' ,age:'45' }) $$ ) as (n agtype);
SELECT * FROM cypher('stock_graph' , $$ CREATE (:person {person_id:'e68b3ae7a003c60cd9d50e371cdb3529' ,name:'宋军' ,gender:'男' ,age:'48' }) $$ ) as (n agtype);
...
SELECT * FROM cypher('stock_graph' , $$ MATCH (a:person), (b:stock) WHERE a.person_id = 'dddbd3ad0f2e3fca80da88296298bb51' AND b.stock_id = '601058' CREATE (a)- [e:employ_of {jobs:'董事长/董事' } ]- > (b) RETURN e$$) as (e agtype);
SELECT * FROM cypher('stock_graph' , $$ MATCH (a:person), (b:stock) WHERE a.person_id = '2f867939e123f10437a15a127799248e' AND b.stock_id = '601058' CREATE (a)- [e:employ_of {jobs:'副董事长/董事' } ]- > (b) RETURN e$$) as (e agtype);
SELECT * FROM cypher('stock_graph' , $$ MATCH (a:person), (b:stock) WHERE a.person_id = 'e68b3ae7a003c60cd9d50e371cdb3529' AND b.stock_id = '601058' CREATE (a)- [e:employ_of {jobs:'董事' } ]- > (b) RETURN e$$) as (e agtype);
...
向量数据 文本信息按照一定规则切割后,以向量的形式存储到数据库中。切分采用 langchain 的 RecursiveCharacterTextSplitter 切分器,实际使用中可根据需要进行切分,并使用通义大模型转换为向量。
pip install BeautifulSoup
pip install bs4
数据库中创建了对应的数据表 docs 用于记录文本以及对应的文本向量。
CREATE TABLE IF NOT EXISTS docs (
id bigserial primary key ,
title text,
content text,
tokens integer ,
embedding vector(1536 )
);
在向量上创建索引,此处使用 hnsw 索引,并使用欧式距离 (l2 距离) 进行查询。(索引类型和距离计算方式可根据实际需要进行选择)
CREATE INDEX ON docs USING hnsw (embedding vector_l2_ops);
查询 以问题'李士祎关连的股票信息?'为例进行查询,并对于单独使用向量检索、图检索以及图加向量检索的结果进行对比。
单独使用向量检索 DASHSCOPE_API_KEY 从环境变量中读取:
import os
DASHSCOPE_API_KEY=os.environ["DASHSCOPE_API_KEY" ]
from langchain.embeddings import DashScopeEmbeddings
embeddings = DashScopeEmbeddings(model="text-embedding-v1" , dashscope_api_key=DASHSCOPE_API_KEY)
from langchain_community.llms import Tongyi
llm_tongyi=Tongyi(temperature=1 )
RetrievalQA 是 LangChain 中封装的一个 chain,可以实现基于本地知识库的问答。
问答大语言模型过程中需要输入相关文档,来进行答案的生成。这里定义了一个 Retriever,通过向量检索的方式来获取相似度最大的 5 篇文档:
from langchain.schema import Document
from langchain_core.retrievers import BaseRetriever
class CustomRetriever (BaseRetriever ):
def __init__ (self ):
super ().__init__()
def _get_relevant_documents (self, query: str ) -> list [Document]:
relevant_docs = []
cur = conn.cursor()
cur.execute("SELECT content FROM docs ORDER BY embedding <=> '{}' LIMIT 5" .format (embeddings.embed_query(query)))
top3_docs = cur.fetchall()
cur.close()
for doc in top3_docs:
relevant_docs.append(Document(page_content=doc[0 ]))
return relevant_docs
custom_retriever = CustomRetriever()
from langchain.chains import RetrievalQA
qa_chain = RetrievalQA.from_chain_type(llm=llm_tongyi, retriever=custom_retriever, verbose=True )
response = qa_chain.invoke("李士祎关连的股票信息?" )
print (response)
根据提供的信息,没有找到与李士祎相关的股票信息。请提供更多的信息以便我能更准确地回答您的问题。如果无法提供更多细节,那么我将无法给出具体的答案。
从执行过程中可以看到,直接执行向量相似度的执行结果如下:
('科士达 (002518) 公司资料_F10_同花顺金融服务网...' ,)
('佳士科技 (300193) 公司资料_F10_同花顺金融服务网...' ,)
('日签署的股权转让协议,沪士控股及碧景控股...' ,)
('5 年 8 月 1 日,香港碧景将其拥有的本公司全部股权转让...' ,)
('其中合并报表的有:7 家。序号关联公司名称参控关系...' ,)
这是因为涉及到的网页材料中与人名关联度较低,主要提供的是上市公司的相关信息,两者关联性不大,因此向量检索模式无法获取答案。
LangChain 中图引擎实现了对于 AGE 的支持,使用时需要先定义一个图对象,并获取图的模式。这里图的模式是指点和边的类型信息,用于生产图的查询语言。
from langchain.chains import GraphCypherQAChain
from langchain_community.graphs.age_graph import AGEGraph
conf = { "database" : "xxx" , "user" :"xxx" , "host" :"pc-xxxx.rwlb.rds.aliyuncs.com" , "port" :"1921" , "password" :"xxx" }
graph = AGEGraph(graph_name="stock_graph" , conf=conf)
graph.refresh_schema()
GraphCypherQAChain 是 LangChain 中封装的一个 chain,可以将自然语言转为图查询,实现本地图谱的问答。
graphchain = GraphCypherQAChain.from_llm(llm_tongyi, graph=graph, verbose=True , top_k=5 )
response = graphchain.invoke("李士祎关连的股票信息?" )
print (response)
根据提供的信息,这里有关于股票的信息:股票名称为酒鬼酒,代码为 799。但是,没有直接提到李士祎相关的具体股票信息。所以,基于给出的数据,我们不知道李士祎具体的关联股票详情。
可见基于图的查询虽然查到了李士祎关联的股票为酒鬼酒,且股票代码为 799,但是由于图中并没有存储酒鬼酒的信息,因此也无法给出具体的信息。
从执行的过程中可以看到,langchain 生成了 Cypher 语句并在知识图谱中进行了执行,查询到了酒鬼酒的名称以及股票代码。
MATCH (p:person)-[r:employ_of] ->(s:stock) WHERE p.name = "李士祎" RETURN s.name, s.code
[{'name' : '酒鬼酒' , 'code' : '799' }]
注意:如果 langchain 中生成的 Cypher 不正确,还可以使用 prompt 的方式给 langchain 提供示例 Cypher 以帮助生成。当然,也可以自定义一个 Retriever,通过连接数据库的方式执行自定义的 Cypher 以获得更加准确的回答。
图 + 向量联合搜索增强 以上两种查询的结果都不尽人意,因为向量检索和知识图谱都只存储了独立的内容,无法独自生成问答结果。将以上两种查询方式进行结合,把知识图谱的查询结果作为向量查询的输入信息,通过向量查询获取相关文档后,由 LLM 最终生成更加完整的问答结果。
此处定义了一个 prompt 的模版,把知识图谱的查询结果作为向量检索的输入,来获得更为准确的问答结果。
from langchain_core.prompts.prompt import PromptTemplate
from langchain.chains import LLMChain
graphchain = GraphCypherQAChain.from_llm(llm_tongyi, graph=graph, verbose=True , top_k=5 , return_direct=True ,
template = """Task:Generate more detailed information about the raw answer.
The question is:`{question}`the raw answer from knowledge graph in format:`{answer}`please give more detailed answer about raw answer"""
prompt = PromptTemplate(input_variables=["question" , "answer" ], template=template)
llm_chain = LLMChain(llm=llm_tongyi, prompt=prompt)
def dynamic_query (question ):
answer = graphchain.invoke(question)
if answer['result' ] == '' :
return "没有找到答案"
formatted_prompt = prompt.format (question=question, answer=answer['result' ][0 ])
answer = qa_chain.invoke(formatted_prompt)
return answer
response = dynamic_query("李士祎关连的股票信息?" )
print (response['result' ])
根据提供的信息,与李士祎相关的股票'酒鬼酒'的详细信息如下:
公司名称 :酒鬼酒股份有限公司
股票代码 :000799
所属地域 :湖南省
英文名称 :Jiugui Liquor Co., Ltd.
公司网址 :www.jiuguijiu000799.com
主营业务 :从事生产、销售曲酒系列产品。
主要产品 :
控股股东及实际控制人 :中皇有限公司(持有酒鬼酒股份有限公司股份比例:31.00%)
请注意,以上信息是基于所提供的上下文得出的结论,如果需要更详细的财务数据或其他具体信息,请参考官方公告或相关财经网站。
该问答结果不但准确地回答出相关的股票为'酒鬼酒',并且给出了酒鬼酒的相关信息。相比只使用向量查询和图查询,该结果更加符合预期,满足实际应用需求。
从执行过程中可以看到,当知识图谱中检索了相应的结果后,问题转换为:
Task:Generate more detailed information about the raw answer.
The question is :李士祎关连的股票信息?
the raw answer from knowledge graph in format :{'name_0' : '酒鬼酒' , 'code' : '799' }
please give more detailed answer about raw answer
在向量检索中包含了酒鬼酒的相关信息,使得向量检索的结果更加准确:
('酒鬼酒 (000799) 公司资料_F10_同花顺金融服务网...' ,)
('名:*ST 酒鬼公司网址:www.jiuguijiu000799.com...' ,)
('其中合并报表的有:0 家。序号关联公司名称参控关系...' ,)
('华谊 B 股 (900909) 公司资料_F10_同花顺金融服务网...' ,)
('华电 B 股 (900937) 公司资料_F10_同花顺金融服务网...' ,)
总结 如何有效利用私有数据一直是 RAG 系统中面临的重大挑战,其中知识图谱是企业私有数据的重要组成部分。得益于 PolarDB 的可扩展性,PolarDB 数据库中可同时存储向量数据和图谱数据,进行统一的存储和检索。同时相较于传统的向量检索,PolarDB 中可将图检索与向量检索相结合,提供更高质量的 RAG 问答结果,满足应用需求。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
随机西班牙地址生成器 随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online