refactor: rename to Graph Memory Demo, remove OpenClaw branding

This commit is contained in:
root
2026-04-09 08:44:44 +08:00
parent d20870255b
commit 987768d835
6 changed files with 109 additions and 182 deletions

225
README.md
View File

@ -1,173 +1,92 @@
OpenClaw: 零上下文图原生自主记忆系统
1. 核心范式
状态完全外部化LLM实例不保留任何对话历史、不维护内部记忆、不依赖上下文窗口。每轮推理仅依赖
- 当前用户输入
- 图数据库实时查询返回的子图
- 系统提供的元认知指令
模型即控制器:与传统"工具调用"不同,模型不是被动响应预设触发器,而是主动评估信息需求、自主决策记忆操作(查询/写入/删除/修正)。
图即唯一真相源:所有会话状态、实体关系、推理轨迹以节点-边形式持久化于Neo4j模型通过显式工具调用与状态交互。
# Graph Memory Demo
---
纯图数据库记忆存储 Demo - 验证无上下文对话系统
2. 架构组件
2.1 工具层Skill System
{
"tools": [
{
"name": "memory_recall",
"description": "当你对当前输入中的实体、指代、或关系不确定时,调用此工具检索相关记忆。输入为自然语言查询意图,系统将返回相关子图。",
"parameters": {
"query_intent": "string", // 模型用自然语言描述想查什么
"seed_entities": ["string"], // 可选已识别的实体ID
"depth": "number" // 期望的遍历深度,由模型根据复杂度决定
}
},
{
"name": "memory_commit",
"description": "当你认为当前对话包含对未来轮次有价值的信息时,将抽取的三元组写入图库。仅在信息具有跨轮次引用潜力时调用。",
"parameters": {
"triplets": [
{"subject": "string", "relation": "string", "object": "string", "confidence": "float"}
],
"entity_types": ["string"], // 模型动态提议类型
"temporal_tag": "string" // 可选:时间标记(如'2026-04-08'
}
},
{
"name": "memory_purge",
"description": "当你发现记忆中的信息与当前认知矛盾或用户明确要求更正时删除指定关系。优先于memory_commit执行以维护一致性。",
"parameters": {
"criteria": {
"subject_contains": "string",
"relation_type": "string",
"time_before": "string"
}
}
},
{
"name": "memory_introspect",
"description": "检索当前对话会话的元数据:已讨论的实体、关系密度、记忆热点。用于自我监控信息缺口。",
"parameters": {}
}
]
}
## 概述
2.2 控制流(每轮交互)
用户输入
[LLM首次推理] → 评估:我是否理解所有实体和指代?
↓ 是/否
├─→ 调用memory_recall自主决定查询深度和范围
│ └─→ 返回子图JSON格式
├─→ 调用memory_introspect可选检查会话状态
[LLM二次推理] → 基于检索结果生成回复草稿
[LLM三次推理] → 评估:本次对话产生的新信息价值?
↓ 高/低
├─→ 调用memory_commit动态类型可变粒度
└─→ 跳过写入
返回给用户
本 Demo 验证使用 Neo4j 图数据库替代传统上下文窗口的可行性。每轮对话通过 DeepSeek API Tool Calls 实现自主记忆存取。
关键每轮可能包含多次工具调用序列模型自主编排调用顺序如先purge后commit或多次recall逐步探索
2.3 数据模型动态Schema
节点:
(:Entity {
id: "模型生成或系统分配",
canonical_name: "标准命名",
aliases: ["别名列表"],
type: "模型动态提议", // 无封闭列表,系统仅做相似性归一化
first_seen: timestamp,
last_accessed: timestamp,
access_count: int,
embedding: vector // 用于语义相似度去重
})
## 核心工具
关系:
(:Entity)-[:RELATION {
type: "模型定义的关系语义",
timestamp: timestamp,
session_id: "对话线程ID",
confidence: float,
valid_until: timestamp // 支持临时性知识
}]->(:Entity)
| 工具 | 功能 |
|------|------|
| memory_recall | 检索历史记忆 |
| memory_commit | 写入记忆(三元组) |
| memory_purge | 修正/删除记忆 |
| memory_introspect | 查看会话状态 |
| memory_archive | 归档旧关系 |
| memory_cleanup | 物理清理 |
会话锚点:
(:Session {id: "uuid", created: timestamp})-[:CONTAINS]->(:Entity)
## 快速开始
### 1. 安装 Neo4j
---
```bash
# Ubuntu/Debian
bash scripts/install_neo4j_ubuntu.sh
3. 自治决策机制
3.1 元认知Prompt系统指令
你是OpenClaw的自主记忆控制器。你的上下文窗口为空你是无状态的。
# CentOS/RHEL
bash scripts/install_neo4j_centos.sh
可用记忆操作:
1. recall: 当你遇到指代("那个"、"它"、"之前说的")、未知实体、或需要验证的事实时调用
2. commit: 仅当信息满足以下条件时写入:
- 用户明确偏好/属性("我喜欢Python"
- 跨轮次可引用的事实("项目X的截止日期是..."
- 推理链的关键中间结论
不要写入:临时例子、闲聊寒暄、已存储的冗余信息
3. purge: 检测到用户更正("不对,我是说...")或逻辑矛盾时立即执行
# openEuler
bash scripts/install_neo4j_openeuler.sh
决策原则:
- 不确定性驱动查询只要存在歧义优先recall而非猜测
- 写入抑制:宁可少写,不要写噪(图库污染代价高)
- 类型复用优先使用已存在的entity_types新类型仅在语义无法归约时创建
# Docker
bash scripts/start_neo4j_docker.sh
```
3.2 并发与一致性
竞态处理:
- 每轮工具调用携带session_id和turn_id
- Neo4j使用MERGE确保实体幂等性基于embedding相似度阈值去重
- 关系写入使用CREATE允许重复关系带不同timestamp形成时序链
长事务支持:
若单轮需要多次recall如探索性查询模型在单次API调用中使用parallel_tool_calls并行发起减少RTT。
### 2. 配置环境变量
---
```bash
export DEEPSEEK_API_KEY="your-api-key"
export NEO4J_PASSWORD="neo4j"
```
4. 与常规架构的本质差异
维度 传统RAG MemGPT OpenClaw
记忆位置 向量库+上下文窗口 分层虚拟内存 图数据库(唯一)
检索触发 固定策略如top-k OS式页面置换 模型自主决策
写入控制 自动分块存储 自动换页 模型价值判断
结构化 平面向量 线性序列 拓扑图结构
一致性 最终一致 虚拟内存一致 显式事务purge+commit
### 3. 运行 Demo
---
```bash
python graph_memory_demo.py
```
5. 工程实现要点
5.1 性能优化(针对你的系统背景)
连接池管理:
- Neo4j驱动配置max_connection_pool_size: 20匹配龙虾工作线程数
- 工具调用使用session.run的短事务避免长连接占用
查询优化:
- recall工具内部实现先向量相似度检索快速定位再图遍历关系展开
- 对高频查询路径(如"用户偏好"建立索引CREATE INDEX entity_type_idx FOR (e:Entity) ON (e.type)
批处理:
- memory_commit支持单轮批量写入UNWIND $triplets减少IO次数
5.2 故障与降级
图库离线:
- 工具返回特定错误码GRAPH_UNAVAILABLE
- 模型进入"无记忆模式":明确告知用户"我暂时无法访问历史记录",而非静默幻觉
写入失败:
- 本地jsonl日志作为WALWrite-Ahead Log后台进程重放
- 模型接收commit_partial_success反馈知道哪些信息已丢失
5.3 监控指标
- 记忆命中率recall返回非空结果的比例衡量查询有效性
- 写入信噪比commit频率 vs 后续recall实际引用的比例
- 类型熵动态创建的entity_types数量及分布防止过度碎片化
### 4. Docker 一键部署
---
```bash
cd docker
./start.sh
```
6. 实验验证路径
1. 基线对比相同长对话任务50+轮对比本架构与32k上下文窗口的事实一致性准确率
2. 消融实验固定recall策略强制每轮查询vs 自主决策,测量查询次数-准确率曲线
3. 压力测试模拟100并发会话监测Neo4j连接池争用及延迟P99
4. 故障注入随机丢弃commit操作验证模型能否通过后续recall发现不一致并修正
## 架构说明
---
- **无上下文**: 每次请求仅带当前输入,不含历史消息
- **图数据库**: 所有记忆存储在 Neo4j 图中
- **自主决策**: 模型自主判断何时查询/写入记忆
这套架构的终极验证是当上下文窗口物理上设为1仅保留当前输入系统能否维持连贯、准确、有记忆的多轮对话。如果成功则证明图外部化完全替代了参数化记忆。
## 文件结构
```
.
├── graph_memory_demo.py # 主程序
├── scripts/ # 各发行版安装脚本
│ ├── install_neo4j_ubuntu.sh
│ ├── install_neo4j_centos.sh
│ ├── install_neo4j_openeuler.sh
│ └── start_neo4j_docker.sh
├── docker/ # Docker 部署
│ ├── docker-compose.yml
│ ├── start.sh
│ └── .env.example
└── README.md
```
## Neo4j 配置
- HTTP: http://localhost:7474
- Bolt: bolt://localhost:7687
- 用户: neo4j / (设置密码)
## 测试验证
```bash
# 测试 Neo4j 连接
cypher-shell -u neo4j -p your_password "MATCH (n) RETURN count(n)"
```

View File

@ -1,6 +1,6 @@
# OpenClaw Docker 部署
# Graph Memory Demo Docker 部署
一键启动 OpenClaw 纯图数据库对话 Demo。
一键启动纯图数据库记忆存储 Demo。
## 快速开始
@ -21,7 +21,7 @@ docker compose up -d
## 启动后
- Neo4j Browser: http://localhost:7474
- 登录用户: neo4j / openclaw123
- 登录用户: neo4j / graph123
- 应用运行在终端交互模式
## 停止
@ -46,4 +46,4 @@ docker/
├── start.sh # 一键启动脚本
├── .env.example # 环境变量模板
└── README.md # 本文件
```
```

View File

@ -3,12 +3,12 @@ version: '3.8'
services:
neo4j:
image: neo4j:5
container_name: openclaw-neo4j
container_name: graph-memory-neo4j
ports:
- "7474:7474"
- "7687:7687"
environment:
- NEO4J_AUTH=neo4j/openclaw123
- NEO4J_AUTH=neo4j/graph123
- NEO4J_PLUGINS=["apoc"]
- NEO4J_server_memory_heap_initial__size=256m
- NEO4J_server_memory_heap_max__size=512m
@ -17,34 +17,41 @@ services:
- neo4j_logs:/logs
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "return cypher-shell -u neo4j -p openclaw123 'RETURN 1' 2>/dev/null || exit 1"]
test: ["CMD-SHELL", "return cypher-shell -u neo4j -p graph123 'RETURN 1' 2>/dev/null || exit 1"]
interval: 30s
timeout: 10s
retries: 5
networks:
- graph-memory-net
openclaw:
demo:
image: python:3.11-slim
container_name: openclaw-app
container_name: graph-memory-app
ports:
- "8000:8000"
environment:
- NEO4J_URI=bolt://neo4j:7687
- NEO4J_USER=neo4j
- NEO4J_PASSWORD=openclaw123
- NEO4J_PASSWORD=graph123
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-your-api-key-here}
volumes:
- ..:/app
- ../openclaw_neo4j_demo.py:/app/openclaw_neo4j_demo.py
working_dir: /app
command: >
sh -c "pip install --quiet neo4j openai && python openclaw_neo4j_demo.py"
sh -c "pip install --quiet neo4j openai && python graph_memory_demo.py"
stdin_open: true
tty: true
depends_on:
neo4j:
condition: service_healthy
restart: unless-stopped
networks:
- graph-memory-net
volumes:
neo4j_data:
neo4j_logs:
neo4j_logs:
networks:
graph-memory-net:
driver: bridge

