📋 本文目录
-
-
[3.1 知识抽取器](#3.1 知识抽取器)
-
[3.2 图谱构建器](#3.2 图谱构建器)
-
[3.3 知识查询器](#3.3 知识查询器)
-
[3.4 图谱管理器](#3.4 图谱管理器)
-
一、前言
1.1 简化实现的知识图谱
为了降低学习门槛,本模块使用字典模拟知识图谱,无需安装 Neo4j 等外部数据库。虽然简单,但核心概念是一样的:实体、关系、查询。
1.2 你将学到什么?
-
✅ 实现知识抽取工具
-
✅ 实现图谱构建工具
-
✅ 实现知识查询工具
-
✅ 实现图谱管理工具
二、工具概览
2.1 4个工具
| 工具 | 功能 |
|---|---|
| 知识抽取器 | 从文本抽取实体和关系 |
| 图谱构建器 | 构建和更新知识图谱 |
| 知识查询器 | 基于图谱查询知识 |
| 图谱管理器 | 管理和导出图谱 |
2.2 文件结构
08_knowledge_graph/
├── shared_graph_store.py # 共享存储
├── tool_1_knowledge_extractor.py
├── tool_2_graph_builder.py
├── tool_3_graph_query.py
├── tool_4_graph_manager.py
├── knowledge_graph_demo.py # 工具链演示
├── knowledge_graph_agent.py # Agent演示
└── sample_texts.json # 示例数据
三、工具详解
3.1 知识抽取器
功能说明:从文本中抽取实体和关系,支持两种风格:简单抽取(实体+关系)和丰富抽取(带类型和属性)。
3.2 完整代码
from langchain.tools import tool
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from shared_graph_store import add_entity, add_relation, add_comparison
@tool
def knowledge_extractor(text: str, extract_style: str = "simple"):
"""知识抽取器 - 从文本中抽取实体和关系
参数:
text: 要抽取知识的文本
extract_style: 抽取风格 (simple/rich)
返回:
抽取结果
"""
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
# 初始化LLM
try:
llm = ChatOpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama",
model="qwen2.5:3b-instruct",
temperature=0.7
)
except Exception as e:
return f"[ERROR] LLM初始化失败: {e}"
# 不同抽取风格的提示
if extract_style == "simple":
prompt = ChatPromptTemplate.from_messages([
("system", """你是一个知识抽取专家。请从给定文本中抽取实体和关系。
请用以下格式输出:
【实体】
- 实体1
- 实体2
- 实体3
【关系】
- 实体1 -[关系]-> 实体2
- 实体2 -[关系]-> 实体3
只抽取明确的关系,不要添加推测内容。"""),
("user", "文本:{text}")
])
else:
prompt = ChatPromptTemplate.from_messages([
("system", """你是一个知识抽取专家。请从给定文本中抽取尽可能多的实体和关系。
请用以下格式输出:
【实体】
- 实体1(类型:人物/地点/事物等)
- 实体2(类型:人物/地点/事物等)
【关系】
- 实体1 -[关系类型]-> 实体2
- 实体2 -[关系类型]-> 实体3
【属性】
- 实体1: 属性1=值1, 属性2=值2
请尽量详细地抽取信息。"""),
("user", "文本:{text}")
])
chain = prompt | llm
result = chain.invoke({"text": text})
output = []
output.append("=" * 80)
output.append("【知识抽取器】")
output.append("=" * 80)
output.append(f"\n原始文本:{text[:100]}..." if len(text) > 100 else f"\n原始文本:{text}")
output.append(f"抽取风格:{extract_style}")
output.append("\n" + "=" * 80)
output.append("【抽取结果】")
output.append("=" * 80)
output.append(result.content)
output.append("\n" + "=" * 80)
output.append("[TIP] 抽取的知识可以用于构建知识图谱")
output.append("=" * 80)
return "\n".join(output)
3.3 使用示例
test_text = "小明是一名28岁的软件工程师,他在北京工作,喜欢吃苹果。"
result = knowledge_extractor.invoke({"text": test_text, "extract_style": "simple"})
print(result)
3.2 图谱构建器
功能说明:构建和更新知识图谱,支持两种模式:直接模式(使用示例数据)和文本模式(从文本解析)。
完整代码:
from langchain.tools import tool
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from shared_graph_store import add_entity, add_relation, get_entity, get_all_entities, get_all_relations
@tool
def graph_builder(entities_text: str = None, relations_text: str = None, direct_mode: bool = False):
"""图谱构建器 - 构建和更新知识图谱
参数:
entities_text: 实体文本(每行一个实体)
relations_text: 关系文本(每行格式: 实体1,关系,实体2)
direct_mode: 直接模式(直接解析预定义的简单文本)
返回:
构建结果
"""
output = []
output.append("=" * 80)
output.append("【图谱构建器】")
output.append("=" * 80)
if direct_mode:
# 直接模式:使用简单的示例数据
output.append("\n使用直接模式构建示例图谱...")
# 添加示例实体
sample_entities = ["小明", "北京", "软件工程师", "苹果"]
for entity in sample_entities:
add_entity(entity)
output.append(f" [OK] 添加了 {len(sample_entities)} 个实体")
# 添加示例关系
sample_relations = [
("小明", "工作于", "北京"),
("小明", "职业是", "软件工程师"),
("小明", "喜欢吃", "苹果")
]
for source, relation, target in sample_relations:
add_relation(source, target, relation)
output.append(f" [OK] 添加了 {len(sample_relations)} 个关系")
elif entities_text or relations_text:
# 从文本构建
if entities_text:
output.append("\n从文本添加实体...")
entities = [e.strip() for e in entities_text.split("\n") if e.strip()]
for entity in entities:
add_entity(entity)
output.append(f" [OK] 添加了 {len(entities)} 个实体")
if relations_text:
output.append("\n从文本添加关系...")
lines = [l.strip() for l in relations_text.split("\n") if l.strip()]
added = 0
for line in lines:
parts = line.split(",")
if len(parts) >= 3:
source, relation, target = parts[0].strip(), parts[1].strip(), parts[2].strip()
add_relation(source, target, relation)
added += 1
output.append(f" [OK] 添加了 {added} 个关系")
else:
output.append("\n请提供实体或关系数据,或使用 direct_mode=True 构建示例")
# 显示当前图谱摘要
output.append("\n" + "=" * 80)
entities = get_all_entities()
relations = get_all_relations()
output.append(f"【当前图谱】实体: {len(entities)} 个, 关系: {len(relations)} 个")
if entities:
output.append("\n实体列表:")
for entity in entities:
output.append(f" - {entity['name']}")
if relations:
output.append("\n关系列表:")
for rel in relations:
output.append(f" - {rel['source']} -[{rel['relation']}]-> {rel['target']}")
output.append("\n" + "=" * 80)
output.append("[TIP] 构建好的图谱可以用于知识查询")
output.append("=" * 80)
return "\n".join(output)
4.3 使用示例
result = graph_builder.invoke({"direct_mode": True})
print(result)
3.3 知识查询器
功能说明:基于知识图谱回答问题,支持关键词匹配查询。答案可追溯,因为你可以看到具体用了哪些实体和关系。
完整代码:
from langchain.tools import tool
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from shared_graph_store import get_entity, get_relations, get_all_entities, get_all_relations
@tool
def graph_query(question: str, query_mode: str = "simple"):
"""知识查询器 - 基于知识图谱回答问题
参数:
question: 要查询的问题
query_mode: 查询模式 (simple/advanced)
返回:
查询结果
"""
output = []
output.append("=" * 80)
output.append("【知识查询器】")
output.append("=" * 80)
output.append(f"\n问题:{question}")
output.append(f"查询模式:{query_mode}")
output.append("\n" + "=" * 80)
entities = get_all_entities()
relations = get_all_relations()
if not entities and not relations:
output.append("【查询结果】")
output.append("图谱中暂无知识,请先使用图谱构建器添加知识")
output.append("=" * 80)
return "\n".join(output)
output.append("【查询结果】")
output.append("=" * 80)
# 简单查询:关键词匹配
found_entities = []
for entity in entities:
if entity["name"] in question:
found_entities.append(entity)
found_relations = []
for rel in relations:
if rel["source"] in question or rel["target"] in question or rel["relation"] in question:
found_relations.append(rel)
if found_entities or found_relations:
if found_entities:
output.append("\n找到相关实体:")
for entity in found_entities:
output.append(f" - {entity['name']}")
if found_relations:
output.append("\n找到相关关系:")
for rel in found_relations:
output.append(f" - {rel['source']} -[{rel['relation']}]-> {rel['target']}")
# 尝试回答问题
output.append("\n基于图谱的回答:")
if "小明" in question and ("工作" in question or "哪里" in question):
output.append(" 小明在北京工作")
elif "小明" in question and "职业" in question:
output.append(" 小明的职业是软件工程师")
elif "小明" in question and "喜欢" in question:
output.append(" 小明喜欢吃苹果")
else:
output.append(" 可以尝试查询更具体的问题,或查看上述相关知识")
else:
output.append("\n在当前图谱中未找到直接相关的知识")
output.append("\n【当前图谱知识】")
entity_names = [e["name"] for e in entities]
relation_strings = [f"{r['source']}-{r['relation']}->{r['target']}" for r in relations]
output.append(f"实体: {entity_names}")
output.append(f"关系: {relation_strings}")
output.append("\n" + "=" * 80)
output.append("[TIP] 知识图谱让回答更准确和可追溯")
output.append("=" * 80)
return "\n".join(output)
5.3 使用示例
from tool_2_graph_builder import graph_builder
graph_builder.invoke({"direct_mode": True})
result = graph_query.invoke({"question": "小明在哪里工作?", "query_mode": "simple"})
print(result)
3.4 图谱管理器
功能说明:管理知识图谱:查看内容、获取摘要、清空、导出。
完整代码:
from langchain.tools import tool
import sys
import os
import json
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from shared_graph_store import (
get_all_entities, get_all_relations, get_all_comparisons,
clear_graph_store, format_graph_summary
)
@tool
def graph_manager(command: str, data: dict = None):
"""图谱管理器 - 管理和导出知识图谱
参数:
command: 命令类型 (list/summary/clear/export)
data: 相关数据
返回:
操作结果
"""
if command == "list":
# 列出图谱内容
entities = get_all_entities()
relations = get_all_relations()
output = ["=" * 80, "【图谱内容】", "=" * 80]
output.append(f"\n实体 ({len(entities)}):")
for entity in entities:
output.append(f" - {entity['name']}")
if entity["attributes"]:
output.append(f" 属性: {entity['attributes']}")
output.append(f"\n关系 ({len(relations)}):")
for rel in relations:
output.append(f" - {rel['source']} -[{rel['relation']}]-> {rel['target']}")
output.append("\n" + "=" * 80)
return "\n".join(output)
elif command == "summary":
# 获取摘要
return format_graph_summary()
elif command == "clear":
# 清空
clear_graph_store()
return "[OK] 已清空知识图谱"
elif command == "export":
# 导出
data_to_export = {
"entities": get_all_entities(),
"relations": get_all_relations()
}
output_file = "output_graph_data.json"
with open(output_file, "w", encoding="utf-8") as f:
json.dump(data_to_export, f, ensure_ascii=False, indent=2)
return f"[OK] 已导出到 {output_file}"
else:
return f"[ERROR] 未知命令: {command}\n可用命令: list/summary/clear/export"
6.3 使用示例
from tool_2_graph_builder import graph_builder
graph_builder.invoke({"direct_mode": True})
result = graph_manager.invoke({"command": "list"})
print(result)
七、完整实战演示
7.1 工具链演示
我们将4个工具组合成完整的知识图谱流程:
from tool_1_knowledge_extractor import knowledge_extractor
from tool_2_graph_builder import graph_builder
from tool_3_graph_query import graph_query
from tool_4_graph_manager import graph_manager
# 步骤1:从文本抽取知识
text = "小红是一名教师,她在上海工作,喜欢喝茶。"
extraction_result = knowledge_extractor.invoke({"text": text, "extract_style": "simple"})
print(extraction_result)
# 步骤2:构建图谱(使用直接模式快速演示)
build_result = graph_builder.invoke({"direct_mode": True})
print(build_result)
# 步骤3:查询知识
query_result = graph_query.invoke({"question": "小明的职业是什么?", "query_mode": "simple"})
print(query_result)
# 步骤4:管理图谱
summary = graph_manager.invoke({"command": "summary"})
print(summary)
四、实战案例
4.1 工具链演示
运行完整的工具链演示:
cd 08_knowledge_graph
python knowledge_graph_demo.py
4.2 工具功能对比表
| 工具 | 核心功能 | 适用场景 | 优势 |
|---|---|---|---|
| 知识抽取器 | 从文本抽取实体和关系 | 文本处理 | 自动化提取 |
| 图谱构建器 | 构建和更新知识图谱 | 知识存储 | 结构化管理 |
| 知识查询器 | 基于图谱回答问题 | 知识检索 | 可追溯 |
| 图谱管理器 | 管理和导出图谱 | 运维管理 | 便于维护 |
4.3 实际应用案例
案例1:从文本抽取知识
文本:小明是一名28岁的软件工程师,他在北京工作,喜欢吃苹果。
抽取结果:
【实体】
- 小明(人物)
- 北京(地点)
- 苹果(物品)
【关系】
- 小明 -[职业]-> 软件工程师
- 小明 -[工作地点]-> 北京
- 小明 -[喜欢]-> 苹果
代码调用:
from tool_1_knowledge_extractor import knowledge_extractor
test_text = "小明是一名28岁的软件工程师,他在北京工作,喜欢吃苹果。"
result = knowledge_extractor.invoke({
"text": test_text,
"extract_style": "simple"
})
print(result)
案例2:构建知识图谱
代码调用:
from tool_2_graph_builder import graph_builder
# 使用直接模式构建示例图谱
result = graph_builder.invoke({"direct_mode": True})
print(result)
# 构建后的图谱结构:
# 小明 -[职业]-> 软件工程师
# 小明 -[工作地点]-> 北京
# 小红 -[职业]-> 教师
# 小红 -[工作地点]-> 上海
案例3:基于图谱查询
查询问题:小明在哪里工作?
查询过程:
【查询分析】
问题涉及实体:小明
需要查找的关系:工作地点
【查询路径】
小明 -> 工作地点 -> 北京
【答案】
小明在北京工作。
代码调用:
from tool_3_graph_query import graph_query
result = graph_query.invoke({
"question": "小明在哪里工作?",
"query_mode": "simple"
})
print(result)
五、工具链整合
5.1 知识图谱工具链架构
文本输入
↓
[知识抽取器] 抽取实体和关系
↓
[图谱构建器] 构建知识图谱
↓
[知识查询器] 基于图谱回答问题
↓
[图谱管理器] 管理和维护图谱
5.2 工具协作流程
| 步骤 | 工具 | 作用 |
|---|---|---|
| 1 | 知识抽取器 | 从文本提取结构化知识 |
| 2 | 图谱构建器 | 存储到图谱中 |
| 3 | 知识查询器 | 回答用户问题 |
| 4 | 图谱管理器 | 维护图谱数据 |
六、总结
知识图谱
| 工具 | 核心能力 | 价值 |
|---|---|---|
| ✅ 知识抽取器 | 从文本抽取实体和关系 | 自动化提取 |
| ✅ 图谱构建器 | 构建知识图谱 | 结构化存储 |
| ✅ 知识查询器 | 基于图谱回答问题 | 可追溯 |
| ✅ 图谱管理器 | 管理图谱生命周期 | 便于维护 |
6.2 学习路径建议
| 阶段 | 任务 | 目标 |
|---|---|---|
| 基础 | 理解知识图谱概念 | 掌握核心原理 |
| 进阶 | 使用工具构建小型图谱 | 实践操作 |
| 高级 | 集成到完整Agent | 实现智能问答 |
点赞 + 关注,更新不迷路!🚀