mirror of
https://gitcode.com/JianFeeeee/TrulyMEM-TrueHumanMEM.git
synced 2026-09-20 17:08:18 +00:00
添加 图数据库结构设计
This commit is contained in:
254
图数据库结构设计
Normal file
254
图数据库结构设计
Normal file
@ -0,0 +1,254 @@
|
||||
以下是完整的 Neo4j 图数据库结构设计,针对 OpenClaw 对话记忆场景优化,边上带完整时间戳和元数据:
|
||||
1. 节点(Node)设计
|
||||
实体节点(Entity)
|
||||
(:Entity {
|
||||
name: string, // 实体名称(唯一标识)
|
||||
type: string, // 类型:concept | technology | person | project | decision
|
||||
created_at: datetime, // 首次出现时间
|
||||
updated_at: datetime, // 最后更新时间
|
||||
mention_count: int // 被提及次数(用于权重)
|
||||
})
|
||||
|
||||
会话节点(Session)
|
||||
(:Session {
|
||||
session_id: string, // 会话唯一ID(如 20260408-a7f3)
|
||||
created_at: datetime, // 会话开始时间
|
||||
summary: string, // 会话摘要(可选)
|
||||
status: string // active | archived | compacted
|
||||
})
|
||||
|
||||
2. 关系(Edge)设计
|
||||
核心关系(RELATES)
|
||||
所有对话关系统一使用 RELATES 类型,属性承载时间戳和元数据:
|
||||
(source:Entity)-[:RELATES {
|
||||
// 基础关系属性
|
||||
type: string, // 关系类型:uses | implements | depends_on | rejects | prefers | leads_to | contradicts
|
||||
|
||||
// 时间戳(核心)
|
||||
created_at: datetime, // 关系创建时间(精确到秒)
|
||||
updated_at: datetime, // 最后更新时间(纠错时更新)
|
||||
|
||||
// 来源追踪
|
||||
session_id: string, // 所属会话ID
|
||||
turn_id: int, // 轮次序号(该会话中的第几轮)
|
||||
|
||||
// 角色标记
|
||||
role: string, // "user" | "assistant" | "system"
|
||||
|
||||
// 内容快照
|
||||
context_snippet: string, // 原始文本片段(前100字符)
|
||||
|
||||
// 状态管理
|
||||
status: string, // active | deleted | archived | superseded(被取代)
|
||||
confidence: float, // 置信度(0.0-1.0,提取算法给出)
|
||||
|
||||
// 时序检索辅助
|
||||
date_bucket: string // 日期分区(2026-04-08),用于快速范围查询
|
||||
}]->(target:Entity)
|
||||
|
||||
时序链(NEXT)- 可选
|
||||
用于严格保持对话顺序:
|
||||
(:Entity)-[:NEXT {
|
||||
session_id: string,
|
||||
created_at: datetime
|
||||
}]->(:Entity)
|
||||
|
||||
3. 索引与约束
|
||||
// 实体唯一性约束
|
||||
CREATE CONSTRAINT entity_name_constraint IF NOT EXISTS
|
||||
FOR (e:Entity) REQUIRE e.name IS UNIQUE;
|
||||
|
||||
// 会话唯一性约束
|
||||
CREATE CONSTRAINT session_id_constraint IF NOT EXISTS
|
||||
FOR (s:Session) REQUIRE s.session_id IS UNIQUE;
|
||||
|
||||
// 关系查询索引(按时间戳检索关键)
|
||||
CREATE INDEX rel_created_at IF NOT EXISTS
|
||||
FOR ()-[r:RELATES]-() ON r.created_at;
|
||||
|
||||
CREATE INDEX rel_session_id IF NOT EXISTS
|
||||
FOR ()-[r:RELATES]-() ON r.session_id;
|
||||
|
||||
CREATE INDEX rel_type IF NOT EXISTS
|
||||
FOR ()-[r:RELATES]-() ON r.type;
|
||||
|
||||
CREATE INDEX rel_status IF NOT EXISTS
|
||||
FOR ()-[r:RELATES]-() ON r.status;
|
||||
|
||||
CREATE INDEX rel_date_bucket IF NOT EXISTS
|
||||
FOR ()-[r:RELATES]-() ON r.date_bucket;
|
||||
|
||||
// 复合索引(会话+时间)
|
||||
CREATE INDEX rel_session_time IF NOT EXISTS
|
||||
FOR ()-[r:RELATES]-() ON (r.session_id, r.created_at);
|
||||
|
||||
4. 数据模型示例
|
||||
插入场景
|
||||
用户说:"我想用 Neo4j 改造 OpenClaw 的记忆系统,替换掉原来的 SQLite 方案。"
|
||||
生成的图结构:
|
||||
// 节点
|
||||
(:Entity {name: "OpenClaw", type: "project", created_at: now()})
|
||||
(:Entity {name: "Neo4j", type: "technology", created_at: now()})
|
||||
(:Entity {name: "SQLite", type: "technology", created_at: now()})
|
||||
(:Entity {name: "记忆系统改造", type: "decision", created_at: now()})
|
||||
|
||||
// 关系(带时间戳)
|
||||
(OpenClaw)-[:RELATES {
|
||||
type: "uses",
|
||||
created_at: datetime("2026-04-08T19:45:00"),
|
||||
session_id: "20260408-a7f3",
|
||||
turn_id: 1,
|
||||
role: "user",
|
||||
context_snippet: "我想用 Neo4j 改造 OpenClaw...",
|
||||
status: "active",
|
||||
confidence: 0.95,
|
||||
date_bucket: "2026-04-08"
|
||||
}]->(Neo4j)
|
||||
|
||||
(OpenClaw)-[:RELATES {
|
||||
type: "replaces",
|
||||
created_at: datetime("2026-04-08T19:45:00"),
|
||||
session_id: "20260408-a7f3",
|
||||
turn_id: 1,
|
||||
role: "user",
|
||||
context_snippet: "替换掉原来的 SQLite 方案",
|
||||
status: "active",
|
||||
confidence: 0.92,
|
||||
date_bucket: "2026-04-08"
|
||||
}]->(SQLite)
|
||||
|
||||
(记忆系统改造)-[:RELATES {
|
||||
type: "involves",
|
||||
created_at: datetime("2026-04-08T19:45:00"),
|
||||
session_id: "20260408-a7f3",
|
||||
turn_id: 1,
|
||||
role: "user",
|
||||
status: "active",
|
||||
date_bucket: "2026-04-08"
|
||||
}]->(OpenClaw)
|
||||
|
||||
5. 关键查询模式
|
||||
A. 时序检索(最新记忆优先)
|
||||
// 查询实体相关的最新关系(按时间戳倒序)
|
||||
MATCH (e:Entity {name: $entity_name})-[r:RELATES]-(target:Entity)
|
||||
WHERE r.status = 'active'
|
||||
RETURN e, r, target
|
||||
ORDER BY r.created_at DESC
|
||||
LIMIT 20
|
||||
|
||||
B. 会话范围查询(上下文隔离)
|
||||
// 仅查询特定会话内的关系
|
||||
MATCH (s:Entity)-[r:RELATES]->(t:Entity)
|
||||
WHERE r.session_id = $session_id
|
||||
RETURN s.name, r.type, t.name, r.created_at
|
||||
ORDER BY r.turn_id
|
||||
|
||||
C. 时间范围查询(最近N天)
|
||||
// 利用 date_bucket 或时间戳范围
|
||||
MATCH (s:Entity)-[r:RELATES]->(t:Entity)
|
||||
WHERE r.date_bucket >= date().isoDate - duration('P7D') // 最近7天
|
||||
OR r.created_at >= datetime() - duration('P7D')
|
||||
RETURN s, r, t
|
||||
ORDER BY r.created_at DESC
|
||||
|
||||
D. 多跳路径查询(关联推理)
|
||||
// 查询两个实体间的路径(带时间约束)
|
||||
MATCH path = (start:Entity {name: $start})-[:RELATES*1..3]->(end:Entity {name: $end})
|
||||
WHERE ALL(r IN relationships(path) WHERE r.status = 'active')
|
||||
RETURN path,
|
||||
[r IN relationships(path) | r.created_at] as path_timestamps,
|
||||
length(path) as hops
|
||||
ORDER BY path_timestamps[-1] DESC // 按最后关系时间排序
|
||||
LIMIT 5
|
||||
|
||||
E. 纠错更新(软删除)
|
||||
// 用户更正时,不物理删除,而是标记为 superseded 并创建新关系
|
||||
MATCH (s:Entity {name: $source})-[r:RELATES {type: $old_relation}]->(t:Entity {name: $target})
|
||||
WHERE r.status = 'active'
|
||||
SET r.status = 'superseded',
|
||||
r.updated_at = datetime(),
|
||||
r.superseded_by = $new_relation_id // 指向新关系的ID
|
||||
|
||||
// 创建新关系(带新的时间戳)
|
||||
CREATE (s)-[:RELATES {
|
||||
type: $new_relation,
|
||||
created_at: datetime(),
|
||||
session_id: $session_id,
|
||||
turn_id: $turn_id,
|
||||
role: $role,
|
||||
status: 'active',
|
||||
supersedes: $old_relation_id
|
||||
}]->(t)
|
||||
|
||||
6. 存储过程(APOC)优化
|
||||
批量插入(高性能)
|
||||
// 使用 APOC 批量合并,避免逐条插入开销
|
||||
CALL apoc.periodic.iterate(
|
||||
"UNWIND $triples as t RETURN t",
|
||||
"
|
||||
MERGE (s:Entity {name: t.source})
|
||||
ON CREATE SET s.created_at = datetime(), s.type = coalesce(t.source_type, 'unknown')
|
||||
ON MATCH SET s.updated_at = datetime(), s.mention_count = coalesce(s.mention_count, 0) + 1
|
||||
|
||||
MERGE (e:Entity {name: t.target})
|
||||
ON CREATE SET e.created_at = datetime(), e.type = coalesce(t.target_type, 'unknown')
|
||||
ON MATCH SET e.updated_at = datetime(), e.mention_count = coalesce(e.mention_count, 0) + 1
|
||||
|
||||
CREATE (s)-[r:RELATES {
|
||||
type: t.relation,
|
||||
created_at: datetime(),
|
||||
session_id: t.session_id,
|
||||
turn_id: t.turn_id,
|
||||
role: t.role,
|
||||
status: 'active',
|
||||
date_bucket: date().isoDate,
|
||||
confidence: coalesce(t.confidence, 1.0)
|
||||
}]->(e)
|
||||
",
|
||||
{batchSize: 100, params: {triples: $triples}}
|
||||
)
|
||||
|
||||
时序压缩(归档旧关系)
|
||||
// 将N天前的关系标记为 archived,但保留节点
|
||||
MATCH ()-[r:RELATES]->()
|
||||
WHERE r.created_at < datetime() - duration('P30D') // 30天前
|
||||
AND r.status = 'active'
|
||||
SET r.status = 'archived',
|
||||
r.archived_at = datetime()
|
||||
RETURN count(r) as archived_count
|
||||
|
||||
7. 与 Bridge API 的映射
|
||||
API 端点 Cypher 操作 时间戳处理
|
||||
POST /insert MERGE 节点 + CREATE 关系 datetime() 自动生成
|
||||
POST /search MATCH 带时间戳排序 返回 r.created_at 等字段
|
||||
POST /delete SET r.status = 'deleted' 软删除,保留 updated_at
|
||||
8. 数据保留策略
|
||||
// 节点保留:永久(实体名词长期有效)
|
||||
// 关系保留策略:
|
||||
// - active: 最近30天(高频查询)
|
||||
// - archived: 30-90天(低频查询,需指定时间范围)
|
||||
// - deleted: 逻辑删除,保留90天后物理清理(APOC 定时任务)
|
||||
|
||||
// 物理清理(谨慎操作)
|
||||
MATCH ()-[r:RELATES]->()
|
||||
WHERE r.status = 'deleted'
|
||||
AND r.updated_at < datetime() - duration('P90D')
|
||||
DELETE r
|
||||
WITH count(*) as deleted_relations
|
||||
MATCH (e:Entity)
|
||||
WHERE NOT (e)-[:RELATES]-() // 无关系的孤立节点
|
||||
DELETE e
|
||||
RETURN deleted_relations, count(e) as deleted_orphans
|
||||
|
||||
这个设计支持时间旅行查询(查看任意时刻的图状态)、会话隔离(只看当前对话历史)和渐进式遗忘(旧关系归档但不删除),符合 OpenClaw 的增量记忆需求。
|
||||
|
||||
}]
|
||||
)
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user