AI图RAG实践笔记
向量检索找的是"像不像",图检索找的是"连没连"——两类问题,两套工具。
在做知识库项目的时候,一直有个痛点:传统的向量检索虽然好用,但在处理复杂关联问题时总是不够灵活。比如用户问"哪些项目同时涉及前后端和数据库技术",简单的相似度检索很难理解这种"同时涉及"的逻辑关系。
我试过很多方法——换 embedding、调检索策略、手动打标签——效果都不太理想,直到接触了 Graph RAG。下面记录把图结构引入检索系统的全过程,坑和结果都写在里面。
背景:什么是图 RAG
简单来说,Graph RAG 就是把知识库的实体和关系用图的方式组织起来,然后在检索时利用图的结构信息。
传统的 RAG 是这样的:
而 Graph RAG 是这样的:
区别在于:前者是"找相似的内容",后者是"找相关联的内容"。
我的需求
基于项目的实际情况,我需要解决几个具体问题:
- 多实体关联查询:用户经常问"项目 A 和项目 B 有什么共同的技术栈"
- 层级关系查询:比如"某个分类下的所有子分类"
- 路径推理:比如"从技术 A 到技术 B 的推荐路径"
- 上下文聚合:把相关的文档按关系聚合起来,而不是简单的列表
这些需求用向量检索都不太合适,而图结构正好能解决。
实现过程
知识图谱构建
先要构建一个知识图谱。我的方案是从文档中提取实体和关系:
# 实体和关系提取
def extract_entities_and_relations(document):
entities = {
'projects': [],
'technologies': [],
'categories': []
}
relations = []
# 使用 NER 提取项目名
# 使用关键词匹配提取技术栈
# 从标题和分类提取分类信息
# 构建关系
for project in entities['projects']:
for tech in entities['technologies']:
if tech in document['content']:
relations.append({
'from': project,
'to': tech,
'type': 'uses'
})
return entities, relations
这一步遇到的问题是实体识别不够准确,特别是项目名和技术名的区分。最后我加了个项目名白名单,效果好多了。
构建出来的图谱大概是这样:
这样就能清楚看到项目和技术之间的使用关系,以及技术本身的分类关系。
图数据库选型
我测试了几个图数据库:
- Neo4j:功能强大,但部署太重
- NetworkX:纯 Python,简单但性能有限
- Memgraph:中间路线,性能和易用性平衡
最后选了 Memgraph,主要是部署简单,而且 Cypher 查询语言比较友好。
# 连接图数据库
from neo4j import GraphDatabase
class GraphRAG:
def __init__(self, uri, user, password):
self.driver = GraphDatabase.driver(uri, auth=(user, password))
def create_graph(self, documents):
for doc in documents:
entities, relations = extract_entities_and_relations(doc)
self._create_nodes(entities)
self._create_relations(relations)
混合检索策略
我做了个混合策略:先向量检索找候选文档,再用图检索扩展相关的实体和关系。
def hybrid_search(query, top_k=10):
# 向量检索找初始候选
vector_results = vector_search(query, top_k=top_k)
# 从结果中提取实体
entities = extract_entities_from_results(vector_results)
# 图检索扩展
graph_results = graph_search(entities)
# 合并去重
combined = merge_results(vector_results, graph_results)
return combined
这样既能保证基本的相关性,又能利用图的结构信息。
关系聚合
用户拿到结果后,除了文档列表,还需要看关系结构。我加了个简单的可视化:
def visualize_results(results):
# 用 NetworkX 构建子图
G = nx.DiGraph()
for node in results['nodes']:
G.add_node(node['id'], **node['data'])
for edge in results['edges']:
G.add_edge(edge['from'], edge['to'], **edge['data'])
# 绘图
plt.figure(figsize=(12, 8))
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_color='lightblue')
plt.show()
踩坑记录
这一段没有少踩坑,我把主要问题整理了下:
每个问题都是实际遇到过的,而且都要调试好几次才找到合适的方案。
问题 1:实体识别准确率低
最开始用通用的 NER 模型,结果把普通词都识别成项目名。比如"项目推进"的"项目"也被识别了。
解决方案:
- 建立项目名白名单
- 用特定领域的模型
- 加了后处理规则
问题 2:图数据库查询慢
一开始图上有个 10 万节点,查询要几秒。用户受不了。
解决方案:
- 做了索引优化
- 限制子图大小
- 加了缓存层
// 索引优化
CREATE INDEX ON :Project(id);
CREATE INDEX ON :Technology(name);
CREATE INDEX ON (p:Project)-[:USES]->(t:Technology) WHERE t.name IN ['Python', 'JavaScript'];
问题 3:结果相关性下降
加了图检索后,有时候结果不太相关,因为图关系扩展太宽了。
解决方案:
- 限制关系扩展深度
- 按关系权重过滤
- 加上向量检索的分数加权
def score_hybrid_results(vector_score, graph_score, weights=(0.7, 0.3)):
return weights[0] * vector_score + weights[1] * graph_score
问题 4:可视化太复杂
子图大了之后,可视化一团乱,看不清关系。
解决方案:
- 只显示关键节点
- 用颜色区分节点类型
- 加了交互功能
结果对比
做了个简单的对比测试,用 Python 画了下数据对比:
import matplotlib.pyplot as plt
import numpy as np
# 数据
metrics = ['准确率', '用户满意度']
vector = [72, 3.2]
hybrid = [85, 4.1]
# 绘图
x = np.arange(len(metrics))
width = 0.35
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
# 准确率对比
bars1 = ax1.bar(x - width/2, vector, width, label='纯向量检索')
bars2 = ax1.bar(x + width/2, hybrid, width, label='混合检索')
ax1.set_ylabel('分数')
ax1.set_title('准确率对比')
ax1.set_xticks(x)
ax1.set_xticklabels(metrics)
ax1.legend()
# 用户满意度对比
bars3 = ax2.bar([0], vector[1], width, label='纯向量检索')
bars4 = ax2.bar([width], hybrid[1], width, label='混合检索')
ax2.set_ylabel('满意度 (1-5分)')
ax2.set_title('用户满意度对比')
ax2.set_xticks([0, width])
ax2.set_xticklabels(['纯向量检索', '混合检索'])
ax2.legend()
plt.tight_layout()
plt.show()
从图表能更直观地看到提升效果。
| 指标 | 纯向量检索 | 混合检索 | 提升 |
|---|---|---|---|
| 准确率 | 72% | 85% | +13% |
| 响应时间 | 0.3s | 1.2s | -300% |
| 用户满意度 | 3.2/5 | 4.1/5 | +28% |
准确率和满意度都有明显提升,但响应时间变长了。这是预料之中的,毕竟多了图检索的开销。
用户反馈说:“现在能找到之前找不到的关联信息,特别是项目之间的共同技术栈。”
写在后面
Graph RAG 折腾下来,没有银弹。构建和维护知识图谱成本高,不是所有问题都适合图检索,知识更新后图谱也要跟着改。
但它确实补上了传统 RAG 的短板——关联性查询。简单问答继续用向量检索,复杂关联走图检索,我这边是混合策略两边都沾。
如果你也在做知识库,且被"项目 A 和 B 有什么共同技术栈"这类问题卡住,可以从小规模试起,基础功能跑通再引图结构。有问题欢迎交流。
相关文章:
版权声明: 本文首发于 指尖魔法屋-AI图RAG实践笔记(https://blog.thinkmoon.cn/post/372-ai-graph-rag-structure-association-practice/) 转载或引用必须申明原指尖魔法屋来源及源地址!
评论
使用 GitHub 账号登录后即可留言,支持 Markdown。