View File

@ -1,10 +1,10 @@
#!/bin/bash
# OpenClaw Docker 一键启动脚本
# Graph Memory Demo Docker 一键启动脚本
set -e
echo "========================================"
echo "OpenClaw Docker 一键启动"
echo "Graph Memory Demo Docker 一键启动"
echo "========================================"
# 检查 Docker 和 Docker Compose
@ -42,7 +42,7 @@ fi
# 启动服务
echo ""
echo "启动 Neo4j 和 OpenClaw 应用..."
echo "启动 Neo4j 和 Graph Memory Demo 应用..."
$DOCKER_COMPOSE up -d
# 等待 Neo4j 就绪
@ -60,7 +60,7 @@ $DOCKER_COMPOSE ps
echo ""
echo "访问地址:"
echo " Neo4j Browser: http://localhost:7474"
echo " Neo4j 用户: neo4j / openclaw123"
echo " Neo4j 用户: neo4j / graph123"
echo ""
echo "停止服务: docker compose down"
echo "查看日志: docker compose logs -f"

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python3
"""
OpenClaw 纯图数据库调用 Demo - Neo4j 真实数据库版本
Graph Memory Demo - 纯图数据库调用 Demo
基于 DeepSeek API Tool Calls 实现摒弃传统上下文的自主记忆多轮对话
验证目的无上下文纯图数据库记忆存储
"""
import json
@ -507,7 +508,7 @@ def format_recall_result(result: dict) -> str:
return "\n".join(lines)
class OpenClawClient:
class GraphMemoryClient:
def __init__(self, api_key: str, base_url: str, graph: Neo4jGraph):
from openai import OpenAI
self.client = OpenAI(api_key=api_key, base_url=base_url)
@ -516,7 +517,7 @@ class OpenClawClient:
self.system_prompt = self._build_system_prompt()
def _build_system_prompt(self) -> str:
return """你是 OpenClaw 的自主记忆助手。
return """你是图数据库记忆助手。
## 核心职责
你是用户的长期记忆助手每次对话后**必须**主动决定是否需要将关键信息写入记忆图库
@ -597,7 +598,7 @@ query_intent 应该是**逗号分隔的多个关键词**,并包含**同义词/
global CURRENT_TURN
print("\n" + "=" * 60)
print("OpenClaw 纯图数据库对话 Demo (Neo4j)")
print("Graph Memory Demo - 纯图数据库对话 (Neo4j)")
print("=" * 60)
print(f"会话ID: {CURRENT_SESSION_ID}")
print(f"Neo4j: {NEO4J_URI}")
@ -681,7 +682,7 @@ query_intent 应该是**逗号分隔的多个关键词**,并包含**同义词/
def main():
print("OpenClaw Demo - Neo4j 纯图数据库调用的多轮对话")
print("Graph Memory Demo - 纯图数据库调用的多轮对话")
print("-" * 40)
if not DEEPSEEK_API_KEY:
@ -704,7 +705,7 @@ def main():
print("请确保 Neo4j 已启动,或运行 scripts/ 下的安装脚本")
return
client = OpenClawClient(DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, graph)
client = GraphMemoryClient(DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, graph)
client.chat_loop()
graph.close()

