深夜的警局档案室灯火通明,名侦探老周把连环案的几十份卷宗摊了一桌。财务报告里反复出现“环宇科技”,一位前员工的笔录里提到了创始人“王总”,一份产品手册则写着“智能门锁由环宇旗下子公司研发”。过去,老周破案靠的是那面照片墙:输入嫌疑人的体貌特征,系统按“长得像”的程度返回一张张相似面孔。可这次他很快发现,只看“长得像”远远不够——真正的关键线索,是那个总在受害人身边出现、却和外貌特征毫不沾边的中间人。 只按关键词和语义相似度检索的旧方法,就像只认“长相”的翻相册。它能找到内容相近的文档,却看不见文档里的人物“谁认识谁、谁属于谁”。GraphRAG 给了老周两样新工具:一盒图钉和一卷红线。先把卷宗里的实体全部钉上墙,再用红线标出“发明”“收购”“认识”,织成一张关系网;随后让“按相片找相似”的向量检索和“顺着红线摸”的图谱检索同时出击,前者召回语义相近的粗候选,后者补上多跳路径里的间接关联,最后把两路结果合并、排序、精挑。这张“相片+关系网”的双引擎检索术,就是本文的主角。

岗位关联

掌握图谱与向量融合的检索设计,是构建知识密集型问答与企业级 RAG 系统的核心基本功:当答案藏在线索链深处,只有双引擎检索能把隐而不见的关联捞出来。

目录
  1. 可视化演示
  2. 知识图谱构建
  3. 图谱向量融合
  4. 多跳推理路径
  5. 社区检测摘要
  6. 混合检索架构
  7. 重排优化策略
  8. 应用落地场景
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

通过融合检索、多跳遍历和社区聚类三个模式,展示知识图谱与向量检索如何互补增强RAG的上下文覆盖。

本节配有交互动效(进入视口后自动加载,约 3KB)。

图谱向量融合检索 向量检索:语义相似度匹配,快速定位相关文档块 图谱检索:沿实体关系边多跳推理,发现间接关联 Score = α·cos_sim + β·path_score 两路检索互补:向量覆盖语义盲区,图谱覆盖结构盲区

知识图谱构建

老周的第一步不是急着读卷宗,而是收拾证物板。他给每个卷宗里出现的人名、公司名、产品名贴上标签——“王总”“环宇科技”“智能门锁”,这叫实体识别;接着拿起红色马克笔,在两个标签之间画线并标注关系——“王总 创立 环宇科技”“环宇科技 生产 智能门锁”,这叫关系抽取。几十份卷宗读下来,贴满标签、画满红线的证物板,就变成了一张线索网。

当所有实体和关系被结构化地摆在图上,计算机科学里把这称为知识图谱(Knowledge Graph)。GraphRAG 的第一步正是如此:从文档集合中抽取实体与关系,构建一个可被程序遍历的知识网络。这张图的价值在于,它不再是一堆散落文本,而是“谁和谁相关、怎样相关”的显式表达。

知识图谱的基本存储单元叫三元组(triple):主语(head)、关系(relation)、宾语(tail)。一条“王总 创立 环宇科技”就是典型的“头实体-关系-尾实体”组合。用数学语言描述,整张图就是所有合法三元组的集合:

有了这张证物板,老周告别了“凭印象翻卷宗”的时代。往后每次提问,都能先在图上一眼看清谁和谁直接相连、谁与谁隔了几个人。但光有图还不够——如何把“按相片找相似”的老方法和新图结合起来,是下一节要解决的问题。

G={(h,r,t)∣h∈E, t∈E, r∈R}\displaystyle \mathcal{G} = \{(h, r, t) \mid h \in \mathcal{E},\ t \in \mathcal{E},\ r \in \mathcal{R} \}
这个公式的意思是:一张知识图谱就是一堆“主语-关系-宾语”的合法组合,主语和宾语都必须来自实体集合,关系必须来自关系集合。
  1. 图符号 G表示整张知识图谱,它是全部合法三元组构成的集合
    G\mathcal{G}
  2. 三元组 (h, r, t)一条连线的完整记录,h 是头实体,r 是关系,t 是尾实体
    (h,r,t)(h, r, t)
  3. 实体集合 E图中所有图钉(人物、组织、产品)构成实体集合,h 和 t 必须从这里取
    h∈E, t∈Eh \in \mathcal{E},\ t \in \mathcal{E}
  4. 关系集合 R图中所有红线(创立、生产、认识)构成关系集合,r 必须从这里取
    r∈Rr \in \mathcal{R}

