Skip to content

Graph RAG:基于知识图谱的 RAG

Graph RAG 是 RAG 技术的前沿方向。它结合了知识图谱 (Knowledge Graph) 的结构化推理能力和 LLM 的生成能力,解决了传统向量检索难以处理的“多跳推理”和“全局关系”问题。

1. 为什么需要 Graph RAG?

传统 RAG(基于向量)的局限:

  • 关系丢失:向量把文本打散了,丢失了实体间的显式关系(如 A 是 B 的父亲)。
  • 多跳推理弱:问“A 的父亲的公司的 CEO 是谁?”,向量检索很难一次性找对链条。

Graph RAG 的优势:

  • 显式关系:直接在图数据库中存储 (Entity A)-[RELATION]->(Entity B)
  • 精准推理:通过图遍历算法(如最短路径)找到答案。

2. 核心架构

  1. 知识抽取 (Extraction):利用 LLM 从非结构化文本中提取实体(Entities)和关系(Relationships)。
  2. 图存储 (Graph Storage):将提取的三元组存入图数据库(如 Neo4j)。
  3. 图检索 (Graph Retrieval):将用户问题转化为 Cypher 查询语句,或检索实体的子图(Sub-graph)。
  4. 混合生成: 将检索到的子图信息 + 向量检索的文本片段,一起喂给 LLM。

3. Golang 操作 Neo4j

我们将使用 Neo4j 的官方 Go 驱动 github.com/neo4j/neo4j-go-driver

3.1 安装驱动

bash
go get github.com/neo4j/neo4j-go-driver/v5

3.2 连接 Neo4j 并查询

go
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/neo4j/neo4j-go-driver/v5/neo4j"
)

func main() {
	ctx := context.Background()
	
	// 1. 连接数据库
	dbUri := "neo4j://localhost:7687"
	dbUser := "neo4j"
	dbPassword := "password"
	
	driver, err := neo4j.NewDriverWithContext(
		dbUri,
		neo4j.BasicAuth(dbUser, dbPassword, ""),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer driver.Close(ctx)

	// 2. 执行查询 (Cypher)
	// 假设我们要查询 "Elon Musk" 关联的公司
	cypher := `
		MATCH (p:Person {name: $name})-[r:FOUNDED]->(c:Company)
		RETURN c.name AS company
	`
	
	session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeRead})
	defer session.Close(ctx)

	result, err := session.Run(ctx, cypher, map[string]any{"name": "Elon Musk"})
	if err != nil {
		log.Fatal(err)
	}

	// 3. 处理结果
	var companies []string
	for result.Next(ctx) {
		record := result.Record()
		company, _ := record.Get("company")
		companies = append(companies, company.(string))
	}

	fmt.Printf("Elon Musk 创立的公司: %v\n", companies)
}

4. 实战:构建 Graph RAG 流程

步骤 1:利用 LLM 提取三元组

我们需要写一个 Prompt,让 LLM 把句子变成 JSON。

go
const extractPrompt = `
请从以下文本中提取实体和关系,输出 JSON 格式:
[{"head": "实体A", "relation": "关系", "tail": "实体B"}, ...]

文本:Elon Musk 创立了 SpaceX。SpaceX 位于美国。
`
// LLM Output: 
// [{"head": "Elon Musk", "relation": "FOUNDED", "tail": "SpaceX"}, 
//  {"head": "SpaceX", "relation": "LOCATED_IN", "tail": "USA"}]

步骤 2:写入 Neo4j

go
func InsertTriplets(ctx context.Context, driver neo4j.DriverWithContext, triplets []Triplet) {
	session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
	defer session.Close(ctx)

	for _, t := range triplets {
		cypher := `
			MERGE (h:Entity {name: $head})
			MERGE (t:Entity {name: $tail})
			MERGE (h)-[:RELATION {type: $rel}]->(t)
		`
		session.Run(ctx, cypher, map[string]any{
			"head": t.Head,
			"tail": t.Tail,
			"rel":  t.Relation,
		})
	}
}

步骤 3:检索增强

当用户问 "SpaceX 的创始人是谁?":

  1. 关键词提取:提取出 "SpaceX"。
  2. 子图检索:在 Neo4j 中查 MATCH (n {name: 'SpaceX'})-[*1..2]-(m) RETURN n, m
  3. 构建 Context:将查到的关系描述成自然语言("SpaceX FOUNDED_BY Elon Musk")。
  4. LLM 生成:结合 Context 回答。

5. 总结

Graph RAG 提升了系统对复杂逻辑的理解能力。 在 Golang 生态中,我们可以灵活组合 LangChainGo (LLM 调用) 和 Neo4j Go Driver (图存储) 来构建强大的图谱增强应用。

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。

了解训练营详情