From 7036390772b8b15b45213a123d99c87f8a676560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eason=20=28=E9=99=88=E5=8C=BB=E7=94=9F=29?= Date: Sun, 22 Feb 2026 15:44:44 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20mem0=20=E8=AE=B0=E5=BF=86=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=AE=8C=E6=95=B4=E9=83=A8=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增内容: - 完整的架构文档 (docs/MEM0_ARCHITECTURE.md) - 部署指南 (docs/MEM0_DEPLOYMENT.md) - 部署脚本 (scripts/01-12.sh) - mem0 Integration Skill (skills/mem0-integration/) - 备份和监控脚本 已完成功能: ✅ Tailscale 组网 (100.115.94.1) ✅ Qdrant Master 向量数据库 ✅ Dozzle 日志系统 ✅ mem0 记忆管理 ✅ OpenClaw /memory 命令 ✅ 自动备份系统 ✅ 监控系统 架构特点: - 中心化部署,支持多 Agent 扩展 - Tailscale 内网安全通信 - 分层记忆架构 (本地 + 共享) - 一键部署和回滚 - 完整的文档和脚本 --- backup/backup-20260222-151510.tar.gz | Bin 0 -> 6517 bytes docs/MEM0_ARCHITECTURE.md | 427 ++++++++++++++++++ docs/MEM0_DEPLOYMENT.md | 126 ++++++ logs/agents/health-2026-02-21.log | 5 + scripts/01-system-check.sh | 57 +++ scripts/02-install-tailscale.sh | 69 +++ scripts/03-create-directories.sh | 101 +++++ scripts/05-start-center.sh | 83 ++++ scripts/07-install-dependencies.sh | 26 ++ scripts/08-test-mem0.py | 78 ++++ scripts/10-create-backup.sh | 40 ++ scripts/12-monitoring.sh | 41 ++ skills/mem0-integration/SKILL.md | 35 ++ .../__pycache__/mem0_client.cpython-312.pyc | Bin 0 -> 4755 bytes skills/mem0-integration/commands.py | 79 ++++ skills/mem0-integration/config.yaml | 46 ++ skills/mem0-integration/mem0_client.py | 104 +++++ skills/mem0-integration/openclaw_commands.py | 150 ++++++ skills/mem0-integration/skill.json | 36 ++ 19 files changed, 1503 insertions(+) create mode 100644 backup/backup-20260222-151510.tar.gz create mode 100644 docs/MEM0_ARCHITECTURE.md create mode 100644 docs/MEM0_DEPLOYMENT.md create mode 100644 logs/agents/health-2026-02-21.log create mode 100755 scripts/01-system-check.sh create mode 100755 scripts/02-install-tailscale.sh create mode 100755 scripts/03-create-directories.sh create mode 100755 scripts/05-start-center.sh create mode 100755 scripts/07-install-dependencies.sh create mode 100755 scripts/08-test-mem0.py create mode 100755 scripts/10-create-backup.sh create mode 100755 scripts/12-monitoring.sh create mode 100644 skills/mem0-integration/SKILL.md create mode 100644 skills/mem0-integration/__pycache__/mem0_client.cpython-312.pyc create mode 100644 skills/mem0-integration/commands.py create mode 100644 skills/mem0-integration/config.yaml create mode 100644 skills/mem0-integration/mem0_client.py create mode 100644 skills/mem0-integration/openclaw_commands.py create mode 100644 skills/mem0-integration/skill.json diff --git a/backup/backup-20260222-151510.tar.gz b/backup/backup-20260222-151510.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..afd96d6b354723a05dba6cf9350a5781caacfe27 GIT binary patch literal 6517 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 b000000000000000{4ab5@3_eK0C)fZDm45M literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..eebe998f179b80dafe00f820467082ff97cca06f GIT binary patch literal 4755 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 PW_qK$bq6!O1Ka-rw*6eB literal 0 HcmV?d00001 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" + ] +}