图谱向量融合

老周的办公室里至今留着两套工具。一套是自动人脸识别仪,输入一段描述,就能按“语义长相”从档案库捞回最相似的面孔——这是向量检索;另一套是刚织好的关系网,从一个人出发能顺藤摸瓜找到他认识的人——这是图谱检索。老周发现,单用脸谱仪会漏掉“长得不像但关键”的中间人,单用关系网又会漏掉“长得像但暂无关系”的嫌疑面孔。

GraphRAG 的检索器正是采用这种“两路并行”设计:一路把用户问题编码成向量,与文档向量做余弦相似度匹配,得到语义候选;另一路抽取问题中的实体,在知识图谱上做遍历,得到与实体有直接或间接关联的文档。两路侧重点完全不同:向量擅长宽泛的语义近似,图谱擅长精准的实体关联,二者天然互补——这就是图谱路径补充与互补机制的含义。

最终得分是两路分数的加权融合。设 λ 是向量得分的权重,图谱得分权重就是 (1-λ):

老周把两套工具的结论记在同一本本子上。他明白,真正的高明不在于任何单一路径,而在于让“相片相似”和“关系相近”互相补位——这正是“图谱向量融合”这个名字的由来。

Score(q,d)=λ⋅cos⁡(q,d)+(1−λ)⋅Path(q,d)\displaystyle \text{Score}(q, d) = \lambda \cdot \cos(\mathbf{q}, \mathbf{d}) + (1-\lambda) \cdot \text{Path}(q, d)
文档 d 对问题 q 的总相关度 = 向量相似度乘以权重 λ,加上图谱路径得分乘以权重 (1-λ)。
  1. 检索得分 Score(q,d)文档 d 对问题 q 的总相关度,融合后用于排序
    Score(q,d)\text{Score}(q, d)
  2. 余弦相似度 cos(q,d)向量路的得分,衡量问题与文档语义方向上的接近程度,值越接近 1 越相似
    cos⁡(q,d)\cos(\mathbf{q}, \mathbf{d})
  3. 融合权重 λ取值在 0 到 1 之间,λ 越大越信任向量路,越小越信任图谱路,需要按数据集调优
    λ⋅cos⁡(q,d)\lambda \cdot \cos(\mathbf{q}, \mathbf{d})
  4. 图谱路径得分 Path(q,d)文档实体与问题实体在图上相隔多近,跳数越少分越高
    Path(q,d)\text{Path}(q, d)

多跳推理路径

老周在证物板上发现一条有趣的线:辞职员工小赵 → 认识 财务主管李姐 → 见过 环宇创始人王总。如果只看第一层,小赵和王总毫无交集;多走两步,一条隐藏的上下游关系就浮出水面。侦探行话管这叫“顺藤摸瓜”,图算法里则叫“多跳推理”。

多跳推理的本质是沿图的边逐层扩展:从问题涉及的实体出发,经过一跳找到直接邻居,两跳找到“朋友的朋友”,k 跳就是 k 层间接关联。它最大的价值在于捕获向量检索遗漏的间接关系:向量只比较“长得像不像”,而多跳推理回答的是“隔着几个人能否扯上关系”,这正是跨文档关联的根基。

用消息传递来建模这一过程:每一轮迭代,节点把邻居上一轮的表示取平均,作为自己的新表示,信息就这样沿着边扩散开去:

老周靠这套“走几步”的方法,找到了那根贯穿三份卷宗的红线。但他也清楚,藤蔓拉得太长容易扯到无关的花花草草——通常 2 到 3 跳以内是可靠的,再远噪声就开始累积。

