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. 核心架构
- 知识抽取 (Extraction):利用 LLM 从非结构化文本中提取实体(Entities)和关系(Relationships)。
- 图存储 (Graph Storage):将提取的三元组存入图数据库(如 Neo4j)。
- 图检索 (Graph Retrieval):将用户问题转化为 Cypher 查询语句,或检索实体的子图(Sub-graph)。
- 混合生成: 将检索到的子图信息 + 向量检索的文本片段,一起喂给 LLM。
3. Golang 操作 Neo4j
我们将使用 Neo4j 的官方 Go 驱动 github.com/neo4j/neo4j-go-driver。
3.1 安装驱动
bash
go get github.com/neo4j/neo4j-go-driver/v53.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 的创始人是谁?":
- 关键词提取:提取出 "SpaceX"。
- 子图检索:在 Neo4j 中查
MATCH (n {name: 'SpaceX'})-[*1..2]-(m) RETURN n, m。 - 构建 Context:将查到的关系描述成自然语言("SpaceX FOUNDED_BY Elon Musk")。
- LLM 生成:结合 Context 回答。
5. 总结
Graph RAG 提升了系统对复杂逻辑的理解能力。 在 Golang 生态中,我们可以灵活组合 LangChainGo (LLM 调用) 和 Neo4j Go Driver (图存储) 来构建强大的图谱增强应用。
