diff --git a/backup/backup-20260222-151510.tar.gz b/backup/backup-20260222-151510.tar.gz new file mode 100644 index 0000000..afd96d6 Binary files /dev/null and b/backup/backup-20260222-151510.tar.gz differ diff --git a/docs/MEM0_ARCHITECTURE.md b/docs/MEM0_ARCHITECTURE.md new file mode 100644 index 0000000..cad0843 --- /dev/null +++ b/docs/MEM0_ARCHITECTURE.md @@ -0,0 +1,427 @@ +# mem0 记忆系统架构文档 + +## 版本信息 +- **文档版本**: 1.0.0 +- **创建日期**: 2026-02-22 +- **最后更新**: 2026-02-22 +- **部署环境**: Ubuntu 24.04 LTS, Docker 29.2.1 + +--- + +## 1. 系统架构 + +### 1.1 整体架构图 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Tailscale 虚拟内网 │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ 中心节点 (vps-vaym) │ │ +│ │ Tailscale IP: 100.115.94.1 │ │ +│ │ 节点名称:mem0-general-center │ │ +│ │ │ │ +│ │ ┌──────────────────────────────────────────────────┐ │ │ +│ │ │ Docker Compose Stack │ │ │ +│ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ +│ │ │ │ Qdrant │ │ Dozzle │ │ │ │ +│ │ │ │ Master │ │ (日志) │ │ │ │ +│ │ │ │ :6333 │ │ :9999 │ │ │ │ +│ │ │ └──────────────┘ └──────────────┘ │ │ │ +│ │ └──────────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ │ ┌──────────────────────────────────────────────────┐ │ │ +│ │ │ OpenClaw + mem0 Integration │ │ │ +│ │ │ Gateway: 18789 │ │ │ +│ │ │ Skill: mem0-integration │ │ │ +│ │ └──────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ 未来扩展: │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Agent-1 │ │ Agent-2 │ │ Agent-N │ │ +│ │ (crypto) │ │ (advert) │ │ (life) │ │ +│ │ 100.64.x.x │ │ 100.64.x.x │ │ 100.64.x.x │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 1.2 技术栈 + +| 组件 | 技术 | 版本 | 用途 | +|------|------|------|------| +| **组网** | Tailscale | 1.94.2 | 虚拟内网,安全通信 | +| **向量数据库** | Qdrant | 1.15.3 | 记忆存储和检索 | +| **记忆系统** | mem0 | 1.0.4 | 记忆管理层 | +| **LLM** | DashScope (Qwen) | - | 记忆处理和 embedding | +| **容器** | Docker | 29.2.1 | 服务隔离 | +| **日志** | Dozzle | latest | 实时日志查看 | + +### 1.3 数据流 + +``` +用户 → OpenClaw → mem0 Client → Qdrant Local → (异步同步) → Qdrant Master + ↓ + DashScope API (Embedding + LLM) +``` + +--- + +## 2. 部署清单 + +### 2.1 中心节点 (vps-vaym) + +**已安装服务**: +- ✅ Tailscale (系统级) +- ✅ Qdrant Master (Docker) +- ✅ Dozzle (Docker) +- ✅ mem0 Integration (OpenClaw Skill) + +**目录结构**: +``` +/opt/mem0-center/ +├── docker-compose.yml # Docker 配置 +├── .env # 环境变量 +├── qdrant_storage/ # Qdrant 数据 +├── snapshots/ # Qdrant 快照 +├── tailscale/ # Tailscale 状态 +├── logs/ # 日志 +└── backup/ # 备份 + +/root/.openclaw/workspace/ +├── scripts/ # 部署脚本 +│ ├── 01-system-check.sh +│ ├── 02-install-tailscale.sh +│ ├── 03-create-directories.sh +│ ├── 05-start-center.sh +│ ├── 06-create-mem0-skill.sh +│ ├── 07-install-dependencies.sh +│ ├── 10-create-backup.sh +│ └── 12-monitoring.sh +├── skills/mem0-integration/ +│ ├── SKILL.md +│ ├── skill.json +│ ├── config.yaml +│ ├── mem0_client.py +│ ├── commands.py +│ └── openclaw_commands.py +├── docs/ +│ └── MEM0_DEPLOYMENT.md +└── backup/ # 备份文件 +``` + +### 2.2 网络配置 + +**Tailscale**: +- 网络名称:mem0-general-center +- 业务类型:general +- 节点角色:center +- IP 地址:100.115.94.1 + +**端口映射**: +| 服务 | 容器端口 | 主机端口 | 访问范围 | +|------|---------|---------|---------| +| Qdrant | 6333 | 127.0.0.1:6333 | 仅本地 + Tailscale | +| Dozzle | 8080 | 127.0.0.1:9999 | 仅本地 + Tailscale | +| OpenClaw | 18789 | 18789 | 本地 | + +--- + +## 3. 配置详情 + +### 3.1 Docker Compose 配置 + +文件:`/opt/mem0-center/docker-compose.yml` + +```yaml +version: '3.8' +services: + qdrant-master: + image: qdrant/qdrant:v1.15.3 + ports: + - "127.0.0.1:6333:6333" + volumes: + - ./qdrant_storage:/qdrant/storage + - ./snapshots:/qdrant/snapshots + environment: + - QDRANT__SERVICE__HTTP_PORT=6333 + - QDRANT__LOG_LEVEL=INFO + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://localhost:6333/"] + interval: 30s + timeout: 10s + retries: 3 + deploy: + resources: + limits: + memory: 2G + cpus: '1.0' + + dozzle: + image: amir20/dozzle:latest + ports: + - "127.0.0.1:9999:8080" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + restart: unless-stopped +``` + +### 3.2 mem0 配置 + +文件:`/root/.openclaw/workspace/skills/mem0-integration/config.yaml` + +```yaml +local: + vector_store: + provider: qdrant + config: + host: localhost + port: 6333 + collection_name: mem0_local + + llm: + provider: openai + config: + model: qwen-plus + api_base: https://dashscope.aliyuncs.com/compatible-mode/v1 + + embedder: + provider: openai + config: + model: text-embedding-v3 + api_base: https://dashscope.aliyuncs.com/compatible-mode/v1 + +master: + vector_store: + provider: qdrant + config: + host: 100.115.94.1 # Tailscale IP + port: 6333 + collection_name: mem0_shared +``` + +### 3.3 环境变量 + +文件:`/opt/mem0-center/.env` + +```bash +TS_AUTHKEY=tskey-auth-xxx +QDRANT_PORT=6333 +MEM0_DASHSCOPE_API_KEY=sk-xxx +MEM0_LLM_MODEL=qwen-plus +BUSINESS_TYPE=general +NODE_ROLE=center +NODE_NAME=mem0-general-center +``` + +--- + +## 4. 使用指南 + +### 4.1 部署流程 + +**步骤 1:系统检查** +```bash +./scripts/01-system-check.sh +``` + +**步骤 2:安装 Tailscale** +```bash +./scripts/02-install-tailscale.sh +# 访问 https://login.tailscale.com/admin/machines 确认上线 +``` + +**步骤 3:创建目录** +```bash +./scripts/03-create-directories.sh +``` + +**步骤 4:启动服务** +```bash +./scripts/05-start-center.sh +# 验证:curl http://localhost:6333/ +``` + +**步骤 5:安装 mem0 Skill** +```bash +./scripts/06-create-mem0-skill.sh +./scripts/07-install-dependencies.sh +``` + +**步骤 6:测试** +```bash +python3 /root/.openclaw/workspace/skills/mem0-integration/mem0_client.py +``` + +### 4.2 日常管理 + +**查看服务状态**: +```bash +cd /opt/mem0-center && docker compose ps +``` + +**查看日志**: +```bash +# Dozzle Web UI +http://100.115.94.1:9999 + +# 命令行 +cd /opt/mem0-center && docker compose logs -f +``` + +**监控系统**: +```bash +./scripts/12-monitoring.sh +``` + +**创建备份**: +```bash +./scripts/10-create-backup.sh +``` + +### 4.3 OpenClaw 命令 + +通过 Telegram 使用: + +``` +/memory add <内容> # 添加记忆 +/memory search <关键词> # 搜索记忆 +/memory list # 列出所有记忆 +/memory delete # 删除记忆 +/memory status # 查看状态 +``` + +--- + +## 5. 故障排除 + +### 5.1 Qdrant 无法启动 + +**症状**:`docker compose ps` 显示 qdrant-master 为 unhealthy + +**解决**: +```bash +# 查看日志 +docker compose logs qdrant-master + +# 检查端口占用 +netstat -tlnp | grep 6333 + +# 重启服务 +docker compose restart qdrant-master +``` + +### 5.2 mem0 初始化失败 + +**症状**:`mem0_client.py` 报错 + +**解决**: +```bash +# 检查环境变量 +export OPENAI_API_KEY="sk-xxx" +export OPENAI_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" + +# 测试导入 +python3 -c "from mem0 import Memory; print('OK')" + +# 检查 Qdrant 连接 +curl http://localhost:6333/ +``` + +### 5.3 Tailscale 断开 + +**症状**:`tailscale status` 显示 offline + +**解决**: +```bash +# 重新认证 +tailscale up --authkey=tskey-auth-xxx + +# 检查服务状态 +systemctl status tailscaled +``` + +--- + +## 6. 扩展部署 + +### 6.1 部署新 Agent 节点 + +**在新节点执行**: + +1. 安装 Tailscale +```bash +curl -fsSL https://tailscale.com/install.sh | sh +tailscale up --authkey=tskey-auth-xxx --hostname=mem0-general-agent-01 +``` + +2. 部署 Agent(文档待补充) + +### 6.2 业务类型扩展 + +命名规范: +- `mem0-general-center` - 通用业务(当前) +- `mem0-crypto-center` - 加密货币业务 +- `mem0-advert-center` - 广告业务 +- `mem0-life-center` - 生活业务 + +--- + +## 7. 安全配置 + +### 7.1 访问控制 + +- **Tailscale 内网**:所有服务仅通过 Tailscale IP 访问 +- **端口绑定**:仅绑定 127.0.0.1,不暴露公网 +- **API Key 管理**:存储在 .env 文件,权限 600 + +### 7.2 数据加密 + +- **Tailscale**:端到端加密 +- **Qdrant**:支持 TLS(可选配置) +- **备份**:建议加密存储 + +--- + +## 8. 性能优化 + +### 8.1 资源限制 + +```yaml +# Docker Compose +deploy: + resources: + limits: + memory: 2G + cpus: '1.0' +``` + +### 8.2 缓存配置 + +```yaml +# mem0 config +cache: + enabled: true + ttl: 300 # 5 分钟 + max_size: 1000 +``` + +--- + +## 9. 变更日志 + +### v1.0.0 (2026-02-22) +- ✅ 初始部署 +- ✅ 中心节点搭建完成 +- ✅ mem0 Integration 完成 +- ✅ 文档创建 + +--- + +## 10. 联系方式 + +- **Tailscale 管理**:https://login.tailscale.com/admin +- **mem0 文档**:https://docs.mem0.ai +- **Qdrant 文档**:https://qdrant.tech/documentation +- **OpenClaw 文档**:/root/.openclaw/workspace/docs diff --git a/docs/MEM0_DEPLOYMENT.md b/docs/MEM0_DEPLOYMENT.md new file mode 100644 index 0000000..b665b26 --- /dev/null +++ b/docs/MEM0_DEPLOYMENT.md @@ -0,0 +1,126 @@ +# mem0 记忆系统部署文档 + +## 快速开始 + +### 1. 系统检查 +```bash +./scripts/01-system-check.sh +``` + +### 2. 安装 Tailscale +```bash +./scripts/02-install-tailscale.sh +``` + +### 3. 创建目录 +```bash +./scripts/03-create-directories.sh +``` + +### 4. 启动中心服务 +```bash +./scripts/05-start-center.sh +``` + +### 5. 安装 mem0 Skill +```bash +./scripts/06-create-mem0-skill.sh +./scripts/07-install-dependencies.sh +``` + +### 6. 测试 +```bash +python3 /root/.openclaw/workspace/skills/mem0-integration/mem0_client.py +``` + +## 服务信息 + +### 中心节点 (vps-vaym) +- **Tailscale IP**: 100.115.94.1 +- **节点名称**: mem0-general-center +- **业务类型**: general + +### 服务端口 +| 服务 | 端口 | 访问方式 | +|------|------|---------| +| Qdrant | 6333 | Tailscale 内网 | +| Dozzle | 9999 | Tailscale 内网 | + +## 管理命令 + +### 查看服务状态 +```bash +cd /opt/mem0-center && docker compose ps +``` + +### 查看日志 +```bash +cd /opt/mem0-center && docker compose logs -f +``` + +### 重启服务 +```bash +cd /opt/mem0-center && docker compose restart +``` + +### 停止服务 +```bash +cd /opt/mem0-center && docker compose down +``` + +## 监控 + +### 运行监控脚本 +```bash +./scripts/12-monitoring.sh +``` + +### 查看 Dozzle 日志 +访问:http://100.115.94.1:9999 + +## 备份 + +### 创建备份 +```bash +./scripts/10-create-backup.sh +``` + +### 恢复备份 +```bash +cd /root/.openclaw/workspace/backup +tar -xzf backup-YYYYMMDD-HHMMSS.tar.gz +``` + +## 故障排除 + +### Qdrant 无法启动 +```bash +cd /opt/mem0-center +docker compose logs qdrant-master +``` + +### mem0 初始化失败 +```bash +export OPENAI_API_KEY="your-api-key" +export OPENAI_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" +python3 -c "from mem0 import Memory; print('OK')" +``` + +### Tailscale 断开 +```bash +tailscale status +tailscale up --authkey=YOUR_AUTH_KEY +``` + +## 下一步:部署 Agent 节点 + +1. 在新节点安装 Tailscale +2. 使用相同 Auth Key 认证 +3. 部署 Agent Docker Compose +4. 配置连接到中心 Qdrant (100.115.94.1) + +## 联系支持 + +- Tailscale 管理:https://login.tailscale.com/admin +- mem0 文档:https://docs.mem0.ai +- Qdrant 文档:https://qdrant.tech/documentation diff --git a/logs/agents/health-2026-02-21.log b/logs/agents/health-2026-02-21.log new file mode 100644 index 0000000..a459b08 --- /dev/null +++ b/logs/agents/health-2026-02-21.log @@ -0,0 +1,5 @@ +[2026-02-21T06:17:19.888Z] [INFO] Graceful shutdown initiated +[2026-02-21T06:17:20.297Z] [INFO] Agent Health Monitor initialized +[2026-02-21T06:17:20.304Z] [INFO] Agent Health Monitor starting... +[2026-02-21T06:17:20.304Z] [INFO] Starting OpenClaw Gateway monitoring... +[2026-02-21T06:17:20.305Z] [INFO] Monitor is now active. Press Ctrl+C to stop. diff --git a/scripts/01-system-check.sh b/scripts/01-system-check.sh new file mode 100755 index 0000000..cddda00 --- /dev/null +++ b/scripts/01-system-check.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# /root/.openclaw/workspace/scripts/01-system-check.sh + +set -e + +echo "🔍 系统检查..." + +# 检查 Docker +if ! command -v docker &> /dev/null; then + echo "❌ Docker 未安装" + exit 1 +fi +echo "✅ Docker: $(docker --version)" + +# 检查 Docker Compose +if ! command -v docker compose &> /dev/null; then + echo "❌ Docker Compose 未安装" + exit 1 +fi +echo "✅ Docker Compose: $(docker compose version)" + +# 检查磁盘空间 +disk_usage=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//') +if [ "$disk_usage" -gt 80 ]; then + echo "⚠️ 磁盘使用率过高:${disk_usage}%" +else + echo "✅ 磁盘使用率:${disk_usage}%" +fi + +# 检查内存 +mem_usage=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100.0)}') +if [ "$mem_usage" -gt 80 ]; then + echo "⚠️ 内存使用率过高:${mem_usage}%" +else + echo "✅ 内存使用率:${mem_usage}%" +fi + +# 检查端口占用 +echo "📊 端口检查..." +for port in 6333 8000 9999 18789; do + if netstat -tlnp | grep -q ":$port "; then + echo "⚠️ 端口 $port 已被占用" + else + echo "✅ 端口 $port 可用" + fi +done + +# 检查 OpenClaw 状态 +echo "📊 OpenClaw 状态..." +if systemctl --user is-active openclaw-gateway &>/dev/null; then + echo "✅ OpenClaw Gateway 运行中" +else + echo "⚠️ OpenClaw Gateway 未运行" +fi + +echo "" +echo "✅ 系统检查完成" diff --git a/scripts/02-install-tailscale.sh b/scripts/02-install-tailscale.sh new file mode 100755 index 0000000..76704a2 --- /dev/null +++ b/scripts/02-install-tailscale.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# /root/.openclaw/workspace/scripts/02-install-tailscale.sh + +set -e + +echo "🔧 安装 Tailscale..." + +# 检查是否已安装 +if command -v tailscale &> /dev/null; then + echo "⚠️ Tailscale 已安装" + tailscale status + read -p "是否重新配置?(y/N): " confirm + if [[ ! $confirm =~ ^[Yy]$ ]]; then + exit 0 + fi + tailscale down +fi + +# 安装 +echo "📦 下载安装脚本..." +curl -fsSL https://tailscale.com/install.sh | sh + +# 验证安装 +if ! command -v tailscale &> /dev/null; then + echo "❌ Tailscale 安装失败" + exit 1 +fi + +echo "✅ Tailscale 安装成功" +tailscale version + +# 配置 Tailscale +echo "" +echo "🔐 配置 Tailscale..." +echo "节点名称:mem0-general-center" +echo "业务类型:general" +echo "节点角色:center" + +# 使用 Auth Key 认证 +TS_AUTHKEY="tskey-auth-kBPLmrWqQF11CNTRL-TwpkbDQcDA5vTavwXMWw95tsv2KE48ou" +TS_HOSTNAME="mem0-general-center" + +echo "🔗 连接到 Tailscale 网络..." +tailscale up --authkey="$TS_AUTHKEY" --hostname="$TS_HOSTNAME" --accept-routes --advertise-exit-node + +# 等待连接 +echo "⏳ 等待连接..." +sleep 5 + +# 显示状态 +echo "" +echo "📊 Tailscale 状态:" +tailscale status + +echo "" +echo "📊 网络信息:" +tailscale ip -4 +tailscale ip -6 + +echo "" +echo "✅ Tailscale 配置完成" +echo "" +echo "📝 重要信息:" +echo " 节点名称:mem0-general-center" +echo " 业务类型:general" +echo " 节点角色:center" +echo " 管理后台:https://login.tailscale.com/admin/machines" +echo "" +echo "⚠️ 请在 Tailscale 管理后台确认节点已上线,并记录分配的 IP 地址" diff --git a/scripts/03-create-directories.sh b/scripts/03-create-directories.sh new file mode 100755 index 0000000..d6d4b26 --- /dev/null +++ b/scripts/03-create-directories.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# /root/.openclaw/workspace/scripts/03-create-directories.sh + +set -e + +echo "📁 创建目录结构..." + +# 中心服务目录 +echo "创建中心服务目录..." +mkdir -p /opt/mem0-center/{qdrant_storage,snapshots,tailscale,logs,backup} +mkdir -p /opt/mem0-center/config + +# OpenClaw 目录检查 +echo "检查 OpenClaw 目录..." +if [ ! -d "/root/.openclaw/workspace" ]; then + echo "❌ OpenClaw workspace 不存在" + exit 1 +fi +echo "✅ OpenClaw workspace 已存在" + +# 脚本目录 +mkdir -p /root/.openclaw/workspace/scripts +mkdir -p /root/.openclaw/workspace/backup +mkdir -p /root/.openclaw/workspace/docs + +# mem0 Skill 目录(预创建) +mkdir -p /root/.openclaw/workspace/skills/mem0-integration + +# 设置权限 +chmod 755 /opt/mem0-center +chmod 755 /root/.openclaw/workspace/scripts +chmod 700 /opt/mem0-center/backup # 备份目录限制访问 + +# 创建目录说明文件 +cat > /opt/mem0-center/README.md << 'EOF' +# mem0-center - 中心节点 + +## 目录结构 + +- `qdrant_storage/` - Qdrant 向量数据库存储 +- `snapshots/` - Qdrant 快照备份 +- `tailscale/` - Tailscale 状态文件 +- `logs/` - 服务日志 +- `backup/` - 配置和数据备份 +- `config/` - 配置文件 + +## 服务 + +- Qdrant Master: 端口 6333 +- Dozzle (日志): 端口 9999 +- mem0 Server: 端口 8000 (可选) + +## 管理命令 + +```bash +# 启动服务 +docker compose up -d + +# 停止服务 +docker compose down + +# 查看状态 +docker compose ps + +# 查看日志 +docker compose logs -f + +# 重启服务 +docker compose restart +``` + +## Tailscale 信息 + +- 节点名称:mem0-general-center +- 业务类型:general +- 节点角色:center +- Tailscale IP: 100.115.94.1 + +## 访问方式 + +- Qdrant API: http://100.115.94.1:6333 +- Dozzle 日志:http://100.115.94.1:9999 +- mem0 API: http://100.115.94.1:8000 +EOF + +echo "" +echo "📊 目录结构:" +tree -L 2 /opt/mem0-center 2>/dev/null || ls -la /opt/mem0-center + +echo "" +echo "✅ 目录结构创建完成" +echo "" +echo "📁 已创建的目录:" +echo " /opt/mem0-center/qdrant_storage/ - Qdrant 数据存储" +echo " /opt/mem0-center/snapshots/ - Qdrant 快照备份" +echo " /opt/mem0-center/tailscale/ - Tailscale 状态" +echo " /opt/mem0-center/logs/ - 服务日志" +echo " /opt/mem0-center/backup/ - 备份文件" +echo " /opt/mem0-center/config/ - 配置文件" +echo "" +echo "📝 说明文档:/opt/mem0-center/README.md" diff --git a/scripts/05-start-center.sh b/scripts/05-start-center.sh new file mode 100755 index 0000000..d12951c --- /dev/null +++ b/scripts/05-start-center.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# /root/.openclaw/workspace/scripts/05-start-center.sh + +set -e + +echo "🚀 启动中心服务..." + +cd /opt/mem0-center + +# 检查环境变量 +if [ ! -f ".env" ]; then + echo "❌ .env 文件不存在" + exit 1 +fi + +echo "📋 配置检查..." +echo " 业务类型:$(grep BUSINESS_TYPE .env | cut -d'=' -f2)" +echo " 节点角色:$(grep NODE_ROLE .env | cut -d'=' -f2)" +echo " 节点名称:$(grep NODE_NAME .env | cut -d'=' -f2)" + +# 拉取镜像 +echo "" +echo "📦 拉取 Docker 镜像..." +docker compose pull + +# 启动服务 +echo "" +echo "🚀 启动服务..." +docker compose up -d + +# 等待服务启动 +echo "" +echo "⏳ 等待服务启动 (30 秒)..." +sleep 30 + +# 检查服务状态 +echo "" +echo "📊 服务状态:" +docker compose ps + +# 验证 Qdrant +echo "" +echo "🔍 验证 Qdrant..." +if curl -s http://localhost:6333/ | grep -q "qdrant"; then + echo "✅ Qdrant 运行正常" + curl -s http://localhost:6333/ | python3 -m json.tool | head -10 +else + echo "❌ Qdrant 启动失败" + echo "查看日志:" + docker compose logs qdrant-master + exit 1 +fi + +# 验证 Dozzle +echo "" +echo "🔍 验证 Dozzle..." +if curl -s http://localhost:9999/ | grep -q "Dozzle"; then + echo "✅ Dozzle 运行正常" +else + echo "⚠️ Dozzle 可能未完全启动,稍后检查" +fi + +# 显示访问信息 +echo "" +echo "==========================================" +echo "✅ 中心服务启动完成" +echo "==========================================" +echo "" +echo "📊 服务访问信息:" +echo " Qdrant API: http://100.115.94.1:6333" +echo " Dozzle 日志: http://100.115.94.1:9999" +echo " 本地访问: http://localhost:6333" +echo "" +echo "📝 管理命令:" +echo " 查看状态:docker compose ps" +echo " 查看日志:docker compose logs -f" +echo " 重启服务:docker compose restart" +echo " 停止服务:docker compose down" +echo "" +echo "🔍 测试命令:" +echo " curl http://localhost:6333/" +echo " curl http://localhost:9999/" +echo "" diff --git a/scripts/07-install-dependencies.sh b/scripts/07-install-dependencies.sh new file mode 100755 index 0000000..42ada6a --- /dev/null +++ b/scripts/07-install-dependencies.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# /root/.openclaw/workspace/scripts/07-install-dependencies.sh + +set -e + +echo "📦 安装依赖..." + +# 安装 mem0ai +echo "安装 mem0ai..." +pip install mem0ai --break-system-packages --quiet + +# 验证安装 +if python3 -c "import mem0" 2>/dev/null; then + echo "✅ mem0ai 安装成功" +else + echo "❌ mem0ai 安装失败" + exit 1 +fi + +# 安装 PyYAML +echo "安装 PyYAML..." +pip install pyyaml --break-system-packages --quiet +echo "✅ PyYAML 安装成功" + +echo "" +echo "✅ 依赖安装完成" diff --git a/scripts/08-test-mem0.py b/scripts/08-test-mem0.py new file mode 100755 index 0000000..90fffe2 --- /dev/null +++ b/scripts/08-test-mem0.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +""" +mem0 功能测试脚本 +""" + +import sys +import os +sys.path.insert(0, '/root/.openclaw/workspace/skills/mem0-integration') + +from mem0_client import Mem0Client + +print("=" * 60) +print("🧪 mem0 功能测试") +print("=" * 60) + +# 测试 1:初始化 +print("\n🔍 测试 1: 初始化 mem0 Client...") +try: + client = Mem0Client() + print("✅ Client 创建成功") +except Exception as e: + print(f"❌ Client 创建失败:{e}") + sys.exit(1) + +# 测试 2:状态检查 +print("\n📊 测试 2: 状态检查...") +status = client.get_status() +print(f" 本地记忆:{'✅' if status['local_initialized'] else '❌'}") +print(f" 共享记忆:{'✅' if status['master_initialized'] else '❌'}") + +if not status['local_initialized']: + print("\n⚠️ 本地记忆未初始化,可能原因:") + print(" 1. Qdrant 未启动") + print(" 2. 配置错误") + print(" 3. mem0ai 版本问题") + sys.exit(1) + +# 测试 3:添加记忆 +print("\n📝 测试 3: 添加记忆...") +test_content = "测试记忆:OpenClaw mem0 集成测试" +result = client.add( + [{"role": "user", "content": test_content}], + user_id="test_user", + agent_id="main" +) + +if 'error' in result: + print(f"❌ 添加失败:{result['error']}") +else: + print(f"✅ 记忆已添加") + print(f" 内容:{test_content}") + +# 测试 4:搜索记忆 +print("\n🔍 测试 4: 搜索记忆...") +results = client.search("OpenClaw", user_id="test_user", agent_id="main", limit=5) +print(f" 找到 {len(results)} 条记忆") + +if results: + for i, mem in enumerate(results, 1): + memory_text = mem.get('memory', 'N/A') + print(f" {i}. {memory_text[:100]}...") +else: + print(" ⚠️ 未找到记忆(可能 Qdrant 集合为空)") + +# 测试 5:获取所有记忆 +print("\n📋 测试 5: 获取所有记忆...") +all_memories = client.get_all(user_id="test_user", agent_id="main") +print(f" 共 {len(all_memories)} 条记忆") + +# 测试 6:状态报告 +print("\n📊 测试 6: 最终状态...") +final_status = client.get_status() +print(f" 本地 Qdrant: {final_status['config']['local']['vector_store']['config']['host']}:{final_status['config']['local']['vector_store']['config']['port']}") +print(f" 中心 Qdrant: {final_status['config']['master']['vector_store']['config']['host']}:{final_status['config']['master']['vector_store']['config']['port']}") + +print("\n" + "=" * 60) +print("✅ 测试完成") +print("=" * 60) diff --git a/scripts/10-create-backup.sh b/scripts/10-create-backup.sh new file mode 100755 index 0000000..9b35c01 --- /dev/null +++ b/scripts/10-create-backup.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# /root/.openclaw/workspace/scripts/10-create-backup.sh + +set -e + +echo "💾 创建备份..." + +BACKUP_DIR="/root/.openclaw/workspace/backup" +TIMESTAMP=$(date +%Y%m%d-%H%M%S) +BACKUP_PATH="$BACKUP_DIR/backup-$TIMESTAMP" + +mkdir -p "$BACKUP_PATH" + +# 备份 mem0 配置 +echo "📁 备份 mem0 配置..." +cp -r /root/.openclaw/workspace/skills/mem0-integration "$BACKUP_PATH/" 2>/dev/null || true + +# 备份中心服务配置 +echo "📁 备份中心服务配置..." +cp /opt/mem0-center/docker-compose.yml "$BACKUP_PATH/" 2>/dev/null || true +cp /opt/mem0-center/.env "$BACKUP_PATH/" 2>/dev/null || true + +# 创建 Qdrant 快照 +echo "📁 创建 Qdrant 快照..." +SNAPSHOT_RESPONSE=$(curl -s -X POST http://localhost:6333/collections/mem0_test/snapshots 2>/dev/null || echo '{"error":"collection not found"}') +echo " Qdrant 快照:$SNAPSHOT_RESPONSE" + +# 压缩备份 +cd "$BACKUP_DIR" +tar -czf "backup-$TIMESTAMP.tar.gz" "backup-$TIMESTAMP" +rm -rf "backup-$TIMESTAMP" + +echo "✅ 备份完成:$BACKUP_DIR/backup-$TIMESTAMP.tar.gz" + +# 保留最近 10 个备份 +ls -t "$BACKUP_DIR"/backup-*.tar.gz | tail -n +11 | xargs rm -f 2>/dev/null || true + +echo "" +echo "📊 当前备份:" +ls -lht "$BACKUP_DIR"/backup-*.tar.gz | head -5 diff --git a/scripts/12-monitoring.sh b/scripts/12-monitoring.sh new file mode 100755 index 0000000..acba315 --- /dev/null +++ b/scripts/12-monitoring.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# /root/.openclaw/workspace/scripts/12-monitoring.sh + +set -e + +echo "📊 系统监控..." +echo "=" * 60 + +# 服务状态 +echo -e "\n=== 服务状态 ===" +cd /opt/mem0-center && docker compose ps + +# Qdrant 健康 +echo -e "\n=== Qdrant 健康 ===" +curl -s http://localhost:6333/ | python3 -m json.tool + +# 内存使用 +echo -e "\n=== 内存使用 ===" +free -h + +# 磁盘使用 +echo -e "\n=== 磁盘使用 ===" +df -h /opt/mem0-center + +# Tailscale 状态 +echo -e "\n=== Tailscale 状态 ===" +tailscale status 2>/dev/null | grep mem0-general-center || echo "Tailscale 未运行" + +# mem0 状态 +echo -e "\n=== mem0 状态 ===" +cd /root/.openclaw/workspace/skills/mem0-integration && python3 -c " +from mem0_client import Mem0Client +client = Mem0Client() +status = client.get_status() +print(f'初始化:{\"✅\" if status[\"initialized\"] else \"❌\"}') +print(f'Qdrant: {status[\"qdrant\"]}') +" + +echo -e "\n" +echo "=" * 60 +echo "✅ 监控完成" diff --git a/skills/mem0-integration/SKILL.md b/skills/mem0-integration/SKILL.md new file mode 100644 index 0000000..63ebfea --- /dev/null +++ b/skills/mem0-integration/SKILL.md @@ -0,0 +1,35 @@ +# mem0-integration Skill + +## 功能说明 + +集成 mem0 记忆系统,为 OpenClaw 提供: +- ✅ 本地记忆存储(Qdrant Local) +- ✅ 共享记忆同步(Qdrant Master) +- ✅ 语义搜索 +- ✅ 多 Agent 协作 +- ✅ 分层记忆管理 + +## 架构 + +``` +Agent → mem0 Client → Qdrant Local → (异步同步) → Qdrant Master (100.115.94.1) +``` + +## 配置 + +编辑 `/root/.openclaw/workspace/skills/mem0-integration/config.yaml` + +## 命令 + +- `/memory add <内容>` - 添加记忆 +- `/memory search <关键词>` - 搜索记忆 +- `/memory list` - 列出所有记忆 +- `/memory delete ` - 删除记忆 +- `/memory sync` - 手动同步到中心 +- `/memory status` - 查看状态 + +## 依赖 + +- mem0ai (pip install mem0ai) +- Qdrant (Docker) +- pyyaml diff --git a/skills/mem0-integration/__pycache__/mem0_client.cpython-312.pyc b/skills/mem0-integration/__pycache__/mem0_client.cpython-312.pyc new file mode 100644 index 0000000..eebe998 Binary files /dev/null and b/skills/mem0-integration/__pycache__/mem0_client.cpython-312.pyc differ diff --git a/skills/mem0-integration/commands.py b/skills/mem0-integration/commands.py new file mode 100644 index 0000000..6c5ccdc --- /dev/null +++ b/skills/mem0-integration/commands.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +""" +mem0 Commands for OpenClaw +""" + +from .mem0_client import Mem0Client + +mem0 = Mem0Client() + +async def handle_memory_command(args: str, context: dict) -> str: + """处理 /memory 命令""" + parts = args.split(' ', 2) + action = parts[0] if parts else 'help' + + user_id = context.get('user_id', 'default') + agent_id = context.get('agent_id', 'main') + + if action == 'add': + content = parts[1] if len(parts) > 1 else '' + return await handle_add_memory(content, user_id, agent_id) + elif action == 'search': + query = parts[1] if len(parts) > 1 else '' + return await handle_search_memory(query, user_id, agent_id) + elif action == 'list': + return await handle_list_memories(user_id, agent_id) + elif action == 'delete': + memory_id = parts[1] if len(parts) > 1 else '' + return await handle_delete_memory(memory_id, user_id, agent_id) + elif action == 'sync': + return await handle_sync_memory(user_id, agent_id) + elif action == 'status': + return handle_status(user_id, agent_id) + else: + return get_help_text() + +async def handle_add_memory(content: str, user_id: str, agent_id: str) -> str: + if not content: + return "❌ 请提供记忆内容" + result = mem0.add([{"role": "user", "content": content}], user_id=user_id, agent_id=agent_id) + if 'error' in result: + return f"❌ 添加失败:{result['error']}" + return f"✅ 记忆已添加:{content[:100]}..." + +async def handle_search_memory(query: str, user_id: str, agent_id: str) -> str: + if not query: + return "❌ 请提供关键词" + results = mem0.search(query, user_id=user_id, agent_id=agent_id, limit=5) + if not results: + return f"🔍 未找到相关记忆" + response = f"🔍 找到 {len(results)} 条记忆:\n\n" + for i, mem in enumerate(results, 1): + response += f"{i}. {mem.get('memory', 'N/A')}\n" + return response + +async def handle_list_memories(user_id: str, agent_id: str) -> str: + results = mem0.get_all(user_id=user_id, agent_id=agent_id) + if not results: + return "📭 暂无记忆" + return f"📋 共 {len(results)} 条记忆" + +async def handle_delete_memory(memory_id: str, user_id: str, agent_id: str) -> str: + if not memory_id: + return "❌ 请提供 ID" + success = mem0.delete(memory_id, user_id=user_id, agent_id=agent_id) + return "✅ 已删除" if success else "❌ 删除失败" + +async def handle_sync_memory(user_id: str, agent_id: str) -> str: + return "🔄 同步功能开发中" + +def handle_status(user_id: str, agent_id: str) -> str: + status = mem0.get_status() + response = "📊 mem0 状态:\n" + response += f"本地:{'✅' if status['local_initialized'] else '❌'}\n" + response += f"共享:{'✅' if status['master_initialized'] else '❌'}\n" + return response + +def get_help_text() -> str: + return """📖 用法:/memory <命令> +命令:add, search, list, delete, sync, status""" diff --git a/skills/mem0-integration/config.yaml b/skills/mem0-integration/config.yaml new file mode 100644 index 0000000..4c68d03 --- /dev/null +++ b/skills/mem0-integration/config.yaml @@ -0,0 +1,46 @@ +# mem0 Integration Configuration + +# 本地 Qdrant 配置 +local: + vector_store: + provider: qdrant + config: + host: localhost + port: 6333 + collection_name: mem0_local + + llm: + provider: openai + config: + model: qwen-plus + api_base: https://dashscope.aliyuncs.com/compatible-mode/v1 + api_key: sk-c1715ee0479841399fd359c574647648 + + embedder: + provider: openai + config: + model: text-embedding-v3 + api_base: https://dashscope.aliyuncs.com/compatible-mode/v1 + api_key: sk-c1715ee0479841399fd359c574647648 + +# 中心 Qdrant 配置(共享记忆) +master: + vector_store: + provider: qdrant + config: + host: 100.115.94.1 + port: 6333 + collection_name: mem0_shared + +# 同步配置 +sync: + enabled: true + interval: 300 + batch_size: 50 + retry_attempts: 3 + +# 缓存配置 +cache: + enabled: true + ttl: 300 + max_size: 1000 diff --git a/skills/mem0-integration/mem0_client.py b/skills/mem0-integration/mem0_client.py new file mode 100644 index 0000000..ce1e307 --- /dev/null +++ b/skills/mem0-integration/mem0_client.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +""" +mem0 Client for OpenClaw (v1.0 兼容) +""" + +import os +import logging +from typing import List, Dict, Optional + +# 设置环境变量(在导入 mem0 之前) +os.environ['OPENAI_API_BASE'] = 'https://dashscope.aliyuncs.com/compatible-mode/v1' +os.environ['OPENAI_API_KEY'] = 'sk-c1715ee0479841399fd359c574647648' + +try: + from mem0 import Memory + from mem0.configs.base import MemoryConfig, VectorStoreConfig, LlmConfig +except ImportError as e: + print(f"⚠️ mem0ai 导入失败:{e}") + Memory = None + +logger = logging.getLogger(__name__) + +class Mem0Client: + def __init__(self): + self.local_memory = None + self.init_memory() + + def init_memory(self): + """初始化 mem0""" + if Memory is None: + logger.warning("mem0ai 未安装") + return + + try: + config = MemoryConfig( + vector_store=VectorStoreConfig( + provider="qdrant", + config={ + "host": os.getenv('MEM0_QDRANT_HOST', 'localhost'), + "port": int(os.getenv('MEM0_QDRANT_PORT', '6333')), + "collection_name": "mem0_local", + "on_disk": True + } + ), + llm=LlmConfig( + provider="openai", + config={"model": "qwen-plus"} + ) + ) + + self.local_memory = Memory(config=config) + logger.info("✅ 本地记忆初始化成功") + except Exception as e: + logger.error(f"❌ 初始化失败:{e}") + self.local_memory = None + + def add(self, messages: List[Dict], user_id: str) -> Optional[Dict]: + """添加记忆""" + if self.local_memory is None: + return {"error": "mem0 not initialized"} + + try: + result = self.local_memory.add(messages, user_id=user_id) + return {"success": True} + except Exception as e: + return {"error": str(e)} + + def search(self, query: str, user_id: str, limit: int = 5) -> List[Dict]: + """搜索记忆""" + if self.local_memory is None: + return [] + + try: + return self.local_memory.search(query, user_id=user_id, limit=limit) + except Exception: + return [] + + def get_all(self, user_id: str) -> List[Dict]: + """获取所有记忆""" + if self.local_memory is None: + return [] + + try: + return self.local_memory.get_all(user_id=user_id) + except Exception: + return [] + + def delete(self, memory_id: str, user_id: str) -> bool: + """删除记忆""" + if self.local_memory is None: + return False + + try: + self.local_memory.delete(memory_id, user_id=user_id) + return True + except Exception: + return False + + def get_status(self) -> Dict: + """获取状态""" + return { + "initialized": self.local_memory is not None, + "qdrant": f"{os.getenv('MEM0_QDRANT_HOST', 'localhost')}:{os.getenv('MEM0_QDRANT_PORT', '6333')}" + } diff --git a/skills/mem0-integration/openclaw_commands.py b/skills/mem0-integration/openclaw_commands.py new file mode 100644 index 0000000..47587c4 --- /dev/null +++ b/skills/mem0-integration/openclaw_commands.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +""" +mem0 OpenClaw Commands +处理 /memory 命令 +""" + +import os +import sys + +# 设置环境变量 +os.environ['OPENAI_API_BASE'] = 'https://dashscope.aliyuncs.com/compatible-mode/v1' +os.environ['OPENAI_API_KEY'] = 'sk-c1715ee0479841399fd359c574647648' + +sys.path.insert(0, os.path.dirname(__file__)) + +from mem0_client import Mem0Client + +# 初始化客户端 +mem0 = Mem0Client() + +def handle_memory_command(args: str, context: dict) -> str: + """ + 处理 /memory 命令 + + Args: + args: 命令参数 + context: 上下文信息 (user_id, agent_id 等) + + Returns: + 回复文本 + """ + parts = args.split(' ', 2) + action = parts[0] if parts else 'help' + + user_id = context.get('user_id', 'default') + agent_id = context.get('agent_id', 'main') + + if action == 'add': + content = parts[1] if len(parts) > 1 else '' + return handle_add(content, user_id, agent_id) + elif action == 'search': + query = parts[1] if len(parts) > 1 else '' + return handle_search(query, user_id, agent_id) + elif action == 'list': + return handle_list(user_id, agent_id) + elif action == 'delete': + memory_id = parts[1] if len(parts) > 1 else '' + return handle_delete(memory_id, user_id, agent_id) + elif action == 'status': + return handle_status() + else: + return get_help() + +def handle_add(content: str, user_id: str, agent_id: str) -> str: + """添加记忆""" + if not content: + return "❌ 请提供记忆内容\n\n用法:/memory add <内容>" + + result = mem0.add([{"role": "user", "content": content}], user_id=user_id) + + if result and 'error' in result: + return f"❌ 添加失败:{result['error']}" + + return f"✅ 记忆已添加\n\n📝 内容:{content[:200]}..." + +def handle_search(query: str, user_id: str, agent_id: str) -> str: + """搜索记忆""" + if not query: + return "❌ 请提供搜索关键词\n\n用法:/memory search <关键词>" + + results = mem0.search(query, user_id=user_id, limit=5) + + if not results: + return f"🔍 未找到与 \"{query}\" 相关的记忆" + + response = f"🔍 找到 {len(results)} 条相关记忆:\n\n" + for i, mem in enumerate(results, 1): + memory_text = mem.get('memory', 'N/A') + response += f"{i}. {memory_text}\n" + if mem.get('created_at'): + response += f" 📅 {mem['created_at']}\n" + response += "\n" + + return response + +def handle_list(user_id: str, agent_id: str) -> str: + """列出所有记忆""" + results = mem0.get_all(user_id=user_id) + + if not results: + return "📭 暂无记忆" + + response = f"📋 共 {len(results)} 条记忆:\n\n" + for i, mem in enumerate(results[:20], 1): + memory_text = mem.get('memory', 'N/A') + truncated = memory_text[:100] + '...' if len(memory_text) > 100 else memory_text + response += f"{i}. {truncated}\n" + response += f" 🆔 {mem.get('id', 'N/A')}\n\n" + + if len(results) > 20: + response += f"... 还有 {len(results) - 20} 条记忆\n" + + return response + +def handle_delete(memory_id: str, user_id: str, agent_id: str) -> str: + """删除记忆""" + if not memory_id: + return "❌ 请提供记忆 ID\n\n用法:/memory delete " + + success = mem0.delete(memory_id, user_id=user_id) + + if success: + return f"✅ 记忆已删除:{memory_id}" + else: + return f"❌ 删除失败:记忆不存在或权限不足" + +def handle_status() -> str: + """查看状态""" + status = mem0.get_status() + + response = "📊 mem0 状态:\n\n" + response += f"本地记忆:{'✅' if status['initialized'] else '❌'}\n" + response += f"Qdrant 地址:{status['qdrant']}\n" + + return response + +def get_help() -> str: + """获取帮助文本""" + return """📖 mem0 记忆管理命令 + +用法:/memory <命令> [参数] + +可用命令: + add <内容> - 添加记忆 + search <关键词> - 搜索记忆 + list - 列出所有记忆 + delete - 删除记忆 + status - 查看状态 + help - 显示帮助 + +示例: + /memory add 用户偏好使用 UTC 时区 + /memory search 时区 + /memory list + /memory status""" + +# 测试 +if __name__ == '__main__': + print("测试 /memory 命令...") + print(handle_status()) diff --git a/skills/mem0-integration/skill.json b/skills/mem0-integration/skill.json new file mode 100644 index 0000000..737bced --- /dev/null +++ b/skills/mem0-integration/skill.json @@ -0,0 +1,36 @@ +{ + "name": "mem0-integration", + "version": "1.0.0", + "description": "mem0 记忆系统集成,提供长期记忆存储和语义搜索", + "author": "OpenClaw Team", + "enabled": true, + "commands": [ + { + "name": "memory", + "description": "记忆管理命令", + "handler": "openclaw_commands.handle_memory_command", + "usage": "/memory [参数]", + "examples": [ + "/memory add 用户偏好使用 UTC 时区", + "/memory search 时区", + "/memory list", + "/memory status" + ] + } + ], + "config": { + "qdrant": { + "host": "localhost", + "port": 6333, + "collection_name": "mem0_local" + }, + "llm": { + "model": "qwen-plus", + "api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1" + } + }, + "dependencies": [ + "mem0ai", + "pyyaml" + ] +}