hv(k)=1∣N(v)∣∑u∈N(v)hu(k−1)\displaystyle h_v^{(k)} = \frac{1}{|\mathcal{N}(v)|} \sum_{u \in \mathcal{N}(v)} h_u^{(k-1)}
第 k 轮时节点 v 的表示,是它所有邻居第 k-1 轮表示的算术平均,等价于把邻居信息“传”给了自己。
  1. 节点表示 h_v^(k)第 k 轮迭代后节点 v 携带的信息向量,代表它积累的关联线索
    hv(k)h_v^{(k)}
  2. 邻居集合 N(v)与 v 直接相连的全部节点,是所有信息的来源
    N(v)\mathcal{N}(v)
  3. 求平均运算把邻居们的表示相加再除以邻居个数,完成一次信息汇总传播
    1∣N(v)∣∑u∈N(v)hu(k−1)\frac{1}{|\mathcal{N}(v)|} \sum_{u \in \mathcal{N}(v)} h_u^{(k-1)}
  4. 迭代更新k 从 1 循环到 K,信息沿图扩散 K 跳,捕获 k 层间接关联
    hv(k)←Aggregate(hu(k−1))h_v^{(k)} \leftarrow \text{Aggregate}(h_u^{(k-1)})

社区检测摘要

案件牵涉上百人,关系网密密麻麻,老周盯着墙直皱眉。助手提议:把“平时来往密集”的人分成几个圈子,比如“环宇系高管圈”“离职员工互助圈”“投资方圈”,再给每个圈子写一份两三行的背景摘要。之后回顾案情时,只需先扫一眼圈子摘要,就能立刻知道当前问题属于哪一派势力。

这就是社区检测(Community Detection)的思路:在图里把连接紧密的一组节点划分为一个社区,再借助大语言模型为每个社区生成摘要。社区摘要相当于给检索加了一层“全局视野”:回答问题时先命中社区,再在社区内部定位具体文档,上下文覆盖更完整。

最常用的社区划分算法是鲁汶算法(Louvain),它通过最大化模块度(Modularity)来寻找最优分组。模块度衡量“社区内部连边比例”比“随机连接期望”高出多少:

老周的笔记本上从此多了几页“圈子档案”。遇上跨卷宗的大问题,先翻圈子摘要,再下钻具体文档,思路清晰了不止一倍——这就是社区摘要提供的“上下文覆盖”。

Q=12m∑ij[Aij−kikj2m]δ(ci,cj)\displaystyle Q = \frac{1}{2m} \sum_{ij} \left[ A_{ij} - \frac{k_i k_j}{2m} \right] \delta(c_i, c_j)
Q 越大说明分组越“物以类聚”——社区内部的连接远多于随机情况下的预期。
  1. 模块度 Q衡量社区划分质量的总体指标,越大说明划分越合理
    QQ
  2. 总边数归一化 1/(2m)m 是全图总边数,除以 2m 把结果缩放到可比较的尺度
    12m\frac{1}{2m}
  3. 实际连边 A_ij节点 i 与 j 之间真的有边则为 1,否则为 0
    AijA_{ij}
  4. 随机期望 k_i k_j/(2m)按节点度数随机连接时,i 与 j 之间出现边的概率期望,用于做减法基准
    kikj2m\frac{k_i k_j}{2m}
  5. 同社区指示 δ(c_i,c_j)i 与 j 被分到同一社区时为 1,不同社区为 0,保证只统计社区内部的超额连接
    δ(ci,cj)\delta(c_i, c_j)

混合检索架构

两路探员带队会师。人脸识别组带回一沓“相貌相似”的照片,关系网组带回一沓“关系相近”的名单。问题来了:两边的分数没法直接比较——这边是 0 到 1 的相似度,那边是按跳数折算的亲密度,一个 0.8 一个 0.5 到底谁更相关?老周让秘书把两沓材料分别按自己的标尺“拉平”,再合并成一张总表。

这就是混合检索架构中的分数归一化(Score Normalization)。向量检索的余弦相似度范围受嵌入空间影响,图谱路径得分的尺度则与跳数设置有关,两者不经过归一化直接相加,会引入严重偏置。生产系统中,向量路与图谱路通常并行召回,各自产出候选与分数,再统一处理后融合。

