深夜的警局档案室灯火通明,名侦探老周把连环案的几十份卷宗摊了一桌。财务报告里反复出现“环宇科技”,一位前员工的笔录里提到了创始人“王总”,一份产品手册则写着“智能门锁由环宇旗下子公司研发”。过去,老周破案靠的是那面照片墙:输入嫌疑人的体貌特征,系统按“长得像”的程度返回一张张相似面孔。可这次他很快发现,只看“长得像”远远不够——真正的关键线索,是那个总在受害人身边出现、却和外貌特征毫不沾边的中间人。 只按关键词和语义相似度检索的旧方法,就像只认“长相”的翻相册。它能找到内容相近的文档,却看不见文档里的人物“谁认识谁、谁属于谁”。GraphRAG 给了老周两样新工具:一盒图钉和一卷红线。先把卷宗里的实体全部钉上墙,再用红线标出“发明”“收购”“认识”,织成一张关系网;随后让“按相片找相似”的向量检索和“顺着红线摸”的图谱检索同时出击,前者召回语义相近的粗候选,后者补上多跳路径里的间接关联,最后把两路结果合并、排序、精挑。这张“相片+关系网”的双引擎检索术,就是本文的主角。
掌握图谱与向量融合的检索设计,是构建知识密集型问答与企业级 RAG 系统的核心基本功:当答案藏在线索链深处,只有双引擎检索能把隐而不见的关联捞出来。
可视化演示
通过融合检索、多跳遍历和社区聚类三个模式,展示知识图谱与向量检索如何互补增强RAG的上下文覆盖。
本节配有交互动效(进入视口后自动加载,约 3KB)。
图谱向量融合检索 向量检索:语义相似度匹配,快速定位相关文档块 图谱检索:沿实体关系边多跳推理,发现间接关联 Score = α·cos_sim + β·path_score 两路检索互补:向量覆盖语义盲区,图谱覆盖结构盲区
知识图谱构建
老周的第一步不是急着读卷宗,而是收拾证物板。他给每个卷宗里出现的人名、公司名、产品名贴上标签——“王总”“环宇科技”“智能门锁”,这叫实体识别;接着拿起红色马克笔,在两个标签之间画线并标注关系——“王总 创立 环宇科技”“环宇科技 生产 智能门锁”,这叫关系抽取。几十份卷宗读下来,贴满标签、画满红线的证物板,就变成了一张线索网。
当所有实体和关系被结构化地摆在图上,计算机科学里把这称为知识图谱(Knowledge Graph)。GraphRAG 的第一步正是如此:从文档集合中抽取实体与关系,构建一个可被程序遍历的知识网络。这张图的价值在于,它不再是一堆散落文本,而是“谁和谁相关、怎样相关”的显式表达。
知识图谱的基本存储单元叫三元组(triple):主语(head)、关系(relation)、宾语(tail)。一条“王总 创立 环宇科技”就是典型的“头实体-关系-尾实体”组合。用数学语言描述,整张图就是所有合法三元组的集合:
有了这张证物板,老周告别了“凭印象翻卷宗”的时代。往后每次提问,都能先在图上一眼看清谁和谁直接相连、谁与谁隔了几个人。但光有图还不够——如何把“按相片找相似”的老方法和新图结合起来,是下一节要解决的问题。
- 图符号 G表示整张知识图谱,它是全部合法三元组构成的集合
- 三元组 (h, r, t)一条连线的完整记录,h 是头实体,r 是关系,t 是尾实体
- 实体集合 E图中所有图钉(人物、组织、产品)构成实体集合,h 和 t 必须从这里取
- 关系集合 R图中所有红线(创立、生产、认识)构成关系集合,r 必须从这里取
图谱向量融合
老周的办公室里至今留着两套工具。一套是自动人脸识别仪,输入一段描述,就能按“语义长相”从档案库捞回最相似的面孔——这是向量检索;另一套是刚织好的关系网,从一个人出发能顺藤摸瓜找到他认识的人——这是图谱检索。老周发现,单用脸谱仪会漏掉“长得不像但关键”的中间人,单用关系网又会漏掉“长得像但暂无关系”的嫌疑面孔。
GraphRAG 的检索器正是采用这种“两路并行”设计:一路把用户问题编码成向量,与文档向量做余弦相似度匹配,得到语义候选;另一路抽取问题中的实体,在知识图谱上做遍历,得到与实体有直接或间接关联的文档。两路侧重点完全不同:向量擅长宽泛的语义近似,图谱擅长精准的实体关联,二者天然互补——这就是图谱路径补充与互补机制的含义。
最终得分是两路分数的加权融合。设 λ 是向量得分的权重,图谱得分权重就是 (1-λ):
老周把两套工具的结论记在同一本本子上。他明白,真正的高明不在于任何单一路径,而在于让“相片相似”和“关系相近”互相补位——这正是“图谱向量融合”这个名字的由来。
- 检索得分 Score(q,d)文档 d 对问题 q 的总相关度,融合后用于排序
- 余弦相似度 cos(q,d)向量路的得分,衡量问题与文档语义方向上的接近程度,值越接近 1 越相似
- 融合权重 λ取值在 0 到 1 之间,λ 越大越信任向量路,越小越信任图谱路,需要按数据集调优
- 图谱路径得分 Path(q,d)文档实体与问题实体在图上相隔多近,跳数越少分越高
多跳推理路径
老周在证物板上发现一条有趣的线:辞职员工小赵 → 认识 财务主管李姐 → 见过 环宇创始人王总。如果只看第一层,小赵和王总毫无交集;多走两步,一条隐藏的上下游关系就浮出水面。侦探行话管这叫“顺藤摸瓜”,图算法里则叫“多跳推理”。
多跳推理的本质是沿图的边逐层扩展:从问题涉及的实体出发,经过一跳找到直接邻居,两跳找到“朋友的朋友”,k 跳就是 k 层间接关联。它最大的价值在于捕获向量检索遗漏的间接关系:向量只比较“长得像不像”,而多跳推理回答的是“隔着几个人能否扯上关系”,这正是跨文档关联的根基。
用消息传递来建模这一过程:每一轮迭代,节点把邻居上一轮的表示取平均,作为自己的新表示,信息就这样沿着边扩散开去:
老周靠这套“走几步”的方法,找到了那根贯穿三份卷宗的红线。但他也清楚,藤蔓拉得太长容易扯到无关的花花草草——通常 2 到 3 跳以内是可靠的,再远噪声就开始累积。
- 节点表示 h_v^(k)第 k 轮迭代后节点 v 携带的信息向量,代表它积累的关联线索
- 邻居集合 N(v)与 v 直接相连的全部节点,是所有信息的来源
- 求平均运算把邻居们的表示相加再除以邻居个数,完成一次信息汇总传播
- 迭代更新k 从 1 循环到 K,信息沿图扩散 K 跳,捕获 k 层间接关联
社区检测摘要
案件牵涉上百人,关系网密密麻麻,老周盯着墙直皱眉。助手提议:把“平时来往密集”的人分成几个圈子,比如“环宇系高管圈”“离职员工互助圈”“投资方圈”,再给每个圈子写一份两三行的背景摘要。之后回顾案情时,只需先扫一眼圈子摘要,就能立刻知道当前问题属于哪一派势力。
这就是社区检测(Community Detection)的思路:在图里把连接紧密的一组节点划分为一个社区,再借助大语言模型为每个社区生成摘要。社区摘要相当于给检索加了一层“全局视野”:回答问题时先命中社区,再在社区内部定位具体文档,上下文覆盖更完整。
最常用的社区划分算法是鲁汶算法(Louvain),它通过最大化模块度(Modularity)来寻找最优分组。模块度衡量“社区内部连边比例”比“随机连接期望”高出多少:
老周的笔记本上从此多了几页“圈子档案”。遇上跨卷宗的大问题,先翻圈子摘要,再下钻具体文档,思路清晰了不止一倍——这就是社区摘要提供的“上下文覆盖”。
- 模块度 Q衡量社区划分质量的总体指标,越大说明划分越合理
- 总边数归一化 1/(2m)m 是全图总边数,除以 2m 把结果缩放到可比较的尺度
- 实际连边 A_ij节点 i 与 j 之间真的有边则为 1,否则为 0
- 随机期望 k_i k_j/(2m)按节点度数随机连接时,i 与 j 之间出现边的概率期望,用于做减法基准
- 同社区指示 δ(c_i,c_j)i 与 j 被分到同一社区时为 1,不同社区为 0,保证只统计社区内部的超额连接
混合检索架构
两路探员带队会师。人脸识别组带回一沓“相貌相似”的照片,关系网组带回一沓“关系相近”的名单。问题来了:两边的分数没法直接比较——这边是 0 到 1 的相似度,那边是按跳数折算的亲密度,一个 0.8 一个 0.5 到底谁更相关?老周让秘书把两沓材料分别按自己的标尺“拉平”,再合并成一张总表。
这就是混合检索架构中的分数归一化(Score Normalization)。向量检索的余弦相似度范围受嵌入空间影响,图谱路径得分的尺度则与跳数设置有关,两者不经过归一化直接相加,会引入严重偏置。生产系统中,向量路与图谱路通常并行召回,各自产出候选与分数,再统一处理后融合。
常用 min-max 归一化把每路分数都压到 [0,1]:
归一化就像把两沓不同单位的名册都翻译成统一的“相关度货币”,合并后才有意义。老周的总表上,向量路与图谱路的候选终于站在同一条起跑线上,接下来只剩最后一道工序:排座次。
- 原始分数 s某一路检索引擎(向量或图谱)给出的原始得分
- 最小值 smin 与最大值 smax该路候选集合中得分的最小值和最大值,构成映射区间
- 差值 (s - smin)当前分数与最低分的距离,衡量相对位置
- 归一化结果 ŝ除以极差后映射到 [0,1] 的标准化分数,两路分数从此同尺度可比
重排优化策略
总表上有几十条候选,老周深吸一口气,开始“排座次”。他不再满足于初筛的大致排序,而是逐一重新审视:与问题关键词直接命中的往前排,绕了三圈才沾边的往后放;同时参考两套引擎给的位次,让在两边都靠前的候选获得更高的最终排名。
这叫重排(Reranking):先由混合检索召回一个较宽的候选集合,再用更精细的打分模型或融合策略重新排序,把最相关的结果顶到最前面。向量路负责初筛宽度,重排负责精度——它是 RAG 系统里决定最终喂给大模型上文质量的关键一环。
倒数排名融合(RRF)是一种不需要调权重的经典融合排序法,它把每个文档在每路结果里的名次取倒数后相加:
老周把“两边都露脸的候选”提到了最前面。重排这一下看似轻巧,却常常是检索质量从“及格”到“优秀”的分水岭——就像破案时,把最像真凶的人放在审讯名单第一位。
- 融合总分 RRF(d)文档 d 在多路检索引擎下的最终排名分
- 求和符号 Σ把 M 路检索引擎各自的贡献累加起来,M 是引擎总数
- 排名 rank_i(d)文档 d 在第 i 路结果中的位次,从 1 开始计,位次越小越靠前
- 平滑常数 k避免排名为 1 时分母过小而分数爆炸,同时适度削弱头部优势
应用落地场景
这套“相片+关系网”双引擎的破案术,如今被老周写成了标准办案手册。它不是万能钥匙,但在三类案子中格外好使:需要横跨几十份卷宗才能还原真相的连环案、涉及多个部门互相扯皮的企业内部调查、以及整理一年年报时理清公司间收购与隶属关系的分析工作。
这三类场景对应 GraphRAG 的三个典型落地方向:知识密集型问答、企业文档检索、文档分析。它们的共同特征是:答案碎片分布在多个文档中,且必须通过实体之间的关联才能串起来——纯向量检索只能找到碎片,却拼不出全貌。
社区摘要为衡量上下文完整度提供了直观指标——查询覆盖度,即查询涉及的实体中有多大比例出现在命中的社区摘要里:
老周合上手册。侦破连环案的关键从来不是某一页卷宗写得多么详细,而是能否看清卷宗之间那条看不见的红线。GraphRAG 要做的,正是把这条红线从文档里抽出来、铺成网、走过去——让检索不仅“看得懂语义”,更“看得见关系”。
- 查询实体集 Q_ent从用户问题中抽取出的关键实体,比如“王总”“环宇科技”
- 摘要实体集 C_ent社区摘要中提及的实体,代表摘要覆盖到的知识范围
- 交集大小 |∩|双方共同拥有的实体数量
- 覆盖率 Coverage比值越接近 1,社区摘要对问题的支撑越充分,检索上下文越完整
AI 应用场景
跨文档知识问答
阶段:检索与召回(GraphRAG 双引擎)
解决的问题:传统向量检索只能按语义相似度召回单个文档,当答案需要融合多篇文档中不同实体的关系时(如“环宇科技现任 CEO 是被谁收购的”),会遗漏间接线索;GraphRAG 通过图谱多跳路径把相关文档串起来,再用社区摘要提供背景上下文。
具体案例:某法律科技公司的合同审阅助手,用户问“A 公司去年收购的子公司与 B 公司是否有合资关系”,系统先抽取实体,在图谱上遍历“收购—合资”关系链,召回并融合三份合同中的相关段落,给出带证据链的答案。
企业知识库检索
阶段:索引构建与查询重排
解决的问题:企业知识库文档散落在各部门,员工提问“上线了 X 服务的团队归谁管”,纯向量检索只能找到介绍 X 服务的文档,找不到“负责人”这一关系的源头;GraphRAG 建立组织结构图谱,沿“隶属/负责”边多跳定位到负责人及其汇报线。
具体案例:某大型互联网公司的内部问答机器人,通过 GraphRAG 将组织架构、项目归属、服务依赖关系建图,员工提问“这个服务挂了该找谁”的定位准确率提升了 35%,平均响应时间缩短一半。
科研文献综述
阶段:实体抽取与社区摘要
解决的问题:综述写作需要理清“某方法被哪些工作改进、又启发了哪些后续研究”的引用网络,向量检索只能按主题相近返回文献,无法表达“谁引用谁”的传承关系。
具体案例:学术助手根据论文引用关系构建引文图谱,按社区把研究流派分组,为每个流派生成摘要,研究者提问“这个方向的开山之作有哪些后续变体”时,系统沿引用边多跳召回并汇总流派脉络。
Python 演示
# -*- coding: utf-8 -*-"""Simplified GraphRAG: hybrid vector + graph retrieval demo.""" import refrom collections import deque TRIPLES = [ ("Alice", "works_at", "Acme"), ("Acme", "produces", "GadgetX"), ("GadgetX", "used_by", "Bob"), ("Bob", "works_at", "BetaCorp"), ("BetaCorp", "competes_with", "Acme"), ("Carol", "invests_in", "BetaCorp"), ("Alice", "friends_with", "Carol"),] DOCS = { "doc1": "Alice leads the GadgetX team at Acme.", "doc2": "Bob says BetaCorp competes with Acme.", "doc3": "Carol invests in BetaCorp and knows Alice.",} ENTITY_RE = { "Alice": r"Alice", "Bob": r"Bob", "Carol": r"Carol", "Acme": r"Acme", "BetaCorp": r"BetaCorp", "GadgetX": r"GadgetX",} def extract_entities(text): return set(name for name, pat in ENTITY_RE.items() if re.search(pat, text)) def build_graph(triples): g = {} for s, r, o in triples: g.setdefault(s, []).append(o) g.setdefault(o, []).append(s) return g def vector_sim(query_tokens, doc_tokens): if not query_tokens or not doc_tokens: return 0.0 common = len(query_tokens & doc_tokens) return common / (len(query_tokens) ** 0.5 * len(doc_tokens) ** 0.5) def graph_search(graph, start_entities, max_hops=2): reach = {} for start in start_entities: q = deque([(start, 0)]) seen = {start} while q: node, depth = q.popleft() if depth > max_hops: continue reach.setdefault(node, min(reach.get(node, 99), depth)) for nxt in graph.get(node, []): if nxt not in seen: seen.add(nxt) q.append((nxt, depth + 1)) return reach def hybrid_retrieve(query, alpha=0.5, max_hops=2): graph = build_graph(TRIPLES) q_ents = extract_entities(query) q_tokens = set(re.findall(r"[a-z]+", query.lower())) reach = graph_search(graph, q_ents, max_hops) scores = {} for doc_id, text in DOCS.items(): d_tokens = set(re.findall(r"[a-z]+", text.lower())) vec = vector_sim(q_tokens, d_tokens) d_ents = extract_entities(text) hop_bonus = 0.0 if d_ents: hop_bonus = sum(1.0 / (reach[e] + 1) for e in d_ents if e in reach) / len(d_ents) scores[doc_id] = alpha * vec + (1 - alpha) * hop_bonus return sorted(scores.items(), key=lambda x: x[1], reverse=True) if __name__ == "__main__": query = "Who might cooperate with Carol on GadgetX?" print("Query:", query) for doc_id, score in hybrid_retrieve(query): print(f" {doc_id}: {score:.3f}")
return set(name for name, pat in ENTITY_RE.items() if re.search(pat, text))用正则从文本中找出出现的实体名,相当于侦探给卷宗贴标签g.setdefault(s, []).append(o)把三元组转换成无向图邻接表,正反两个方向都建边common / (len(query_tokens) ** 0.5 * len(doc_tokens) ** 0.5)用余弦公式计算查询与文档的语义相似度reach.setdefault(node, min(reach.get(node, 99), depth))记录每个可达实体的最短跳数,多起点取最小值hop_bonus = sum(1.0 / (reach[e] + 1) for e in d_ents if e in reach) / len(d_ents)文档实体离查询实体越近,图谱路径加分越高,跳数为 0 时得满分 1.0scores[doc_id] = alpha * vec + (1 - alpha) * hop_bonus向量得分与图谱路径得分按 λ 加权融合,这就是全文的核心公式return sorted(scores.items(), key=lambda x: x[1], reverse=True)按融合总分降序排列,把最相关的文档排到最前
常见误区
误区“我以为 GraphRAG 只要把文档存进 Neo4j 这类图数据库,检索效果就会自动变好,剩下的交给数据库就行。”
正解图数据库只是存储载体,GraphRAG 的核心在于“向量语义召回 + 图谱多跳检索”两条路径的配合设计:实体抽取的准确度、路径得分的计算方式、两路分数的融合权重,每一环都决定最终效果。就像侦探把档案钉上墙只是第一步,怎么连线、怎么顺着线走才是真正的功夫。
为何常见:图数据库的标签和“知识图谱”概念相近,容易被误当作整套解决方案本身,而忽略了检索流程的工程细节。
误区“既然图谱能发现间接关系,那把检索全部换成图谱遍历就行了,向量那套可以淘汰。”
正解知识图谱是稀疏的显式结构,覆盖面远不如稠密的向量空间。用户问题措辞灵活多变,实体抽取一旦失败,图谱路径就无从谈起;而向量检索对语义近似和模糊表达更鲁棒。两者是互补关系,不是替代关系——向量负责宽召回,图谱负责深关联。
为何常见:看到 GraphRAG 对比实验大幅领先,容易想当然地以为领先全部来自图谱单点能力,忽略了它是在向量基础上叠加而来的。
误区“既然多跳能发现间接关系,那就把跳数设大一点,比如 5 跳 6 跳,找得更全。”
正解每多走一跳,信息被稀释一次,无关联的“路过节点”越来越多,噪声累积会让结果发散,甚至把毫不相关的文档拖进候选。实践中常用 2 到 3 跳,并配合社区摘要提供更高层的全局信息。侦探顺藤摸瓜,也会在藤蔓分叉过密时停下,先看圈子档案。
为何常见:直觉上“走得越远知道越多”,忽略了图传播的衰减效应和噪声放大效应。
误区“社区摘要生成一次就能一直用,文档更新了也没关系,反正图是离线构建的。”
正解文档更新、实体关系变化都会让社区结构发生漂移,旧摘要会失真。生产系统需要按变更频率对社区重新检测,并增量刷新摘要。就像办案圈子的成员会跳槽、会失联,圈子档案必须定期更新才有参考价值。
为何常见:离线构建的图看起来是静态快照,容易忽略真实知识库持续演化的特点。
面试题
Q1. GraphRAG 相比纯向量检索最核心的增量能力是什么?
- A.关键词精确匹配能力增强
- B.多跳推理捕获间接实体关联← 正确答案
- C.减少文档向量化计算开销
- D.提高单文档内部语义理解
答案:B。GraphRAG 的关键增量是在知识图谱上进行多跳推理,能发现跨文档的间接实体关联,这是纯向量检索看不到的。关键词精确匹配是倒排索引的强项;向量化计算开销并未因此减少;单文档内部理解也不是图谱引入的主要目的。
Q2. 知识图谱三元组的标准形式是?
- A.(实体,关系,实体)← 正确答案
- B.(文档,段落,句子)
- C.(问题,答案,得分)
- D.(主语,谓语,文本)
答案:A。三元组由头实体、关系、尾实体组成,记作 (h, r, t),例如“王总 创立 环宇科技”。选项 B 是文档层级结构,C 是问答记录,D 中“文本”不是实体,都不符合知识图谱的存储单元定义。
Q3. 为什么向量检索与图谱检索的分数不能直接相加?
- A.两路分数量纲和分布不同需要归一化← 正确答案
- B.相加会导致候选文档数量翻倍
- C.图谱得分总是大于向量得分
- D.向量得分无法离线预先计算
答案:A。余弦相似度与图谱路径得分的取值范围、分布形态都不同,直接相加会让某一路天然占据主导,产生偏置,必须先归一化到同一尺度。B 错在融合并不增加候选数量;C 是绝对化说法;D 与事实相反,向量得分恰恰可以离线预计算。
Q4. 多跳推理中限制跳数的主要原因是?
- A.跳数越多计算开销反而更低
- B.远距离传播会让噪声累积发散← 正确答案
- C.实体抽取的精度会随跳数提升
- D.图数据库无法存储多跳路径
答案:B。每多一跳,无关节点混入候选的概率增加,信息在传播中被稀释,噪声累积导致结果发散,所以通常限制在 2 到 3 跳。A、C 与事实相反;D 错在图数据库天然支持多跳查询,存储不是瓶颈。
Q5. 社区摘要最主要的作用是?
- A.压缩向量索引的存储空间
- B.为检索提供全局上下文覆盖← 正确答案
- C.替代实体关系抽取全过程
- D.提升图谱遍历的计算速度
答案:B。社区摘要用大语言模型为每个密集圈子生成背景总结,回答问题时先看摘要获得全局视野,再下钻具体文档,提升上下文覆盖。它不是存储优化手段,不能替代实体关系抽取,也与遍历计算速度无关。
Q6. RRF 公式中的平滑常数 k 主要作用是?
- A.减少没有候选文档时的报错
- B.防止排名 1 时分数过高的爆炸← 正确答案
- C.让向量得分可以变成负数
- D.将图谱边数归一化到零一
答案:B。k 使分母至少为 k+1,当文档排名为 1 时分数不会过大,起到平滑头部优势的作用。A 是工程异常处理,C 与语义得分的性质无关,D 描述的是 min-max 归一化,都与 k 无关。
Q7. 融合两路检索结果时,某候选仅在向量路排名第 1、图谱路完全未命中,以下哪种处理最合理?
- A.选择直接丢弃该候选
- B.保留并按融合规则给分← 正确答案
- C.强制补充一条图谱路径
- D.令图谱得分等于向量得分
答案:B。融合的目的正是让两路互相补位,单路命中的候选应当保留,但其得分受融合规则(如 RRF 倒数求和)影响,单路高分不会自动获得极高总分。直接丢弃会损失召回;强行补路径或令两路相等都是在伪造数据,违背检索的客观性。
Q8. 知识图谱构建阶段包括哪些关键步骤?
- A.从文档中识别命名实体← 正确答案
- B.抽取实体之间的语义关系← 正确答案
- C.将结果存为三元组形式← 正确答案
- D.对所有文档做向量聚类
答案:ABC。构建图谱的三步是实体识别、关系抽取、三元组存储,对应“贴标签—画红线—落盘”。向量聚类是索引层面的技术,服务于向量召回,不属于知识图谱构建步骤。
Q9. 以下哪些场景更适合使用 GraphRAG?
- A.跨多份文档才能拼出完整答案← 正确答案
- B.答案依赖实体间的间接关联← 正确答案
- C.只需要单篇文档摘要生成
- D.需要组织结构图谱上的推理← 正确答案
答案:ABD。GraphRAG 擅长跨文档关联、间接关系捕获和图谱推理,因此 A、B、D 都符合。单篇文档摘要用普通 RAG 或直接调用大模型即可完成,无需构建知识图谱,属于过度设计。
Q10. 关于图谱向量融合中权重 λ 的行为,描述正确的有?
- A.λ 越大图谱路径得分权重越大
- B.λ 等于 1 时等价于纯向量检索← 正确答案
- C.λ 需要根据数据集调优← 正确答案
- D.λ 等于 0 时忽略向量相似度← 正确答案
答案:BCD。融合公式为 Score = λ·cos + (1-λ)·Path。λ=1 时图谱权重为 0,等价纯向量检索;λ=0 时向量权重为 0,完全忽略语义相似度。λ 是超参数,需按数据集验证调优。A 说反了——λ 越大图谱权重反而越小。