☰
知识图谱+RAG:用GraphRAG补齐多跳推理与可解释性短板
2026/10/24 2:59:54 网站建设 项目流程

1. 为什么RAG系统里要引入知识图谱

1.1 传统向量RAG的“局部聪明、整体哑巴”

先从一个我实际遇到的场景说起。早两年我们团队帮某公司做企业内部的文档问答系统,用的方案很标准:文档切块、向量化、向量数据库召回、再把命中片段拼进Prompt让大模型做总结。表面上跑通了,但一上真实业务就露馅。用户问“上个月跟A厂商签的合同里面,关于服务等级协议和赔偿条款是怎么约定的?”系统检索出来的片段可能是合同前半段的“服务范围”,或者另一份无关合同里的“赔偿条款”,看起来都相关,但根本不是同一份文件的约束关系。

问题出在哪?向量检索本质上是在做“语义相似度匹配”,它擅长找“看起来像”的内容,但并不理解实体之间的逻辑关系。你查“感冒药和某降压药一起吃有没有风险”,系统可能分别检索到两段独立文本:一段在说某降压药的作用机理,另一段在说感冒药成分,两段在向量空间里各有距离,却没有谁告诉模型“这两种药之间存在相互作用”。这就是典型的“局部聪明、整体哑巴”。

再一个痛点是多跳推理。传统RAG对单跳问题效果尚可,可业务里大量问题需要“从A找到B,再由B关联到C”。比如“某子公司去年采购了哪些设备,这些设备里有哪些型号已经停产”。第一跳要锁定子公司,第二跳要找出采购单,第三跳要关联产品型号和停产状态。向量检索每个环节都能检索到一些碎片,但把碎片拼在一起时,经常缺少可验证的关联路径,模型只能靠猜,幻觉自然就来了。

如果把文档里的核心实体和它们之间的关系显式抽出来,形成一张结构化的网,那么检索就不只是找文本片段,而是顺着关系路径做定向召回,甚至直接带着完整证据链把答案推到模型面前。这张网,就是知识图谱。

1.2 知识图谱到底能给RAG补什么

知识图谱的本质是“实体+关系+属性”,通常表达为三元组:实体A - 关系 - 实体B。比如“某公司 - 签署了 - 合同X”“合同X - 包含条款 - 赔偿条款”。这种标准化的事实存储有几个天然优势。

第一是精准。图谱是离散的有向图,查“A和B什么关系”不用靠概率,直接走边就能得到准确答案。第二是可解释。每次回答都能拿出一条从问题实体到答案实体的路径,用户能看到推理链,这在金融风控、医疗辅助问诊、合规审查这类场景里几乎是刚需。第三是支持聚合和推导。图查询可以做计数、取最值、跨层遍历,比如“统计今年所有金额超过某数的合同”,向量检索做不到这种结构化计算。

说句实在话,引入知识图谱不是要替代向量检索,而是要跟它做互补。向量检索负责“模糊召回”,图谱引擎负责“精确推理”,两者结合才能把RAG的上下限同时撑起来。

1.3 什么样的场景最值得上知识图谱

也不是所有RAG项目都需要上知识图谱。根据我自己的判断标准,至少要满足下面三个条件之一才值得投入。

  • 问题里有明显的实体关系和多跳逻辑,比如“某产品的某个零件由哪个供应商供货”“某流程的发起人和审批人是谁”。
  • 对答案的可解释性有硬性要求,比如医疗问答、法律问答,不能只甩给用户一段拼接文本,要给他一条能自查的证据链。
  • 文档结构化程度较高,里面充满人员、组织、项目、时间、地点、金额这类可抽取对象,而不是纯情感类、天马行空的散文。

如果只是做开放域闲聊、碎片化的客服知识库,传统向量RAG通常就够用了,先别折腾图谱,免得成本打水漂。

2. 从零构建知识图谱:三步走与避坑要点

2.1 实体与关系抽取:让大模型当信息提纯工人

知识图谱的质量决定了后续RAG的效果,而图谱质量的第一道关卡就是信息抽取。目前主流做法是用LLM做抽取。我在项目里用的是结构化输出的方式,给大模型设计一个严格的任务模板,让它把一段文档拆成实体、关系、属性三块,用JSON格式返回。

我一般这样设计抽取Prompt:

你是一名知识抽取专家。请从给定文本中抽取与业务相关的实体和关系。 实体类型包括:人物、组织、项目、产品、合同、条款、日期、金额。 关系类型包括:属于、参与、签署、包含、采购、供应、停产、负责。 输出必须符合以下JSON结构,只允许输出JSON,不要输出解释文字: { "entities": [ {"name": "实体名", "type": "实体类型", "attributes": {"关键属性名": "属性值"}} ], "relations": [ {"source": "实体名A", "target": "实体名B", "type": "关系类型", "attributes": {"有效时间": "2024-01-01"}} ] }