常用 min-max 归一化把每路分数都压到 [0,1]:

归一化就像把两沓不同单位的名册都翻译成统一的“相关度货币”,合并后才有意义。老周的总表上,向量路与图谱路的候选终于站在同一条起跑线上,接下来只剩最后一道工序:排座次。

s^=s−smin⁡smax⁡−smin⁡\displaystyle \hat{s} = \frac{s - s_{\min}}{s_{\max} - s_{\min}}
将一路分数里的最小值映射为 0、最大值映射为 1,其他值线性映射在中间,两路即可公平相加。
  1. 原始分数 s某一路检索引擎(向量或图谱)给出的原始得分
    ss
  2. 最小值 smin 与最大值 smax该路候选集合中得分的最小值和最大值,构成映射区间
    smin⁡, smax⁡s_{\min},\ s_{\max}
  3. 差值 (s - smin)当前分数与最低分的距离,衡量相对位置
    s−smin⁡s - s_{\min}
  4. 归一化结果 ŝ除以极差后映射到 [0,1] 的标准化分数,两路分数从此同尺度可比
    s^\hat{s}

重排优化策略

总表上有几十条候选,老周深吸一口气,开始“排座次”。他不再满足于初筛的大致排序,而是逐一重新审视:与问题关键词直接命中的往前排,绕了三圈才沾边的往后放;同时参考两套引擎给的位次,让在两边都靠前的候选获得更高的最终排名。

这叫重排(Reranking):先由混合检索召回一个较宽的候选集合,再用更精细的打分模型或融合策略重新排序,把最相关的结果顶到最前面。向量路负责初筛宽度,重排负责精度——它是 RAG 系统里决定最终喂给大模型上文质量的关键一环。

倒数排名融合(RRF)是一种不需要调权重的经典融合排序法,它把每个文档在每路结果里的名次取倒数后相加:

老周把“两边都露脸的候选”提到了最前面。重排这一下看似轻巧,却常常是检索质量从“及格”到“优秀”的分水岭——就像破案时,把最像真凶的人放在审讯名单第一位。

RRF(d)=∑i=1M1k+ranki(d)\displaystyle \text{RRF}(d) = \sum_{i=1}^{M} \frac{1}{k + \text{rank}_i(d)}
文档在某一路上排名越靠前,倒数越大;在越多路上靠前,总分越高。k 是平滑常数,通常取 60。
  1. 融合总分 RRF(d)文档 d 在多路检索引擎下的最终排名分
    RRF(d)\text{RRF}(d)
  2. 求和符号 Σ把 M 路检索引擎各自的贡献累加起来,M 是引擎总数
    ∑i=1M\sum_{i=1}^{M}
  3. 排名 rank_i(d)文档 d 在第 i 路结果中的位次,从 1 开始计,位次越小越靠前
    ranki(d)\text{rank}_i(d)
  4. 平滑常数 k避免排名为 1 时分母过小而分数爆炸,同时适度削弱头部优势
    k+ranki(d)k + \text{rank}_i(d)

应用落地场景

这套“相片+关系网”双引擎的破案术,如今被老周写成了标准办案手册。它不是万能钥匙,但在三类案子中格外好使:需要横跨几十份卷宗才能还原真相的连环案、涉及多个部门互相扯皮的企业内部调查、以及整理一年年报时理清公司间收购与隶属关系的分析工作。

这三类场景对应 GraphRAG 的三个典型落地方向:知识密集型问答、企业文档检索、文档分析。它们的共同特征是:答案碎片分布在多个文档中,且必须通过实体之间的关联才能串起来——纯向量检索只能找到碎片,却拼不出全貌。

社区摘要为衡量上下文完整度提供了直观指标——查询覆盖度,即查询涉及的实体中有多大比例出现在命中的社区摘要里:

老周合上手册。侦破连环案的关键从来不是某一页卷宗写得多么详细,而是能否看清卷宗之间那条看不见的红线。GraphRAG 要做的,正是把这条红线从文档里抽出来、铺成网、走过去——让检索不仅“看得懂语义”,更“看得见关系”。

