知识图谱构建基础:实体-关系抽取 + Neo4j 图数据库

一句话:知识图谱是一种用图结构表示知识和实体之间关系的技术。Neo4j是流行的图数据库,用于存储和查询知识图谱。在AI应用中,知识图谱可以增强RAG的检索能力。

1. 知识图谱基础

1.1 什么是知识图谱?


graph LR

    A[知识图谱] --> B[实体 Entity]

    A --> C[关系 Relation]

    A --> D[属性 Attribute]

    B --> B1[人物]

    B --> B2[地点]

    B --> B3[事件]

    C --> C1[工作于]

    C --> C2[位于]

    C --> C3[参与]

    style A fill:#e1f5fe

知识图谱:一种用图结构表示知识的技术,其中节点表示实体,边表示实体之间的关系。

核心元素

  • 实体(Entity):现实世界中的对象,如人物、地点、组织

  • 关系(Relation):实体之间的连接,如“工作于”、“位于”

  • 属性(Attribute):实体或关系的特征,如“姓名”、“创建时间”

1.2 知识图谱 vs 传统数据库

特性传统关系数据库知识图谱
数据模型表、行、列节点、边、属性
关系处理外键、JOIN直接遍历
查询语言SQLCypher、SPARQL
适用场景结构化数据复杂关系数据

2. 实体-关系抽取

2.1 什么是实体-关系抽取?


graph TD

    A[原始文本] --> B[命名实体识别 NER]

    B --> C[实体抽取]

    A --> D[关系抽取]

    C --> E[实体列表]

    D --> F[关系列表]

    E --> G[知识图谱]

    F --> G

    style A fill:#e8f5e8

实体-关系抽取:从非结构化文本中自动识别实体和它们之间的关系。

2.2 实体类型

实体类型说明示例
PERSON人物张三、李四
ORG组织腾讯、阿里巴巴
LOC地点北京、上海
TIME时间2026年、今天
EVENT事件求职、

2.3 关系类型

关系类型说明示例
WORKS_AT工作于张三 工作于 腾讯
LOCATED_IN位于北京 位于 中国
PARTICIPATED_IN参与张三 参与 求职
CREATED创建张三 创建 项目

2.4 抽取方法

 
# 使用spaCy进行实体抽取
 
import spacy
 
nlp = spacy.load("zh_core_web_sm")
 
text = "张三是腾讯的工程师,他在北京工作。"
 
doc = nlp(text)
 
# 提取实体
 
for ent in doc.ents:
 
    print(f"实体: {ent.text}, 类型: {ent.label_}")
 
# 实体: 北京, 类型: LOC
 

3. Neo4j 图数据库

3.1 什么是Neo4j?


graph TD

    A[Neo4j] --> B[节点 Node]

    A --> C[关系 Relationship]

    A --> D[属性 Property]

    A --> E[Cypher查询语言]

    B --> B1[标签 Label]

    B --> B2[属性 Properties]

    C --> C1[类型 Type]

    C --> C2[方向 Direction]

    C --> C3[属性 Properties]

    style A fill:#e1f5fe

Neo4j:一种基于图的NoSQL数据库,使用节点、关系和属性来存储数据。

3.2 安装和使用

 
# Docker安装Neo4j
 
docker run -d \
 
  --name neo4j \
 
  -p 7474:7474 -p 7687:7687 \
 
  -e NEO4J_AUTH=neo4j/password \
 
  neo4j:latest
 
# Python驱动安装
 
pip install neo4j
 

3.3 基础操作

 
from neo4j import GraphDatabase
 
# 连接Neo4j
 
driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password"))
 
# 创建节点
 
def create_person(tx, name, age):
 
    tx.run("CREATE (p:Person {name: $name, age: $age})", name=name, age=age)
 
# 创建关系
 