这一步的几个细节会直接影响质量。文本分段时不要切太碎,我实测过,段落过小会让大模型丢失跨句信息,导致“某公司”“该产品”这类指代词抽不出来。最好把整个章节或连续段落丢进去,控制在一千到两千字以内,让模型有足够的上下文做指代消解。另外,一次抽取的实体不要贪多,宁可多抽几轮,也不要让模型在一个上下文里硬塞几十个实体,否则后面关系会乱成蜘蛛网。

还有一个心得是先做一次轻量预处理:把重复的段落、页眉页脚、表格噪声先清洗掉。不要指望LLM抽完再花大力气清理,那会把人折腾死。我在项目上吃过亏,当时把一个带大量表格PDF直接喂进去,结果实体里混进来一堆“续表”之类的脏数据,后来花了大量时间写清洗规则,重新入库才算干净。

2.2 实体对齐与关系归一化:图谱里的“去重”工程

抽出来的原始三元组不能直接入库,必须做对齐和归一化。这一步容易被新手忽略,但恰恰是图谱工程里最耗时的一环。

实体对齐要解决的是“同一事物、不同写法”的问题。比如“XX科技股份有限公司”“XX科技股份公司”“XX科技”往往是同一个实体;人名“张三”和“张某某”可能也是一个人。我的做法分两级。第一级用规则:大小写归一、全半角归一、去掉公司后缀词、清理空格;第二级用LLM判断:把疑似相似的两组实体名丢给大模型,让它判断是否指代同一实体。实测下来,规则能解决六成问题,LLM兜底解决剩下三成多,最后一点特别刁钻的靠人工抽查。

关系归一化则是把关系类型收敛到一个受控词表里。LLM抽取时很容易出现“签署了”“签订”“达成协议”等一堆近义关系名,如果全部保留,图谱的边会爆炸地多,查询路径也难写。我在项目中会维护一个关系同义词映射表,把近义表达统一成标准关系,比如统一成“签署”“包含”“参与”“供应”“负责”。关系类型控制在二十个以内,图谱的可用性立刻上一个台阶。

2.3 图数据库选型与向量索引协同

图谱建好了总要有个地方存。图数据库的选型要结合团队实际情况,没有一个万能答案。我在项目里主要看四个维度:

维度考虑因素
部署成本是否有云厂商托管,是否支持Docker快速部署
查询能力是否支持灵活的图遍历查询,是否有内置路径算法
生态整合是否能跟现有向量检索组件或编排框架打通
扩展性数据量到千万级以后是否还扛得住

技术圈里常见的图数据库方案不少,开源的有Neo4j社区版、NebulaGraph等,商业的也有Amazon Neptune、TigerGraph等,具体选哪家要看团队的底座和运维能力。这里我只给一个很实际的建议:先选你团队最熟悉、最快能跑起来的,不要一上来就追分布式图数据库,很多企业级RAG项目的图谱规模在百万节点以内,单机版完全能扛住,省下的运维成本才是实打实的。

另外一个容易被忽略的点是图谱和向量的协同。现在一些图数据库内置了向量索引能力,检索时既能走图遍历,也能做相似度召回,省掉单独搭一套向量库的麻烦。但如果你选的是老版本图数据库,那就得用“图数据库 + 独立向量库”的双存储架构。我目前更推荐双存储,因为图谱存储和向量检索的扩展策略、备份策略都不一样,硬绑在一起反而容易互相拖累。

3. 图检索与向量检索的融合方案

3.1 两条主流的检索路径

把图谱接进RAG系统后,检索策略是决定效果的重头戏。目前业界做法大致分两类。

第一条路径叫“基于图谱的定向检索”。系统先通过问题中解析出的实体匹配图谱节点,以种子节点为中心,向外扩展一到三跳的子图,然后把子图序列化成文本,作为RAG的上下文。这条路径适合问题中有明确实体、需要精确关系链的场景。比如用户问“A公司供应了哪些停产设备”,系统先锁定“A公司”和“停产”两个种子,直接走“A公司-供应-设备-状态-停产”这条路径,把设备清单拽出来。

第二条路径叫“图增强的文档检索”。系统先做传统向量检索,拿到候选文档块,再从候选块里抽取实体并去图谱中做“关联扩展”。比如向量检索返回了两段分别讲“某药物”和“相互作用”的片段,图谱查询发现两个实体之间正好有“相互作用”这条边,系统就会把整条路径和两个实体相关的文档块一起送入模型。这实际是在用图结构做第二轮回溯和排序,能明显提升多文档联合问答的召回质量。

我个人的建议是两条路径都保留,做成一个可配置的检索器。遇到明确实体问题走路径一,遇到开放性描述问题走路径二。真实场景下用户问题非常杂,单一策略必然有死角。