Coverage(C)=∣ Qent∩Cent ∣∣ Qent ∣\displaystyle \text{Coverage}(C) = \frac{|\, Q_{\text{ent}} \cap C_{\text{ent}} \,|}{|\, Q_{\text{ent}} \,|}
覆盖度等于“查询实体与社区摘要实体交集的大小”除以“查询实体总数”,越高说明全局上下文越完整。
  1. 查询实体集 Q_ent从用户问题中抽取出的关键实体,比如“王总”“环宇科技”
    QentQ_{\text{ent}}
  2. 摘要实体集 C_ent社区摘要中提及的实体,代表摘要覆盖到的知识范围
    CentC_{\text{ent}}
  3. 交集大小 |∩|双方共同拥有的实体数量
    ∣ Qent∩Cent ∣|\, Q_{\text{ent}} \cap C_{\text{ent}} \,|
  4. 覆盖率 Coverage比值越接近 1,社区摘要对问题的支撑越充分,检索上下文越完整
    ∣ Qent∩Cent ∣∣ Qent ∣\frac{|\, Q_{\text{ent}} \cap C_{\text{ent}} \,|}{|\, Q_{\text{ent}} \,|}

AI 应用场景

跨文档知识问答

阶段:检索与召回(GraphRAG 双引擎)

解决的问题:传统向量检索只能按语义相似度召回单个文档,当答案需要融合多篇文档中不同实体的关系时(如“环宇科技现任 CEO 是被谁收购的”),会遗漏间接线索;GraphRAG 通过图谱多跳路径把相关文档串起来,再用社区摘要提供背景上下文。

具体案例:某法律科技公司的合同审阅助手,用户问“A 公司去年收购的子公司与 B 公司是否有合资关系”,系统先抽取实体,在图谱上遍历“收购—合资”关系链,召回并融合三份合同中的相关段落,给出带证据链的答案。

企业知识库检索

阶段:索引构建与查询重排

解决的问题:企业知识库文档散落在各部门,员工提问“上线了 X 服务的团队归谁管”,纯向量检索只能找到介绍 X 服务的文档,找不到“负责人”这一关系的源头;GraphRAG 建立组织结构图谱,沿“隶属/负责”边多跳定位到负责人及其汇报线。

具体案例:某大型互联网公司的内部问答机器人,通过 GraphRAG 将组织架构、项目归属、服务依赖关系建图,员工提问“这个服务挂了该找谁”的定位准确率提升了 35%,平均响应时间缩短一半。

科研文献综述

阶段:实体抽取与社区摘要

解决的问题:综述写作需要理清“某方法被哪些工作改进、又启发了哪些后续研究”的引用网络,向量检索只能按主题相近返回文献,无法表达“谁引用谁”的传承关系。

具体案例:学术助手根据论文引用关系构建引文图谱,按社区把研究流派分组,为每个流派生成摘要,研究者提问“这个方向的开山之作有哪些后续变体”时,系统沿引用边多跳召回并汇总流派脉络。

Python 演示

python87 行
# -*- 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}")
目的:用迷你知识图谱演示 GraphRAG 双引擎检索——向量相似度负责语义召回,图谱多跳遍历负责发现间接关联,两者加权融合后排序,展示“向量找不到的答案,图谱能补上”。
  1. return set(name for name, pat in ENTITY_RE.items() if re.search(pat, text))用正则从文本中找出出现的实体名,相当于侦探给卷宗贴标签
  2. g.setdefault(s, []).append(o)把三元组转换成无向图邻接表,正反两个方向都建边
  3. common / (len(query_tokens) ** 0.5 * len(doc_tokens) ** 0.5)用余弦公式计算查询与文档的语义相似度
  4. reach.setdefault(node, min(reach.get(node, 99), depth))记录每个可达实体的最短跳数,多起点取最小值
  5. hop_bonus = sum(1.0 / (reach[e] + 1) for e in d_ents if e in reach) / len(d_ents)文档实体离查询实体越近,图谱路径加分越高,跳数为 0 时得满分 1.0
  6. scores[doc_id] = alpha * vec + (1 - alpha) * hop_bonus向量得分与图谱路径得分按 λ 加权融合,这就是全文的核心公式
  7. return sorted(scores.items(), key=lambda x: x[1], reverse=True)按融合总分降序排列,把最相关的文档排到最前

