Skip to content
🔗 分享本题
查看我的学习进度 →

GraphRAG 与向量 RAG 对比动漫知识图:向量检索语义相似内容,图谱支持实体关系遍历、社区总结和多跳推理,复杂场景可混合

记忆点:相似内容用向量,关系推理看图谱;GraphRAG 并非总是更优。

💡 答案要点

GraphRAG = 知识图谱 + RAG,用实体关系图做检索而非纯向量相似度

核心区别

维度向量RAGGraphRAG
数据组织文本切块→向量实体+关系→图节点/边
检索方式语义相似度(近似邻居)图遍历/Cypher查询
多跳推理❌ 难以关联多个文档✅ 沿关系路径自然推理
可解释性低(黑盒相似度)高(关系路径可追踪)
构建成本高(需要NER+关系抽取)
适用场景语义搜索、文档问答复杂关系推理、知识密集

GraphRAG实现流程

Step 1:知识图谱构建

展开 Python 代码示例(60 行)
python
from neo4j import GraphDatabase
import spacy

class KnowledgeGraphBuilder:
    def __init__(self, neo4j_uri, user, password):
        self.driver = GraphDatabase.driver(neo4j_uri, auth=(user, password))
        self.nlp = spacy.load("zh_core_web_sm")

    def extract_entities_relations(self, text: str):
        """用LLM抽取实体和关系"""
        prompt = f"""
        从以下文本中提取实体和关系,以JSON格式输出:

        文本:{text}

        输出格式:
        {{
            "entities": [
                {{"name": "实体名", "type": "Person/Organization/Product/Location"}}
            ],
            "relations": [
                {{"source": "实体A", "relation": "关系类型", "target": "实体B"}}
            ]
        }}
        """
        result = llm.generate(prompt, temperature=0)
        return json.loads(result)

    def build_graph(self, documents: list):
        """将文档转化为知识图谱"""
        with self.driver.session() as session:
            for doc in documents:
                data = self.extract_entities_relations(doc)

                # 创建实体节点
                for entity in data["entities"]:
                    session.run(
                        "MERGE (e:Entity {name: $name}) SET e.type = $type",
                        name=entity["name"], type=entity["type"]
                    )

                # 创建关系边
                for rel in data["relations"]:
                    session.run("""
                        MATCH (a:Entity {name: $source})
                        MATCH (b:Entity {name: $target})
                        MERGE (a)-[r:RELATION {type: $rel_type}]->(b)
                    """, source=rel["source"],
                         target=rel["target"],
                         rel_type=rel["relation"])

# 示例:构建公司知识图谱
builder = KnowledgeGraphBuilder("bolt://localhost:7687", "neo4j", "password")

docs = [
    "张三是阿里巴巴的CTO,负责技术战略",
    "阿里巴巴旗下有淘宝、天猫、支付宝等产品",
    "支付宝由彭蕾创立,现由韩歆毅担任CEO",
]
builder.build_graph(docs)

Step 2:图检索查询

展开 Python 代码示例(56 行)
python
class GraphRAGRetriever:
    def __init__(self, driver, llm):
        self.driver = driver
        self.llm = llm

    def query_to_cypher(self, user_query: str) -> str:
        """将自然语言查询转为Cypher图查询"""
        prompt = f"""
        将以下问题转为Neo4j Cypher查询语句:

        问题:{user_query}

        图结构:节点(Entity)有name和type属性,关系(RELATION)有type属性

        只输出Cypher语句,不加解释:
        """
        return self.llm.generate(prompt, temperature=0).strip()

    def retrieve(self, user_query: str) -> list:
        """图检索 + 向量检索混合"""
        results = []

        # 1. 图检索:精确关系查询
        try:
            cypher = self.query_to_cypher(user_query)
            with self.driver.session() as session:
                graph_results = session.run(cypher).data()
                results.extend(graph_results)
        except Exception as e:
            print(f"图查询失败,降级到向量检索:{e}")

        # 2. 向量检索:语义相似度补充
        vector_results = vectordb.search(user_query, k=3)
        results.extend(vector_results)

        return results

    def multi_hop_reasoning(self, query: str, max_hops=3) -> str:
        """多跳推理:沿图关系路径推理"""
        # 提取问题中的实体
        entities = self.extract_entities(query)

        reasoning_chain = []
        for entity in entities:
            # 从实体出发,遍历K跳邻居
            cypher = f"""
            MATCH path = (start:Entity {{name: '{entity}'}})-[*1..{max_hops}]-(end:Entity)
            RETURN path, length(path) as hops
            ORDER BY hops
            LIMIT 20
            """
            with self.driver.session() as session:
                paths = session.run(cypher).data()
                reasoning_chain.extend(paths)

        return reasoning_chain

Step 3:结合LLM生成

python
def graphrag_answer(user_query: str):
    retriever = GraphRAGRetriever(driver, llm)

    # 1. 多跳图检索
    graph_context = retriever.multi_hop_reasoning(user_query, max_hops=2)

    # 2. 格式化图上下文
    graph_text = format_graph_paths(graph_context)

    # 3. LLM生成
    prompt = f"""
    基于以下知识图谱信息回答问题:

    图谱信息(实体关系路径):
    {graph_text}

    问题:{user_query}

    请基于上述关系链条进行推理并回答:
    """

    return llm.generate(prompt)

# 示例
answer = graphrag_answer("支付宝的创始人和阿里巴巴CTO是什么关系?")
# 推理路径:彭蕾 → 创立 → 支付宝 → 归属 → 阿里巴巴 ← 任职 → 张三(CTO)
# 回答:"彭蕾创立了支付宝,支付宝隶属于阿里巴巴,张三是阿里巴巴的CTO,所以彭蕾和张三都服务于阿里巴巴体系..."

选型建议

问自己3个问题:

1. 问题需要多跳推理吗?
   例:"A的老板的老板是谁?" → 需要 → 选GraphRAG

2. 实体间关系是核心信息吗?
   例:医药、法律、供应链 → 是 → 选GraphRAG

3. 数据是自由文本为主吗?
   例:文章、客服记录 → 是 → 选向量RAG

推荐:生产环境用混合方案(向量召回 + 图精排)

面试话术:

"GraphRAG用知识图谱替代纯向量存储,核心优势是多跳推理和可解释性。实现分3步:LLM抽取实体关系建图、自然语言转Cypher图查询、沿关系路径推理生成答案。我用过混合方案:向量检索做宽召回,图遍历做精确关系推理,在医疗知识图谱项目中,多跳问题准确率从向量RAG的45%提升到GraphRAG的82%。代价是构建成本高,需要NER+关系抽取流程。"