> **参考对象**:语义网络之父 Allan M. Collins + 知识图谱权威 Denny Vrandečić + 时态数据库研究者
---
## 引子:为什么 RAG 不够用了?
传统 RAG(Retrieval-Augmented Generation)的工作方式:
1. 把文档切成文本块
2. 用户提问时,检索最相关的文本块
3. 把文本块喂给 LLM,生成回答
**这在简单问答场景中表现良好,但在复杂分析场景中经常失效:**
> **问题**:"某高校宿舍甲醛事件中,学生、校方、媒体、政府四方的立场分别是什么?它们之间如何相互影响?"
**传统 RAG 的问题**:
- 文本块之间是孤立的,无法表示"关系"
- 无法回答需要多跳推理的问题(A 影响 B,B 影响 C,那么 A 如何影响 C?)
- 无法处理时态信息(关系何时建立、何时失效)
**GraphRAG 的解决方案**:把文本转换成知识图谱,用图结构表示实体和关系。
---
## 第一部分:GraphRAG 核心原理
### 从文本到图谱的转换
```
原始文本:
"张三是一名计算机专业的学生,就读于北京大学。
2024年3月,他在微博上曝光了宿舍甲醛超标问题。
校方随后发布声明回应,北京日报对此事进行了报道。"
传统 RAG 存储:
[文本块1] "张三是一名计算机专业的学生..."
[文本块2] "2024年3月,他在微博上曝光了..."
[文本块3] "校方随后发布声明回应..."
GraphRAG 存储:
实体:张三(学生)、北京大学(大学)、校方(组织)、北京日报(媒体)
关系:张三 --[就读于]--> 北京大学
张三 --[曝光]--> 甲醛事件
校方 --[回应]--> 甲醛事件
北京日报 --[报道]--> 甲醛事件
```
### GraphRAG 的三大优势
| 优势 | 说明 | 示例 |
|------|------|------|
| **结构化关系** | 显式表示实体间关系 | "张三和校方是什么关系?" |
| **多跳推理** | 支持关系链追踪 | "媒体如何影响公众认知?" |
| **语义聚合** | 将分散信息关联到同一实体 | "关于张三的所有信息" |
---
## 第二部分:MiroFish 的 GraphRAG 实现(Zep Cloud)
MiroFish 使用 **Zep Cloud** 作为 GraphRAG 引擎。Zep 是一个专门为 LLM 应用设计的时态知识图谱服务。
### Zep 的核心特性
#### 1. 时态图谱(Temporal Graph)
**传统知识图谱**:记录"什么实体存在"
**Zep 时态图谱**:记录"什么实体存在" + "什么时候有效"
```python
# Zep 中的边(关系)包含时间信息
class EdgeInfo:
uuid: str
name: str # 关系类型,如 "STUDIES_AT"
fact: str # 自然语言描述
source_node_uuid: str
target_node_uuid: str
created_at: Optional[str] # 创建时间
valid_at: Optional[str] # 生效时间
invalid_at: Optional[str] # 失效时间
expired_at: Optional[str] # 过期时间(被新事实覆盖)
```
**示例**:
```
边:张三 --[STUDIES_AT]--> 北京大学
valid_at: "2023-09-01"
invalid_at: "2027-06-30"
边:张三 --[WORKS_FOR]--> 某科技公司
valid_at: "2027-07-01"
invalid_at: null # 至今
```
**这使得系统可以回答时态问题**:
- "2024年3月,张三还在北京大学就读吗?" → 是
- "2028年,张三还在北京大学就读吗?" → 否(已毕业)
#### 2. 自动去重与事实更新
当新文档中包含与现有事实冲突的信息时,Zep 会自动处理:
```
现有事实:张三就读于北京大学(valid_at: 2023-09-01, invalid_at: null)
新信息:张三于2027年毕业,加入某科技公司
Zep 自动操作:
1. 更新原事实:invalid_at = "2027-06-30"
2. 创建新事实:张三 --[WORKS_FOR]--> 某科技公司(valid_at: "2027-07-01")
3. 原事实被标记为"历史事实",新事实为"当前事实"
```
#### 3. 层次化实体模型
Zep 使用 Pydantic 模型定义实体类型,支持属性:
```python
from pydantic import Field
from zep_cloud.external_clients.ontology import EntityModel, EntityText
class Student(EntityModel):
"""学生实体"""
full_name: EntityText = Field(description="姓名")
major: EntityText = Field(description="专业")
enrollment_year: EntityText = Field(description="入学年份")
class University(EntityModel):
"""大学实体"""
org_name: EntityText = Field(description="学校名称")
location: EntityText = Field(description="地理位置")
ranking: EntityText = Field(description="排名")
```
---
## 第三部分:MiroFish 的本体生成器
### 什么是"本体"(Ontology)?
在知识图谱中,**本体**定义了:
- 有哪些实体类型(如学生、大学、媒体)
- 有哪些关系类型(如就读于、报道、回应)
- 每个类型有什么属性
### MiroFish 的自动本体生成
传统方法:人工定义本体(耗时、需要领域知识)
MiroFish 方法:**LLM 自动生成本体**
**约束条件**:
1. 必须正好 10 个实体类型
2. 最后 2 个必须是兜底类型(Person、Organization)
3. 所有实体必须是能在社交媒体上"发声"的主体
4. 不能是抽象概念
**为什么需要兜底类型?**
```
具体类型(8个):
- Student(学生)
- Professor(教授)
- University(大学)
- MediaOutlet(媒体)
...
兜底类型(2个):
- Person(个人兜底)
用于:"某位路人"、"匿名网友"、"一位家长"
- Organization(组织兜底)
用于:"某小型公司"、"一个社区团体"
```
### 本体生成 Prompt 设计
```python
ONTOLOGY_SYSTEM_PROMPT = """
你是一个专业的知识图谱本体设计专家。
【核心任务背景】
我们正在构建一个社交媒体舆论模拟系统。在这个系统中:
- 每个实体都是一个可以在社交媒体上发声、互动、传播信息的"账号"
- 实体之间会相互影响、转发、评论、回应
因此,【实体必须是现实中真实存在的、可以在社媒上发声的主体】:
【可以是】:
- 具体的个人(公众人物、当事人、意见领袖)
- 公司、企业(包括其官方账号)
- 组织机构(大学、协会、NGO)
- 政府部门、监管机构
- 媒体机构(报纸、电视台、自媒体)
【不可以是】:
- 抽象概念(如"舆论"、"情绪"、"趋势")
- 主题/话题(如"学术诚信"、"教育改革")
- 观点/态度(如"支持方"、"反对方")
"""
```
### 本体生成示例输出
```json
{
"entity_types": [
{
"name": "Student",
"description": "在校学生,包括本科生、研究生",
"attributes": [
{"name": "full_name", "type": "text", "description": "姓名"},
{"name": "major", "type": "text", "description": "专业"}
],
"examples": ["张三", "李四"]
},
{
"name": "University",
"description": "高等教育机构",
"attributes": [
{"name": "org_name", "type": "text", "description": "学校名称"},
{"name": "location", "type": "text", "description": "地理位置"}
],
"examples": ["北京大学", "清华大学"]
},
{
"name": "Person",
"description": "任何自然人个体的兜底类型",
"attributes": [
{"name": "full_name", "type": "text", "description": "姓名"},
{"name": "role", "type": "text", "description": "角色"}
],
"examples": ["普通市民", "匿名网友"]
}
],
"edge_types": [
{
"name": "STUDIES_AT",
"description": "就读于",
"source_targets": [
{"source": "Student", "target": "University"},
{"source": "Person", "target": "University"}
]
},
{
"name": "REPORTS_ON",
"description": "报道",
"source_targets": [
{"source": "MediaOutlet", "target": "Event"},
{"source": "MediaOutlet", "target": "Person"}
]
}
]
}
```
---
## 第四部分:知识图谱构建流程
### 流程图
```
┌─────────────────────────────────────────────────────────────┐
│ 知识图谱构建流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 输入处理 │
│ ├── 读取 PDF/Word/网页 │
│ └── 文本清洗与分段 │
│ ↓ │
│ 2. 本体生成 │
│ └── LLM 分析文本 → 生成实体类型 + 关系类型 │
│ ↓ │
│ 3. 实体抽取 │
│ └── LLM 识别文本中的实体 │
│ └── "张三是一名学生" → 实体: 张三(Student) │
│ ↓ │
│ 4. 关系抽取 │
│ └── LLM 识别实体间的关系 │
│ └── "张三就读于北京大学" → 关系: STUDIES_AT │
│ ↓ │
│ 5. 时态信息抽取 │
│ └── 识别时间表达式 │
│ └── "2023年入学" → valid_at: "2023-09-01" │
│ ↓ │
│ 6. 图谱写入 Zep │
│ └── 创建节点 → 创建边 → 更新时间属性 │
│ │
└─────────────────────────────────────────────────────────────┘
```
### 技术细节:Graph Builder
```python
class GraphBuilder:
"""
知识图谱构建器
流程:
1. 读取文档 → 提取文本
2. 生成本体(实体类型、关系类型)
3. 抽取实体
4. 抽取关系
5. 写入 Zep Cloud
"""
def build_from_documents(
self,
documents: List[Document],
simulation_requirement: str,
progress_callback: Optional[Callable] = None
) -> GraphBuildResult:
"""
从文档构建知识图谱
Args:
documents: 文档列表
simulation_requirement: 模拟需求描述
progress_callback: 进度回调函数
Returns:
GraphBuildResult: 构建结果
"""
# 1. 生成本体
ontology = self.ontology_generator.generate(
document_texts=[doc.text for doc in documents],
simulation_requirement=simulation_requirement
)
# 2. 分批处理文档,抽取实体和关系
all_entities = []
all_relationships = []
for batch in self._batch_documents(documents):
# 抽取实体
entities = self._extract_entities(batch, ontology)
all_entities.extend(entities)
# 抽取关系
relationships = self._extract_relationships(batch, entities, ontology)
all_relationships.extend(relationships)
# 3. 去重与合并
merged_entities = self._merge_entities(all_entities)
merged_relationships = self._merge_relationships(all_relationships)
# 4. 写入 Zep Cloud
graph_id = self._write_to_zep(merged_entities, merged_relationships, ontology)
return GraphBuildResult(
graph_id=graph_id,
entity_count=len(merged_entities),
relationship_count=len(merged_relationships),
ontology=ontology
)
```
---
## 第五部分:Zep Tools 检索系统
MiroFish 封装了四个核心检索工具:
### 1. QuickSearch(快速搜索)
```python
def quick_search(
self,
graph_id: str,
query: str,
limit: int = 10
) -> SearchResult:
"""
快速搜索
使用场景:
- 需要快速查找某个具体信息
- 需要验证某个事实
- 简单的信息检索
实现:
- 语义搜索相关事实
- 返回最相关的事实列表
"""
```
### 2. PanoramaSearch(广度搜索)
```python
def panorama_search(
self,
graph_id: str,
query: str,
include_expired: bool = True
) -> PanoramaResult:
"""
广角全景搜索
使用场景:
- 需要了解事件的完整发展脉络
- 需要对比不同阶段的舆情变化
- 需要获取全面的实体和关系信息
实现:
- 获取所有相关节点和关系
- 区分当前有效的事实和历史/过期的事实
- 帮助了解舆情是如何演变的
"""
```
### 3. InsightForge(深度洞察检索)
```python
def insight_forge(
self,
graph_id: str,
query: str,
simulation_requirement: str,
report_context: str = ""
) -> InsightForgeResult:
"""
深度洞察检索(最强大的检索工具)
使用场景:
- 需要深入分析某个话题
- 需要了解事件的多个方面
- 需要获取支撑报告章节的丰富素材
实现:
1. LLM 自动将问题分解为多个子问题
2. 从多个维度检索图谱信息:
- 语义搜索:找到相关事实
- 实体分析:识别关键实体
- 关系链追踪:发现影响路径
3. 整合结果,生成深度分析
"""
```
### 4. Interview Agents(深度采访)
```python
def interview_agents(
self,
simulation_id: str,
interview_requirement: str,
simulation_requirement: str,
max_agents: int = 5
) -> InterviewResult:
"""
深度采访 - 真实 Agent 采访(双平台)
调用 OASIS 模拟环境的采访 API,对正在运行的模拟 Agent 进行真实采访!
功能流程:
1. 自动读取人设文件,了解所有模拟 Agent
2. 智能选择与采访主题最相关的 Agent(如学生、媒体、官方等)
3. 自动生成采访问题
4. 调用 /api/simulation/interview/batch 接口在双平台进行真实采访
5. 整合所有采访结果,提供多视角分析
【重要】需要 OASIS 模拟环境正在运行才能使用此功能!
"""
```
---
## 第六部分:时态图谱的实际应用
### 场景 1:追踪关系变化
```
初始事实:
张三 --[STUDIES_AT]--> 北京大学 (valid_at: 2023-09-01, invalid_at: null)
新信息:张三于2027年毕业
系统操作:
1. 更新原事实:invalid_at = "2027-06-30"
2. 创建新事实:张三 --[WORKS_FOR]--> 某科技公司 (valid_at: "2027-07-01")
查询:"2024年张三的身份是什么?"
结果:北京大学学生
查询:"2028年张三的身份是什么?"
结果:某科技公司员工
```
### 场景 2:事实版本管理
```
事实 1(2024-03-01):
校方 --[ANNOUNCES]--> "宿舍甲醛检测合格" (valid_at: 2024-03-01)
事实 2(2024-03-15):
第三方检测机构 --[REPORTS]--> "宿舍甲醛超标" (valid_at: 2024-03-15)
事实 3(2024-03-16):
校方 --[REVISES]--> "已启动整改" (valid_at: 2024-03-16)
同时标记事实 1 为 expired
查询:"校方立场的变化过程?"
结果:
1. 3月1日:声称检测合格
2. 3月15日:被第三方机构质疑
3. 3月16日:改口称已启动整改
```
---
## 第七部分:GraphRAG vs 传统 RAG 对比
| 维度 | 传统 RAG | GraphRAG (MiroFish) |
|------|---------|---------------------|
| **数据结构** | 文本块向量 | 实体-关系图 |
| **关系表示** | 隐式(通过文本共现) | 显式(边类型) |
| **多跳推理** | 困难 | 天然支持 |
| **时态信息** | 难以处理 | 一等公民 |
| **可解释性** | 黑箱 | 可追溯关系链 |
| **适用场景** | 简单问答 | 复杂分析、仿真 |
---
## 尾声:知识图谱是 AI 理解世界的基础设施
MiroFish 的实践表明,**知识图谱是 AI 从"语言模型"进化为"世界模型"的关键一步**。
传统 LLM 擅长:
- 语言理解与生成
- 模式识别与联想
- 单轮问答
GraphRAG 赋予 LLM:
- 结构化知识表示
- 关系推理能力
- 时态推理能力
**这不是替代 LLM,而是增强 LLM**——就像给 LLM 配备了一个"外脑记忆系统"。
---
*本文是 MiroFish 深度解析系列的第二篇,下一篇将深入探讨 OASIS 仿真引擎。*
#MiroFish #GraphRAG #Zep #知识图谱 #时态图谱
登录后可参与表态
讨论回复
0 条回复还没有人回复,快来发表你的看法吧!