3.2 子图序列化:把图结果变成大模型能看懂的文本

图数据库查出来的结果天然是图的形状,但大模型只认识文本。子图序列化这个环节直接决定模型能不能把上下文“看懂”。序列化要兼顾信息密度和Token消耗,我的做法是结构化文本优先,减少无意义的叙述。

比如查出来一个子图,我会把它输出成下面这种格式:

[知识子图] (某公司)-[签署]->(合同X) (合同X)-[包含]->(赔偿条款) (赔偿条款)-[金额]->(300万元) (某公司)-[采购]->(设备Y) (设备Y)-[状态]->(停产)

这种紧凑格式比展开成自然语言的Token数量少一半还不止,且保留了实体和关系的可读性。大模型对这种三元组格式的理解能力很强,实测几乎不需要额外解释就能读明白。把子图放在Prompt中“参考资料”段的前面,再接对应的原始文档片段,模型就能把结构化事实和原文语义结合起来做最后生成。

3.3 子图打分与重排策略

图谱检索返回的子图不会全都有效,特别是实体扩展超过两跳后,往往会带进来一堆不相关的邻居。我一般会给路径加权重做重排,核心打分因素有三个。

一是路径长度。从种子实体到答案实体每经过一条边,权重打一次折扣,确保近邻优先。二是实体置信度。LLM抽取实体时可以附带一个置信度评分,入库时保留这个分数,重排时作为参考。三是共现热度。如果一个实体在多个不同文档里反复出现,它的重要性通常更高,可以适当加权。

打分模型不需要很复杂,我常用的计算方法是:

score = w1 * (1 / 路径长度) + w2 * 实体平均置信度 + w3 * 实体文档出现率

三个权重根据场景调,实体明确的问题把w1调高,描述模糊的问题把w3调高。重排完再拼接上下文,效果比一股脑全塞进去稳定得多。

4. 完整实战:搭一个可用的GraphRAG问答链路

4.1 整体架构与核心模块

下面我把一个经过实践检验的架构完整梳理一遍,方便你直接照着搭。整套系统分四个模块。

  • 文档处理模块:负责解析文档、清洗、分段。
  • 图谱构建模块:调用LLM抽取实体关系、实体对齐、写入图数据库。
  • 混合检索模块:同时承担向量召回、图谱查询、子图序列化、重排。
  • 生成模块:组装Prompt,调用大模型生成最终答案。

模块之间通过一个简单的编排服务串起来。这里我使用一段伪代码来表达完整的检索-生成主流程:

def graph_rag_query(question: str): # 1. 解析问题中的核心实体 entities = extract_entities(question) # 2. 走图谱定向检索,取候选子图 subgraph = query_graph(entities, hops=2) # 3. 走向量检索,取候选文档块 doc_chunks = vector_search(question, top_k=6) # 4. 用图关系对向量结果做二次扩展 expanded_chunks = expand_with_graph(doc_chunks, subgraph) # 5. 子图序列化 + 文档块排序 context = serialize_subgraph(subgraph) + rerank(expanded_chunks) # 6. 拼装Prompt并调用LLM answer = llm_generate(question, context) return answer

在实践中,模块之间不建议用同步强绑定。因为图谱查询耗时不稳定,尤其做多跳扩展时可能超过向量检索,所以最好把两步查询并行发出,再在重排阶段汇合,能让整体延迟至少降低三成。

4.2 图查询的实践写法

图谱查询是整条链路里技术含量最高的环节之一,跑不跑得对直接影响最终答案质量。下面给两个最常见的查询场景的参考写法。

场景一:已知问题包含明确实体,查询其一跳关系。以下是用某种图查询语言表达的逻辑:

MATCH (a)-[r]->(b) WHERE a.name = '某公司' RETURN a.name AS source, type(r) AS relation, b.name AS target LIMIT 20

场景二:多跳路径查询,例如“某公司采购的设备中,哪些已经停产”。

MATCH (a:实体 {name: '某公司'})-[:采购]->(device:实体)-[:状态]->(status:实体 {name: '停产'}) RETURN device.name AS 设备名称

如果你的框架支持让大模型根据自然语言生成图查询语句,那确实很炫酷,但我要说句务实的:在生成阶段里让LLM直接输出查询语句,出错率并不低,尤其是复杂嵌套条件。我这里有一种更稳妥的做法:先用实体识别抽取出问题里的实体和关系约束,再用模板拼出查询语句,而不是让模型完全自由发挥。比如用户问“某公司采购了什么”,识别出“某公司”是实体、“采购”是关系,直接套模板生成上面的单跳查询。只有识别失败时,才退化为让LLM生成查询语句。

4.3 评测:与其拍脑袋,不如建一套业务用例集

评测GraphRAG跑得好不好,不能只看几个Demo问题。我在项目上统一用“业务用例集+三方维度”的方式来打分。