def create_works_at(tx, person_name, company_name):
 
    tx.run("""
 
        MATCH (p:Person {name: $person_name})
 
        MATCH (c:Company {name: $company_name})
 
        CREATE (p)-[:WORKS_AT]->(c)
 
    """, person_name=person_name, company_name=company_name)
 
# 查询
 
def find_person(tx, name):
 
    result = tx.run("MATCH (p:Person {name: $name}) RETURN p", name=name)
 
    return result.single()
 
# 使用
 
with driver.session() as session:
 
    session.write_transaction(create_person, "张三", 30)
 
    session.write_transaction(create_person, "腾讯", 25)
 
    session.write_transaction(create_works_at, "张三", "腾讯")
 

4. Cypher查询语言

4.1 基础语法

 
// 创建节点
 
CREATE (p:Person {name: "张三", age: 30})
 
// 创建关系
 
MATCH (p:Person {name: "张三"})
 
MATCH (c:Company {name: "腾讯"})
 
CREATE (p)-[:WORKS_AT]->(c)
 
// 查询
 
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
 
WHERE p.name = "张三"
 
RETURN c.name
 
// 更新
 
MATCH (p:Person {name: "张三"})
 
SET p.age = 31
 
// 删除
 
MATCH (p:Person {name: "张三"})
 
DETACH DELETE p
 

4.2 高级查询

 
// 路径查询:找到张三到李四的所有路径
 
MATCH path = shortestPath(
 
    (a:Person {name: "张三"})-[*]-(b:Person {name: "李四"})
 
)
 
RETURN path
 
// 聚合查询:统计每个公司的员工数
 
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
 
RETURN c.name, COUNT(p) AS employee_count
 
// 模式匹配:找到在腾讯工作且年龄大于25的人
 
MATCH (p:Person)-[:WORKS_AT]->(c:Company {name: "腾讯"})
 
WHERE p.age > 25
 
RETURN p.name, p.age
 

5. 知识图谱构建流程

5.1 构建步骤


graph TD

    A[数据收集] --> B[数据预处理]

    B --> C[实体抽取]

    C --> D[关系抽取]

    D --> E[知识融合]

    E --> F[知识存储]

    F --> G[知识推理]

    style A fill:#e8f5e8

    style G fill:#e1f5fe

5.2 Python实现

 
import spacy
 
from neo4j import GraphDatabase
 
# 1. 实体抽取
 
def extract_entities(text):
 
    nlp = spacy.load("zh_core_web_sm")
 
    doc = nlp(text)
 
    entities = []
 
    for ent in doc.ents:
 
        entities.append({
 
            "text": ent.text,
 
            "label": ent.label_,
 
            "start": ent.start_char,
 
            "end": ent.end_char
 
        })
 
    return entities
 
# 2. 关系抽取(简化版)
 
def extract_relations(text, entities):
 
    # 这里使用简单的规则匹配
 
    relations = []
 
    for i, ent1 in enumerate(entities):
 
        for j, ent2 in enumerate(entities):
 
            if i != j:
 
                # 简单规则:如果两个实体在句子中相邻,可能是关系
 
                if abs(ent1["start"] - ent2["start"]) < 20:
 
                    relations.append({
 
                        "subject": ent1["text"],
 
                        "object": ent2["text"],
 
                        "predicate": "RELATED_TO"
 
                    })
 
    return relations
 
# 3. 存储到Neo4j
 
def store_to_neo4j(entities, relations):
 
    driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password"))
 
    with driver.session() as session:
 
        # 创建实体节点
 
        for entity in entities:
 
            session.run(
 
                "CREATE (n:Entity {name: $name, type: $type})",
 
                name=entity["text"],
 
                type=entity["label"]
 
            )
 
        # 创建关系
 
        for relation in relations:
 
            session.run("""
 
                MATCH (a:Entity {name: $subject})
 
                MATCH (b:Entity {name: $object})
 
                CREATE (a)-[:RELATED_TO]->(b)
 
            """, subject=relation["subject"], object=relation["object"])
 

