《GraphRAG 工程落地:Neo4j 与向量数据库的“混合双打”架构》

在传统的 RAG 系统中,我们通常只需要一个向量数据库(如 Milvus、Pinecone 或 Chroma)来存储文本块和 Embedding。但在 GraphRAG 中,数据变得极其复杂:既有非结构化的文本块,又有结构化的实体、关系,还有我们上一篇文章生成的“社区摘要”。

单一的数据库已经无法胜任,我们需要一套**“混合双打”**的存储与检索架构。

1. 存储层:各司其职的双库架构

在生产环境中,最主流的方案是图数据库(如 Neo4j) + 向量数据库(如 Milvus/Pinecone)的协同工作。

  • 图数据库(Neo4j):负责“关系”与“结构”
    图数据库是 GraphRAG 的骨架。我们将上一篇文章中提取的实体(Nodes)、关系(Edges)以及社区摘要(Community Summaries)全部存入 Neo4j。

    • 优势:支持 Cypher 查询语言,能够极其高效地进行多跳查询(Multi-hop Traversal)。比如“查找 A 公司的所有供应商,以及这些供应商所在的国家”,图数据库可以在毫秒级完成这种复杂的逻辑推理。
    • 存储内容:实体节点、关系边、社区摘要节点、以及它们之间的层级关系。
  • 向量数据库(Milvus/Pinecone):负责“语义”与“召回”
    向量数据库是 GraphRAG 的触角。我们将原始文档切分后的文本块(Chunks)及其 Embedding 向量存入这里。

    • 优势:擅长处理模糊的语义匹配。当用户输入一个从未在图谱中出现过的口语化表达时,向量检索能迅速找到最相关的原始文本片段。
    • 存储内容:原始文本块、文本块的 Embedding 向量、以及指向图数据库节点的元数据(Metadata)。

关键技巧:通过元数据(Metadata)打通双库
为了让这两个数据库协同工作,我们需要在向量数据库的每个文本块中,存入一个唯一的标识符(如source_doc_idchunk_id)。这个 ID 同时也是图数据库中对应节点的属性。这样,当我们通过向量检索找到一段文本时,就能立刻拿着这个 ID 去 Neo4j 里“顺藤摸瓜”,找到它关联的所有实体和关系。

2. 检索层:从“盲人摸象”到“上帝视角”

有了双库架构,当用户提出问题时,我们不再依赖单一的检索方式,而是采用**混合检索(Hybrid Retrieval)**策略。

一个完整的 GraphRAG 检索流程通常包含以下三个步骤:

Step 1:向量检索(语义召回)
首先,将用户的问题转化为向量,在向量数据库中进行相似度搜索(Similarity Search),召回 Top-K 个最相关的文本块。

  • 目的:确保不遗漏任何与问题字面或语义相关的细节信息,解决“召回率”问题。

Step 2:图谱增强(关系扩展)
拿到 Step 1 召回的文本块后,提取其中的实体 ID,去 Neo4j 中进行图遍历。

  • 目的:补充上下文。比如向量检索只找到了“特斯拉”这个实体,图谱遍历可以帮我们顺带把“马斯克”、“电池供应商”、“股价”等关联信息全部拉取出来,解决“上下文缺失”问题。

Step 3:社区摘要检索(全局概览)
如果用户的问题比较宏观(例如“总结报告”),系统会触发全局搜索模式。此时,检索器会跳过具体的文本块,直接去 Neo4j 中检索与问题最相关的“社区摘要节点”。

  • 目的:提供高度浓缩的宏观视角,避免 LLM 陷入细节泥潭。
3. 代码实战:LangChain 中的混合检索实现

在代码层面,我们可以利用 LangChain 轻松编排这套流程。以下是一个简化的伪代码示例:

fromlangchain_community.vectorstoresimportMilvusfromlangchain_community.graphsimportNeo4jGraph# 1. 初始化双库连接vector_db=Milvus(...)graph=Neo4jGraph(...)defhybrid_retrieval(query):# Step 1: 向量检索# 获取最相关的文本块及其元数据(包含实体ID)docs=vector_db.similarity_search(query,k=5)entity_ids=[doc.metadata['entity_id']fordocindocs]# Step 2: 图谱增强# 使用 Cypher 查询关联的实体和关系cypher_query=""" MATCH (e:Entity) WHERE e.id IN $ids MATCH (e)-[r]->(related) RETURN e.name, type(r), related.name """graph_context=graph.query(cypher_query,params={"ids":entity_ids})# Step 3: 合并上下文# 将文本块细节 + 图谱关系结构 一起喂给 LLMfinal_context=f"文本细节:{docs}\n\n关联关系:{graph_context}"returnfinal_context
4. 进阶优化:Neo4j 的原生混合搜索

值得一提的是,Neo4j 自身也在不断进化。在较新的版本中,Neo4j 已经支持了原生向量索引。这意味着你可以直接在图数据库内部完成“向量检索 + 关键词检索 + 图遍历”的混合操作,而无需额外维护一个独立的向量数据库。

这种“单库混合搜索”方案大大简化了架构复杂度,特别适合中小型项目快速落地。

5. 总结

通过引入“图数据库 + 向量数据库”的混合架构,我们成功打通了 GraphRAG 的任督二脉。向量检索保证了信息的广度,图谱遍历保证了逻辑的深度,而社区摘要则提供了宏观的高度。

至此,从数据清洗、图谱构建、社区摘要到混合检索,我们已经完整走完了 GraphRAG 的核心技术链路。

下一篇,我们将迎来这个系列的收官之作:《GraphRAG 评估与调优:如何量化你的 AI 到底“懂”了多少?》。我们将探讨如何使用 RAGAS 等框架,对这套复杂的系统进行科学的打分与优化。