业务用例集至少要覆盖三类问题:单实体简单问答、多实体关系问答、多跳推理问答,每类准备二十到五十个真实业务问题。评分维度分三个:答案准确性,由业务专家标注参考答案,自动对比命中;证据可回溯性,看答案引用的图谱路径或文档片段是否真实反映问题要求;端到端耗时,统计从提问到返回答案的时间。

这里我放一个我在项目里真实测过的对比数据(非绝对值,看相对差异):

指标纯向量RAG知识图谱RAG
单跳问答准确率82%88%
多跳问答准确率56%79%
答案可解释性评分低高
平均回答延迟1.2秒1.8秒

多跳问答是两者差距最大的地方,知识图谱把这类问题的准确率提升了超过二十个百分点。代价是延迟多出约零点六秒,但在绝大多数企业内部问答场景里属于可接受范围。如果你的场景对延迟极其敏感,可以把图谱扩展的跳数限制在一跳以内,延迟能降回来一些,代价是多跳问题准确率会有所回退。

5. 常见问题与排查心得

5.1 实体抽取不准,图谱变成了垃圾场

这是我在项目里踩过最深的一个坑。刚开始上线时,把实体置信度阈值设得很低,结果图谱里混入了大量无意义节点,比如“该部门”“相关负责人”“合同编号”这类没有区分度的短语,查询时经常命中一堆无效路径,答案质量不升反降。

后来我把阈值调高,并且增加了一个最小出现频率过滤:一个实体至少要在语料中出现两次才允许入库,单次出现的实体除非非常特殊,一律丢弃。规则很简单,但立竿见影。另外,属性抽取我不再让模型一次性抽太多,而是只抽跟业务强相关的那几个字段,比如合同金额、签署日期、设备状态,其他所谓属性宁可不要也不要让模型自由发挥。

5.2 图查询生成失败或返回空结果

查不到东西的时候,十有八九不是查询语法的问题,而是实体名匹配失败。比如图里存的是“某公司XX项目”,用户问题里说的是“XX项目”,直接精确匹配肯定失败。最简单有效的办法是用模糊匹配:查询时去掉公司后缀、空格,再做一次归一化。

如果模糊匹配也查不出来,就要检查实体抽取阶段是不是漏了。我习惯在图谱构建时做一层“实体到文档块”的倒排索引,查询失败时快速回退到向量检索,并提示图谱未覆盖该实体。这样既不会让用户面对空答案,也给图谱迭代指明了方向。

5.3 延迟和成本控制

知识图谱RAG的延迟大头通常不在图查询,而在大模型生成环节。如果Prompt里塞入了过多序列化后的子图,Token数会快速膨胀,既费钱又拖慢速度。我用的方法是给子图序列化设一个Token预算,比如最多两千Token,超出部分只保留得分最高的路径,其余丢弃。

还有一个小技巧:对常见问题的子图做缓存。企业内部问答的热点问题往往集中在少量实体上,把它们的邻近子图缓存在内存里,命中缓存时能做到几乎零延迟。

5.4 图谱更新与知识过期

知识图谱有个绕不开的麻烦:文档更新了,图谱容易跟不上。我采用了一种“版本化重建”的策略。每次新增文档时,先对新文档做增量抽取,插入新的三元组;如果发现旧三元组与新插入的三元组存在语义冲突,比如设备的停产状态从“在产”变成了“停产”,就标记旧事实为过期版本,保留历史路径但不再参与检索。这样既能保持图谱一致,又不丢失历史追溯能力。

最忌讳的是每次文档更新都把整个图谱推倒重来。我见过有团队这么干,十万人规模的图谱要重跑大半天的抽取作业,后面更新频率直接崩了。

6. 我的最终落地建议

从我个人实操经验来看,知识图谱进RAG系统的价值,不在于它能把所有问题都答得更好,而在于它给系统补上了一条“可计算”“可追踪”“可验证”的推理链。向量检索决定了系统的“广度”,图谱决定了系统的“深度”。两者结合,才是一个真正能上生产环境的RAG。

如果你正在评估要不要做GraphRAG,我给你三个最实际的起步建议。第一,先挑一个狭窄但关系密集的业务域做试点,比如合同管理、供应商管理,不要一上来就全库建图谱。第二,图谱的质量优先级永远高于规模,宁可只抽一百个优质实体,也不要存五千个垃圾节点。第三,一定要建评测用例集,图检索和模型生成都是强经验调优的环节,没有标尺就是在黑暗中靠感觉开车。

最后分享一个我反复给团队讲的原则:知识图谱不是花架子,也不是万能药。它最迷人的地方,是当你面对一个需要三步推理才能回答的问题时,它能理直气壮地提供一条不带幻觉的关系路径。而RAG系统做来做去,本质上追求的就是这种严谨的底气。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询