常见误区

误区“我以为 GraphRAG 只要把文档存进 Neo4j 这类图数据库,检索效果就会自动变好,剩下的交给数据库就行。”

正解图数据库只是存储载体,GraphRAG 的核心在于“向量语义召回 + 图谱多跳检索”两条路径的配合设计:实体抽取的准确度、路径得分的计算方式、两路分数的融合权重,每一环都决定最终效果。就像侦探把档案钉上墙只是第一步,怎么连线、怎么顺着线走才是真正的功夫。

为何常见:图数据库的标签和“知识图谱”概念相近,容易被误当作整套解决方案本身,而忽略了检索流程的工程细节。

误区“既然图谱能发现间接关系,那把检索全部换成图谱遍历就行了,向量那套可以淘汰。”

正解知识图谱是稀疏的显式结构,覆盖面远不如稠密的向量空间。用户问题措辞灵活多变,实体抽取一旦失败,图谱路径就无从谈起;而向量检索对语义近似和模糊表达更鲁棒。两者是互补关系,不是替代关系——向量负责宽召回,图谱负责深关联。

为何常见:看到 GraphRAG 对比实验大幅领先,容易想当然地以为领先全部来自图谱单点能力,忽略了它是在向量基础上叠加而来的。

误区“既然多跳能发现间接关系,那就把跳数设大一点,比如 5 跳 6 跳,找得更全。”

正解每多走一跳,信息被稀释一次,无关联的“路过节点”越来越多,噪声累积会让结果发散,甚至把毫不相关的文档拖进候选。实践中常用 2 到 3 跳,并配合社区摘要提供更高层的全局信息。侦探顺藤摸瓜,也会在藤蔓分叉过密时停下,先看圈子档案。

为何常见:直觉上“走得越远知道越多”,忽略了图传播的衰减效应和噪声放大效应。

误区“社区摘要生成一次就能一直用,文档更新了也没关系,反正图是离线构建的。”

正解文档更新、实体关系变化都会让社区结构发生漂移,旧摘要会失真。生产系统需要按变更频率对社区重新检测,并增量刷新摘要。就像办案圈子的成员会跳槽、会失联,圈子档案必须定期更新才有参考价值。

为何常见:离线构建的图看起来是静态快照,容易忽略真实知识库持续演化的特点。

面试题

Q1. GraphRAG 相比纯向量检索最核心的增量能力是什么?

单选题 · easy

  • A.关键词精确匹配能力增强
  • B.多跳推理捕获间接实体关联← 正确答案
  • C.减少文档向量化计算开销
  • D.提高单文档内部语义理解

答案:B。GraphRAG 的关键增量是在知识图谱上进行多跳推理,能发现跨文档的间接实体关联,这是纯向量检索看不到的。关键词精确匹配是倒排索引的强项;向量化计算开销并未因此减少;单文档内部理解也不是图谱引入的主要目的。

Q2. 知识图谱三元组的标准形式是?

单选题 · easy

  • A.(实体,关系,实体)← 正确答案
  • B.(文档,段落,句子)
  • C.(问题,答案,得分)
  • D.(主语,谓语,文本)

答案:A。三元组由头实体、关系、尾实体组成,记作 (h, r, t),例如“王总 创立 环宇科技”。选项 B 是文档层级结构,C 是问答记录,D 中“文本”不是实体,都不符合知识图谱的存储单元定义。

Q3. 为什么向量检索与图谱检索的分数不能直接相加?

单选题 · mid

  • A.两路分数量纲和分布不同需要归一化← 正确答案
  • B.相加会导致候选文档数量翻倍
  • C.图谱得分总是大于向量得分
  • D.向量得分无法离线预先计算