6. 在AI应用中的使用

6.1 知识图谱增强RAG

 
from langchain.graphs import Neo4jGraph
 
from langchain.chains import GraphCypherQAChain
 
# 连接知识图谱
 
graph = Neo4jGraph(
 
    url="bolt://localhost:7687",
 
    username="neo4j",
 
    password="password"
 
)
 
# 创建查询链
 
chain = GraphCypherQAChain.from_llm(
 
    llm=llm,
 
    graph=graph,
 
    verbose=True
 
)
 
# 查询
 
result = chain.invoke({"query": "张三在哪个公司工作?"})
 
print(result)
 

6.2 向量+图谱混合检索

 
from langchain.vectorstores import Chroma
 
from langchain.embeddings import OpenAIEmbeddings
 
# 向量检索
 
vectorstore = Chroma(embedding_function=OpenAIEmbeddings())
 
# 图谱检索
 
graph_chain = GraphCypherQAChain.from_llm(llm, graph)
 
def hybrid_retrieve(query):
 
    # 1. 向量检索
 
    vector_results = vectorstore.similarity_search(query, k=3)
 
    # 2. 图谱检索
 
    graph_results = graph_chain.invoke({"query": query})
 
    # 3. 融合结果
 
    combined = []
 
    combined.extend(vector_results)
 
    combined.extend([graph_results])
 
    return combined
 

7. 常见坑点

1. 实体抽取准确性

 
# 示例:医疗领域使用医疗NER模型
 

2. 关系抽取复杂性

 
# 示例:使用预训练关系抽取模型
 

3. 知识图谱维护

 
# 示例:定期从新数据中抽取实体和关系
 

核心要点

 
# 知识图谱核心元素
 
实体 Entity → 节点
 
关系 Relation → 边
 
属性 Attribute → 节点/边的属性
 
# Neo4j基础
 
创建节点:CREATE (n:Label {prop: value})
 
创建关系:MATCH (a), (b) CREATE (a)-[:TYPE]->(b)
 
查询:MATCH (n)-[:TYPE]->(m) RETURN n, m
 
# 构建流程
 
数据收集 → 实体抽取 → 关系抽取 → 知识存储
 

速记卡(面试闪卡)

Q1:一句话讲清「知识图谱构建基础:实体-关系抽取 + Neo4j 图数据库」到底是什么?

A:知识图谱构建:从文本抽取实体与关系存成图,用 Neo4j 存储查询,增强 RAG 检索。

Q2:一、知识图谱基础 —— 怎么理解?

A:知识图谱像一张人脉网:节点是人物/地点(实体),边是”工作于/位于”(关系),属性是姓名年龄(Graph = Nodes+Edges)。

Q3:二、实体-关系抽取 —— 怎么理解?

A:从一堆非结构化文本里自动”捡”出张三(实体)和”张三工作于腾讯”(关系),NER+规则/模型(Entity Extraction)。

Q4:三、Neo4j 图数据库 —— 怎么理解?

A:Neo4j 是用节点/关系/属性存数据的图数据库,查”谁在哪上班”直接遍历边,比 SQL JOIN 快(Graph DB)。

Q5:四、构建流程与 AI 应用 —— 怎么理解?

A:流程:收集→抽取→融合→存储→推理;落地用 GraphCypherQAChain,向量+图谱混合检索更准(Hybrid Retrieval)。

Q6:核心速记主线有哪些?

  • 基础:实体(节点)+ 关系(边)+ 属性

  • 抽取:NER 识别实体,规则/模型抽关系

  • 存储:Neo4j + Cypher 直接遍历

  • 增强:向量+图谱混合检索补 RAG

口诀

A:知识图谱人脉网,实体节点关系边;

NER 抽取出实体,关系规则一眼看;

Neo4j 存图遍历快,Cypher 查询很自然;

向量图谱混合检,RAG 检索更周全。

相关链接