View File

@ -14,16 +14,16 @@ if ! command -v docker &> /dev/null; then
fi
# 检查并停止现有容器
if docker ps -a | grep -q openclaw-neo4j; then
if docker ps -a | grep -q graph-memory-neo4j; then
echo "[Info] 停止现有容器..."
docker stop openclaw-neo4j 2>/dev/null || true
docker rm openclaw-neo4j 2>/dev/null || true
docker stop graph-memory-neo4j 2>/dev/null || true
docker rm graph-memory-neo4j 2>/dev/null || true
fi
# 启动 Neo4j
echo "[Info] 启动 Neo4j 容器..."
docker run -d \
--name openclaw-neo4j \
--name graph-memory-neo4j \
-p 7474:7474 \
-p 7687:7687 \
-e NEO4J_AUTH=neo4j/neo4j \
@ -78,8 +78,8 @@ echo ""
echo "远程 Neo4j 配置示例:"
echo " NEO4J_URI=bolt://192.168.1.100:7687 \\"
echo " NEO4J_PASSWORD=your_password \\"
echo " python /home/program/graph_enable_ability/openclaw_neo4j_demo.py"
echo " python /home/program/graph_enable_ability/graph_memory_demo.py"
echo ""
echo "启动对话:"
echo " cd $PROJECT_DIR && source venv/bin/activate"
echo " python /home/program/graph_enable_ability/openclaw_neo4j_demo.py"
echo " python /home/program/graph_enable_ability/graph_memory_demo.py"