答案:A。余弦相似度与图谱路径得分的取值范围、分布形态都不同,直接相加会让某一路天然占据主导,产生偏置,必须先归一化到同一尺度。B 错在融合并不增加候选数量;C 是绝对化说法;D 与事实相反,向量得分恰恰可以离线预计算。

Q4. 多跳推理中限制跳数的主要原因是?

单选题 · mid

  • A.跳数越多计算开销反而更低
  • B.远距离传播会让噪声累积发散← 正确答案
  • C.实体抽取的精度会随跳数提升
  • D.图数据库无法存储多跳路径

答案:B。每多一跳,无关节点混入候选的概率增加,信息在传播中被稀释,噪声累积导致结果发散,所以通常限制在 2 到 3 跳。A、C 与事实相反;D 错在图数据库天然支持多跳查询,存储不是瓶颈。

Q5. 社区摘要最主要的作用是?

单选题 · mid

  • A.压缩向量索引的存储空间
  • B.为检索提供全局上下文覆盖← 正确答案
  • C.替代实体关系抽取全过程
  • D.提升图谱遍历的计算速度

答案:B。社区摘要用大语言模型为每个密集圈子生成背景总结,回答问题时先看摘要获得全局视野,再下钻具体文档,提升上下文覆盖。它不是存储优化手段,不能替代实体关系抽取,也与遍历计算速度无关。

Q6. RRF 公式中的平滑常数 k 主要作用是?

单选题 · mid

  • A.减少没有候选文档时的报错
  • B.防止排名 1 时分数过高的爆炸← 正确答案
  • C.让向量得分可以变成负数
  • D.将图谱边数归一化到零一

答案:B。k 使分母至少为 k+1,当文档排名为 1 时分数不会过大,起到平滑头部优势的作用。A 是工程异常处理,C 与语义得分的性质无关,D 描述的是 min-max 归一化,都与 k 无关。

Q7. 融合两路检索结果时,某候选仅在向量路排名第 1、图谱路完全未命中,以下哪种处理最合理?

单选题 · extreme

  • A.选择直接丢弃该候选
  • B.保留并按融合规则给分← 正确答案
  • C.强制补充一条图谱路径
  • D.令图谱得分等于向量得分

答案:B。融合的目的正是让两路互相补位,单路命中的候选应当保留,但其得分受融合规则(如 RRF 倒数求和)影响,单路高分不会自动获得极高总分。直接丢弃会损失召回;强行补路径或令两路相等都是在伪造数据,违背检索的客观性。

Q8. 知识图谱构建阶段包括哪些关键步骤?

多选题 · easy

  • A.从文档中识别命名实体← 正确答案
  • B.抽取实体之间的语义关系← 正确答案
  • C.将结果存为三元组形式← 正确答案
  • D.对所有文档做向量聚类

答案:ABC。构建图谱的三步是实体识别、关系抽取、三元组存储,对应“贴标签—画红线—落盘”。向量聚类是索引层面的技术,服务于向量召回,不属于知识图谱构建步骤。

Q9. 以下哪些场景更适合使用 GraphRAG?

多选题 · mid

  • A.跨多份文档才能拼出完整答案← 正确答案
  • B.答案依赖实体间的间接关联← 正确答案
  • C.只需要单篇文档摘要生成
  • D.需要组织结构图谱上的推理← 正确答案

答案:ABD。GraphRAG 擅长跨文档关联、间接关系捕获和图谱推理,因此 A、B、D 都符合。单篇文档摘要用普通 RAG 或直接调用大模型即可完成,无需构建知识图谱,属于过度设计。

Q10. 关于图谱向量融合中权重 λ 的行为,描述正确的有?

多选题 · hard

  • A.λ 越大图谱路径得分权重越大
  • B.λ 等于 1 时等价于纯向量检索← 正确答案
  • C.λ 需要根据数据集调优← 正确答案
  • D.λ 等于 0 时忽略向量相似度← 正确答案

答案:BCD。融合公式为 Score = λ·cos + (1-λ)·Path。λ=1 时图谱权重为 0,等价纯向量检索;λ=0 时向量权重为 0,完全忽略语义相似度。λ 是超参数,需按数据集验证调优。A 说反了——λ 越大图谱权重反而越小。