Compare commits
No commits in common. '6a84c4abac8de229f977baf6d3f37e20a0fbd32d' and '560ad52bdaa2017b02d2ff9197fe2abfe6e25f0b' have entirely different histories.
6a84c4abac
...
560ad52bda
47 changed files with 277 additions and 3860 deletions
@ -1,40 +0,0 @@ |
|||||||
# 敏感配置(包含 API keys、密码等) |
|
||||||
openclaw-config.json |
|
||||||
skills/*/config.yaml |
|
||||||
skills/*/.env |
|
||||||
*.env |
|
||||||
*.pem |
|
||||||
*.key |
|
||||||
|
|
||||||
# 日志和缓存 |
|
||||||
logs/ |
|
||||||
*.pyc |
|
||||||
__pycache__/ |
|
||||||
.cache/ |
|
||||||
.pytest_cache/ |
|
||||||
|
|
||||||
# 运行时 |
|
||||||
.pid |
|
||||||
*.pid |
|
||||||
*.log |
|
||||||
|
|
||||||
# 记忆文件(每日日志量大,单独备份) |
|
||||||
memory/*.md |
|
||||||
!memory/.gitkeep |
|
||||||
|
|
||||||
# 备份目录 |
|
||||||
backup/ |
|
||||||
|
|
||||||
# 系统文件 |
|
||||||
.DS_Store |
|
||||||
Thumbs.db |
|
||||||
*.swp |
|
||||||
*.swo |
|
||||||
*~ |
|
||||||
|
|
||||||
# Node modules(如果有) |
|
||||||
node_modules/ |
|
||||||
|
|
||||||
# Python 虚拟环境 |
|
||||||
venv/ |
|
||||||
.venv/ |
|
||||||
Binary file not shown.
@ -1,365 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
|
|
||||||
############################################################################### |
|
||||||
# OpenClaw System Deployment & Management Script |
|
||||||
# |
|
||||||
# Features: |
|
||||||
# - One-click deployment of OpenClaw with systemd services |
|
||||||
# - Auto-healing configuration |
|
||||||
# - Health monitoring |
|
||||||
# - Rollback support via git |
|
||||||
# - Telegram notifications |
|
||||||
# |
|
||||||
# Usage: |
|
||||||
# ./deploy.sh install - Install and start all services |
|
||||||
# ./deploy.sh start - Start all services |
|
||||||
# ./deploy.sh stop - Stop all services |
|
||||||
# ./deploy.sh restart - Restart all services |
|
||||||
# ./deploy.sh status - Show service status |
|
||||||
# ./deploy.sh logs - Show recent logs |
|
||||||
# ./deploy.sh rollback - Rollback to previous git commit |
|
||||||
# ./deploy.sh backup - Create backup of current state |
|
||||||
############################################################################### |
|
||||||
|
|
||||||
set -e |
|
||||||
|
|
||||||
WORKSPACE="/root/.openclaw/workspace" |
|
||||||
LOG_DIR="/root/.openclaw/workspace/logs/system" |
|
||||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S) |
|
||||||
|
|
||||||
# Colors for output |
|
||||||
RED='\033[0;31m' |
|
||||||
GREEN='\033[0;32m' |
|
||||||
YELLOW='\033[1;33m' |
|
||||||
BLUE='\033[0;34m' |
|
||||||
NC='\033[0m' # No Color |
|
||||||
|
|
||||||
log_info() { |
|
||||||
echo -e "${BLUE}[INFO]${NC} $1" |
|
||||||
} |
|
||||||
|
|
||||||
log_success() { |
|
||||||
echo -e "${GREEN}[SUCCESS]${NC} $1" |
|
||||||
} |
|
||||||
|
|
||||||
log_warning() { |
|
||||||
echo -e "${YELLOW}[WARNING]${NC} $1" |
|
||||||
} |
|
||||||
|
|
||||||
log_error() { |
|
||||||
echo -e "${RED}[ERROR]${NC} $1" |
|
||||||
} |
|
||||||
|
|
||||||
ensure_log_dir() { |
|
||||||
mkdir -p "$LOG_DIR" |
|
||||||
} |
|
||||||
|
|
||||||
install_services() { |
|
||||||
log_info "Installing OpenClaw systemd services..." |
|
||||||
|
|
||||||
# Step 1: Enable linger for user-level systemd (CRITICAL for VPS/server deployments) |
|
||||||
log_info "Enabling user linger for persistent user-level services..." |
|
||||||
loginctl enable-linger $(whoami) |
|
||||||
|
|
||||||
# Step 2: Export required environment variables |
|
||||||
export XDG_RUNTIME_DIR=/run/user/$(id -u) |
|
||||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" |
|
||||||
|
|
||||||
# Verify environment |
|
||||||
if [ ! -d "$XDG_RUNTIME_DIR" ]; then |
|
||||||
log_error "XDG_RUNTIME_DIR not found: $XDG_RUNTIME_DIR" |
|
||||||
log_warning "Creating runtime directory..." |
|
||||||
mkdir -p "$XDG_RUNTIME_DIR" |
|
||||||
chmod 700 "$XDG_RUNTIME_DIR" |
|
||||||
fi |
|
||||||
|
|
||||||
# Step 3: Install user-level gateway service |
|
||||||
log_info "Installing user-level gateway service..." |
|
||||||
mkdir -p ~/.config/systemd/user/ |
|
||||||
cp "$WORKSPACE/systemd/openclaw-gateway-user.service" ~/.config/systemd/user/openclaw-gateway.service |
|
||||||
|
|
||||||
# Reload user systemd daemon |
|
||||||
systemctl --user daemon-reload |
|
||||||
systemctl --user enable openclaw-gateway |
|
||||||
|
|
||||||
# Step 4: Install system-level agent monitor (independent of user session) |
|
||||||
log_info "Installing system-level agent monitor..." |
|
||||||
cp "$WORKSPACE/systemd/openclaw-agent-monitor.service" /etc/systemd/system/ |
|
||||||
systemctl daemon-reload |
|
||||||
systemctl enable openclaw-agent-monitor |
|
||||||
|
|
||||||
# Step 5: Start services |
|
||||||
log_info "Starting services..." |
|
||||||
systemctl --user start openclaw-gateway |
|
||||||
systemctl start openclaw-agent-monitor |
|
||||||
|
|
||||||
# Wait for gateway to be ready |
|
||||||
sleep 3 |
|
||||||
|
|
||||||
log_success "OpenClaw services installed and started!" |
|
||||||
log_info "Gateway: ws://localhost:18789" |
|
||||||
log_info "Dashboard: http://localhost:18789/" |
|
||||||
log_info "User service logs: journalctl --user -u openclaw-gateway -f" |
|
||||||
log_info "Monitor logs: journalctl -u openclaw-agent-monitor -f" |
|
||||||
} |
|
||||||
|
|
||||||
start_services() { |
|
||||||
log_info "Starting OpenClaw services..." |
|
||||||
|
|
||||||
# Set up environment for user-level services |
|
||||||
export XDG_RUNTIME_DIR=/run/user/$(id -u) |
|
||||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" |
|
||||||
|
|
||||||
systemctl --user start openclaw-gateway |
|
||||||
systemctl start openclaw-agent-monitor |
|
||||||
log_success "Services started!" |
|
||||||
} |
|
||||||
|
|
||||||
stop_services() { |
|
||||||
log_info "Stopping OpenClaw services..." |
|
||||||
|
|
||||||
# Set up environment for user-level services |
|
||||||
export XDG_RUNTIME_DIR=/run/user/$(id -u) |
|
||||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" |
|
||||||
|
|
||||||
systemctl --user stop openclaw-gateway |
|
||||||
systemctl stop openclaw-agent-monitor |
|
||||||
log_success "Services stopped!" |
|
||||||
} |
|
||||||
|
|
||||||
restart_services() { |
|
||||||
log_info "Restarting OpenClaw services..." |
|
||||||
|
|
||||||
# Set up environment for user-level services |
|
||||||
export XDG_RUNTIME_DIR=/run/user/$(id -u) |
|
||||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" |
|
||||||
|
|
||||||
systemctl --user restart openclaw-gateway |
|
||||||
systemctl restart openclaw-agent-monitor |
|
||||||
log_success "Services restarted!" |
|
||||||
} |
|
||||||
|
|
||||||
show_status() { |
|
||||||
# Set up environment for user-level services |
|
||||||
export XDG_RUNTIME_DIR=/run/user/$(id -u) |
|
||||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" |
|
||||||
|
|
||||||
echo "" |
|
||||||
log_info "=== OpenClaw Gateway Status (User Service) ===" |
|
||||||
systemctl --user status openclaw-gateway --no-pager -l |
|
||||||
echo "" |
|
||||||
log_info "=== Agent Monitor Status (System Service) ===" |
|
||||||
systemctl status openclaw-agent-monitor --no-pager -l |
|
||||||
echo "" |
|
||||||
log_info "=== Recent Gateway Logs ===" |
|
||||||
journalctl --user -u openclaw-gateway --no-pager -n 15 |
|
||||||
echo "" |
|
||||||
log_info "=== Recent Monitor Logs ===" |
|
||||||
journalctl -u openclaw-agent-monitor --no-pager -n 15 |
|
||||||
} |
|
||||||
|
|
||||||
show_logs() { |
|
||||||
# Set up environment for user-level services |
|
||||||
export XDG_RUNTIME_DIR=/run/user/$(id -u) |
|
||||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" |
|
||||||
|
|
||||||
log_info "Showing recent gateway logs (last 50 lines)..." |
|
||||||
journalctl --user -u openclaw-gateway --no-pager -n 50 |
|
||||||
echo "" |
|
||||||
log_info "Showing recent monitor logs (last 50 lines)..." |
|
||||||
journalctl -u openclaw-agent-monitor --no-pager -n 50 |
|
||||||
} |
|
||||||
|
|
||||||
rollback() { |
|
||||||
log_warning "This will rollback the workspace to the previous git commit!" |
|
||||||
read -p "Are you sure? (y/N): " confirm |
|
||||||
|
|
||||||
if [[ $confirm =~ ^[Yy]$ ]]; then |
|
||||||
cd "$WORKSPACE" |
|
||||||
|
|
||||||
# Create backup before rollback |
|
||||||
backup |
|
||||||
|
|
||||||
# Show current commit |
|
||||||
log_info "Current commit:" |
|
||||||
git log -1 --oneline |
|
||||||
|
|
||||||
# Rollback |
|
||||||
git reset --hard HEAD~1 |
|
||||||
|
|
||||||
log_success "Rolled back to previous commit!" |
|
||||||
log_info "Restarting services to apply changes..." |
|
||||||
restart_services |
|
||||||
else |
|
||||||
log_info "Rollback cancelled." |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
rollback_to() { |
|
||||||
if [ -z "$1" ]; then |
|
||||||
log_error "Please specify a commit hash or tag" |
|
||||||
exit 1 |
|
||||||
fi |
|
||||||
|
|
||||||
log_warning "This will rollback the workspace to commit: $1" |
|
||||||
read -p "Are you sure? (y/N): " confirm |
|
||||||
|
|
||||||
if [[ $confirm =~ ^[Yy]$ ]]; then |
|
||||||
cd "$WORKSPACE" |
|
||||||
backup |
|
||||||
git reset --hard "$1" |
|
||||||
log_success "Rolled back to commit: $1" |
|
||||||
restart_services |
|
||||||
else |
|
||||||
log_info "Rollback cancelled." |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
backup() { |
|
||||||
local backup_dir="/root/.openclaw/backups" |
|
||||||
mkdir -p "$backup_dir" |
|
||||||
|
|
||||||
log_info "Creating backup..." |
|
||||||
|
|
||||||
# Backup workspace |
|
||||||
tar -czf "$backup_dir/workspace-$TIMESTAMP.tar.gz" \ |
|
||||||
--exclude='.git' \ |
|
||||||
--exclude='logs' \ |
|
||||||
-C /root/.openclaw workspace |
|
||||||
|
|
||||||
# Backup config |
|
||||||
cp /root/.openclaw/openclaw.json "$backup_dir/openclaw-config-$TIMESTAMP.json" 2>/dev/null || true |
|
||||||
|
|
||||||
log_success "Backup created: $backup_dir/workspace-$TIMESTAMP.tar.gz" |
|
||||||
} |
|
||||||
|
|
||||||
health_check() { |
|
||||||
log_info "Running health check..." |
|
||||||
|
|
||||||
# Set up environment for user-level services |
|
||||||
export XDG_RUNTIME_DIR=/run/user/$(id -u) |
|
||||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" |
|
||||||
|
|
||||||
local issues=0 |
|
||||||
|
|
||||||
# Check gateway (user-level service) |
|
||||||
if systemctl --user is-active --quiet openclaw-gateway 2>/dev/null; then |
|
||||||
log_success "✓ Gateway is running (user service)" |
|
||||||
else |
|
||||||
log_error "✗ Gateway is not running" |
|
||||||
((issues++)) |
|
||||||
fi |
|
||||||
|
|
||||||
# Check monitor (system-level service) |
|
||||||
if systemctl is-active --quiet openclaw-agent-monitor; then |
|
||||||
log_success "✓ Agent Monitor is running (system service)" |
|
||||||
else |
|
||||||
log_error "✗ Agent Monitor is not running" |
|
||||||
((issues++)) |
|
||||||
fi |
|
||||||
|
|
||||||
# Check disk space |
|
||||||
local disk_usage=$(df -h /root | tail -1 | awk '{print $5}' | sed 's/%//') |
|
||||||
if [ "$disk_usage" -lt 80 ]; then |
|
||||||
log_success "✓ Disk usage: ${disk_usage}%" |
|
||||||
else |
|
||||||
log_warning "⚠ Disk usage: ${disk_usage}%" |
|
||||||
((issues++)) |
|
||||||
fi |
|
||||||
|
|
||||||
# Check memory |
|
||||||
local mem_usage=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100.0)}') |
|
||||||
if [ "$mem_usage" -lt 80 ]; then |
|
||||||
log_success "✓ Memory usage: ${mem_usage}%" |
|
||||||
else |
|
||||||
log_warning "⚠ Memory usage: ${mem_usage}%" |
|
||||||
((issues++)) |
|
||||||
fi |
|
||||||
|
|
||||||
# Check XDG_RUNTIME_DIR |
|
||||||
if [ -d "$XDG_RUNTIME_DIR" ]; then |
|
||||||
log_success "✓ XDG_RUNTIME_DIR exists: $XDG_RUNTIME_DIR" |
|
||||||
else |
|
||||||
log_warning "⚠ XDG_RUNTIME_DIR not found" |
|
||||||
((issues++)) |
|
||||||
fi |
|
||||||
|
|
||||||
# Check linger status |
|
||||||
if loginctl show-user $(whoami) -p Linger | grep -q "yes"; then |
|
||||||
log_success "✓ User linger is enabled" |
|
||||||
else |
|
||||||
log_warning "⚠ User linger is NOT enabled (run: loginctl enable-linger)" |
|
||||||
((issues++)) |
|
||||||
fi |
|
||||||
|
|
||||||
echo "" |
|
||||||
if [ $issues -eq 0 ]; then |
|
||||||
log_success "All health checks passed!" |
|
||||||
return 0 |
|
||||||
else |
|
||||||
log_error "$issues health check(s) failed!" |
|
||||||
return 1 |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
show_help() { |
|
||||||
echo "OpenClaw System Management Script" |
|
||||||
echo "" |
|
||||||
echo "Usage: $0 <command>" |
|
||||||
echo "" |
|
||||||
echo "Commands:" |
|
||||||
echo " install - Install and start all systemd services" |
|
||||||
echo " start - Start all services" |
|
||||||
echo " stop - Stop all services" |
|
||||||
echo " restart - Restart all services" |
|
||||||
echo " status - Show service status" |
|
||||||
echo " logs - Show recent logs" |
|
||||||
echo " health - Run health check" |
|
||||||
echo " backup - Create backup of current state" |
|
||||||
echo " rollback - Rollback to previous git commit" |
|
||||||
echo " rollback-to <commit> - Rollback to specific commit" |
|
||||||
echo " help - Show this help message" |
|
||||||
echo "" |
|
||||||
} |
|
||||||
|
|
||||||
# Main |
|
||||||
case "${1:-help}" in |
|
||||||
install) |
|
||||||
install_services |
|
||||||
;; |
|
||||||
start) |
|
||||||
start_services |
|
||||||
;; |
|
||||||
stop) |
|
||||||
stop_services |
|
||||||
;; |
|
||||||
restart) |
|
||||||
restart_services |
|
||||||
;; |
|
||||||
status) |
|
||||||
show_status |
|
||||||
;; |
|
||||||
logs) |
|
||||||
show_logs |
|
||||||
;; |
|
||||||
health) |
|
||||||
health_check |
|
||||||
;; |
|
||||||
backup) |
|
||||||
backup |
|
||||||
;; |
|
||||||
rollback) |
|
||||||
rollback |
|
||||||
;; |
|
||||||
rollback-to) |
|
||||||
rollback_to "$2" |
|
||||||
;; |
|
||||||
help|--help|-h) |
|
||||||
show_help |
|
||||||
;; |
|
||||||
*) |
|
||||||
log_error "Unknown command: $1" |
|
||||||
show_help |
|
||||||
exit 1 |
|
||||||
;; |
|
||||||
esac |
|
||||||
@ -1,427 +0,0 @@ |
|||||||
# 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 <ID> # 删除记忆 |
|
||||||
/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 |
|
||||||
@ -1,126 +0,0 @@ |
|||||||
# 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 |
|
||||||
@ -1,4 +0,0 @@ |
|||||||
[2026-02-20T14:25:25.027Z] [INFO] Agent Health Monitor initialized |
|
||||||
[2026-02-20T14:25:25.035Z] [INFO] Agent Health Monitor starting... |
|
||||||
[2026-02-20T14:25:25.036Z] [INFO] Starting OpenClaw Gateway monitoring... |
|
||||||
[2026-02-20T14:25:25.038Z] [INFO] Monitor is now active. Press Ctrl+C to stop. |
|
||||||
@ -1,5 +0,0 @@ |
|||||||
[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. |
|
||||||
@ -1,5 +0,0 @@ |
|||||||
[2026-02-22T19:12:25.950Z] [INFO] Graceful shutdown initiated |
|
||||||
[2026-02-22T19:12:26.373Z] [INFO] Agent Health Monitor initialized |
|
||||||
[2026-02-22T19:12:26.379Z] [INFO] Agent Health Monitor starting... |
|
||||||
[2026-02-22T19:12:26.379Z] [INFO] Starting OpenClaw Gateway monitoring... |
|
||||||
[2026-02-22T19:12:26.380Z] [INFO] Monitor is now active. Press Ctrl+C to stop. |
|
||||||
@ -1,5 +0,0 @@ |
|||||||
[2026-02-23T03:45:54.043Z] [INFO] Graceful shutdown initiated |
|
||||||
[2026-02-23T03:45:54.472Z] [INFO] Agent Health Monitor initialized |
|
||||||
[2026-02-23T03:45:54.555Z] [INFO] Agent Health Monitor starting... |
|
||||||
[2026-02-23T03:45:54.556Z] [INFO] Starting OpenClaw Gateway monitoring... |
|
||||||
[2026-02-23T03:45:54.557Z] [INFO] Monitor is now active. Press Ctrl+C to stop. |
|
||||||
@ -1,144 +0,0 @@ |
|||||||
# Session: 2026-02-20 11:05:07 UTC |
|
||||||
|
|
||||||
- **Session Key**: agent:main:main |
|
||||||
- **Session ID**: 71bed9c3-41be-4ef1-83ba-623d3b50483c |
|
||||||
- **Source**: telegram |
|
||||||
|
|
||||||
## Conversation Summary |
|
||||||
|
|
||||||
assistant: ✅ **成功推送到你的 Gitea 仓库!** |
|
||||||
|
|
||||||
## 📋 **Git 配置总结** |
|
||||||
|
|
||||||
### **SSH 配置** |
|
||||||
- **私钥**: `/root/.ssh/id_ed25519_openclaw` |
|
||||||
- **公钥**: 已添加到你的 Gitea 账户 |
|
||||||
- **SSH Config**: 自动使用端口 10022 连接 `gl.tigerone.tech` |
|
||||||
|
|
||||||
### **Git 仓库** |
|
||||||
- **远程地址**: `git@gl.tigerone.tech:sw_dm/openClaw_agent_dm.git` |
|
||||||
- **分支**: master (已跟踪 origin/master) |
|
||||||
- **首次推送**: ✅ 成功 |
|
||||||
|
|
||||||
### **工作流程** |
|
||||||
现在每次进行重要配置更改时,我会: |
|
||||||
1. **自动创建备份 commit** |
|
||||||
2. **推送变更到你的私有 Gitea 仓库** |
|
||||||
3. **确保所有修改都有完整的版本历史** |
|
||||||
|
|
||||||
这样你就有了完整的配置版本控制和灾难恢复能力! |
|
||||||
|
|
||||||
需要我演示一下修改配置并自动提交的流程吗? |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1006", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
不用演示git流程。 关于上文中提到的版本控制 (Rollback):给OpenClaw装个“撤销键”,创建一个说明文本(markdown文件),详细说明当配置错误时候如何通过拉取上一版本的记录以恢复agent,以便后续你可以在排查中参考,以及当你失去功能时,我可以到git上查找该文件进行回复。这个后续也作为其他agent的实践。 |
|
||||||
assistant: [[reply_to_current]] 好的!让我创建一个详细的回滚恢复指南。 |
|
||||||
|
|
||||||
|
|
||||||
assistant: 现在让我将这个指南添加到核心索引中,并提交到 Git: |
|
||||||
|
|
||||||
|
|
||||||
assistant: ✅ **回滚恢复指南已创建并推送到 Git!** |
|
||||||
|
|
||||||
## 📋 **rollback_guide.md 内容概要** |
|
||||||
|
|
||||||
### **核心恢复流程** |
|
||||||
1. **识别问题**: 确定哪个配置文件导致了问题 |
|
||||||
2. **查看历史**: `git log --oneline <filename>` 查看修改历史 |
|
||||||
3. **预览差异**: `git show <commit-hash>:<filename>` 预览特定版本 |
|
||||||
4. **执行回滚**: `git checkout <commit-hash> -- <filename>` |
|
||||||
5. **验证恢复**: 重启相关服务并测试功能 |
|
||||||
|
|
||||||
### **常见场景处理** |
|
||||||
- **OpenClaw 配置损坏**: 回滚 `~/.openclaw/openclaw.json` |
|
||||||
- **工作区配置错误**: 回滚 `/root/.openclaw/workspace/` 下的文件 |
|
||||||
- **Agent 脚本故障**: 回滚对应的 agent 文件 |
|
||||||
- **完全系统恢复**: `git reset --hard <good-commit>` |
|
||||||
|
|
||||||
### **安全注意事项** |
|
||||||
- **先备份当前状态**: `git stash` 保存未提交的更改 |
|
||||||
- **逐文件回滚**: 避免一次性回滚所有文件造成其他问题 |
|
||||||
- **测试后再提交**: 确认恢复成功后再推送新 commit |
|
||||||
|
|
||||||
### **紧急恢复命令速查** |
|
||||||
```bash |
|
||||||
# 查看最近10次提交 |
|
||||||
git log --oneline -10 |
|
||||||
|
|
||||||
# 回滚到上一个版本 |
|
||||||
git checkout HEAD~1 -- filename |
|
||||||
|
|
||||||
# 恢复整个工作区到指定提交 |
|
||||||
git reset --hard <commit-hash> |
|
||||||
|
|
||||||
# 强制推送恢复(谨慎使用) |
|
||||||
git push --force-with-lease origin master |
|
||||||
``` |
|
||||||
|
|
||||||
这个指南现在存储在你的 Gitea 仓库中,即使我完全失去功能,你也可以直接从 `https://gl.tigerone.tech/sw_dm/openClaw_agent_dm.git` 访问并按照指南进行恢复。 |
|
||||||
|
|
||||||
这将成为所有后续 agents 的标准实践模板! |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1010", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
修改现在使用的模型,改用qwen3.5-plus和qwen3.5-plus-2026-02-15,移除qwen3-max-2026-01-23 |
|
||||||
assistant: [[reply_to_current]] 好的!让我修改 OpenClaw 的模型配置,将默认模型从 `qwen3-max-2026-01-23` 替换为 `qwen3.5-plus` 和 `qwen3.5-plus-2026-02-15`。 |
|
||||||
|
|
||||||
首先,让我创建一个备份 commit: |
|
||||||
|
|
||||||
|
|
||||||
assistant: 现在让我修改 OpenClaw 的配置文件: |
|
||||||
|
|
||||||
|
|
||||||
assistant: 现在让我更新模型配置。我需要: |
|
||||||
1. 在 bailian provider 中添加新的 qwen3.5-plus 模型 |
|
||||||
2. 更新 agents defaults 中的 primary model 和 models 配置 |
|
||||||
|
|
||||||
|
|
||||||
assistant: 现在让我创建一个 commit 记录这个变更: |
|
||||||
|
|
||||||
|
|
||||||
assistant: 让我将 OpenClaw 配置文件也纳入 Git 管理: |
|
||||||
|
|
||||||
|
|
||||||
assistant: 现在让我重启 OpenClaw 服务以应用新的模型配置: |
|
||||||
|
|
||||||
|
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1012", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
进度如何? |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1014", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
进度如何? |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1016", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
修改模型的进度如何? |
|
||||||
@ -1,28 +0,0 @@ |
|||||||
# Session: 2026-02-20 11:11:50 UTC |
|
||||||
|
|
||||||
- **Session Key**: agent:main:main |
|
||||||
- **Session ID**: 47414465-b497-40b1-a385-f67d17f5ed24 |
|
||||||
- **Source**: telegram |
|
||||||
|
|
||||||
## Conversation Summary |
|
||||||
|
|
||||||
assistant: ✅ New session started · model: bailian/qwen3.5-plus |
|
||||||
user: A new session was started via /new or /reset. Greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning. |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1021", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
上文提到修改模型,是否已经完成修改。 |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1023", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
修复报错 Message ordering conflict - please try again. If this persists, use /new to start a fresh session. |
|
||||||
@ -1,19 +0,0 @@ |
|||||||
# Session: 2026-02-20 13:48:24 UTC |
|
||||||
|
|
||||||
- **Session Key**: agent:main:main |
|
||||||
- **Session ID**: c142ae76-0f74-4f28-a2b7-bf1983466abd |
|
||||||
- **Source**: telegram |
|
||||||
|
|
||||||
## Conversation Summary |
|
||||||
|
|
||||||
assistant: ✅ New session started · model: bailian/qwen3.5-plus |
|
||||||
user: A new session was started via /new or /reset. Greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning. |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1030", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
下面我们将继续进行优化,你按照我上文的要求尽作参考,结合现有的架构以及之前已经做的,你以专业AI架构师的角度去分析并执行最佳实践: 检查现有功能是否已经实现: 1. System-Level: 即使你注销或重启电脑,它依然在后台运行。 2. Auto-Healing: 如果它因为内存溢出崩溃或其他错误,任务会内自动重启。 多层记忆架构【核心记忆】:在《你指定的路径》创建一个Core_Profile.md 文件,存储最重要的信息及索引,未来重启/切换模型,第一时间读取这个文件,让模型快速明白我是谁?我是做什么的?【日常记忆】:我们的日常对话请自动保存为MEMORY.md,作为归档备份,方便未来检索记忆。当我与模型对话提到一些关键词时,可以启动调取,以便模型更好的理解并输出结果。【被动归档】:当我觉得我们的对话非常有价值,我会让你将对话转化成Skill/笔记,未来我有需要请你发给模型读取操作。 通过git实现的一键回滚功能。 |
|
||||||
@ -1,28 +0,0 @@ |
|||||||
# Session: 2026-02-20 14:03:32 UTC |
|
||||||
|
|
||||||
- **Session Key**: agent:main:main |
|
||||||
- **Session ID**: f37313e8-2d95-4782-abf4-8bb502d49f46 |
|
||||||
- **Source**: webchat |
|
||||||
|
|
||||||
## Conversation Summary |
|
||||||
|
|
||||||
assistant: ✅ New session started · model: bailian/qwen3.5-plus |
|
||||||
user: A new session was started via /new or /reset. Greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning. |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1035", |
|
||||||
"sender": "5237946060" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
下面我们将继续进行优化,你按照我上文的要求尽作参考,结合现有的架构以及之前已经做的,你以专业AI架构师的角度去分析并执行最佳实践: 检查现有功能是否已经实现: 1. System-Level: 即使你注销或重启电脑,它依然在后台运行。 2. Auto-Healing: 如果它因为内存溢出崩溃或其他错误,任务会内自动重启。 3. 多层记忆架构【核心记忆】:在《你指定的路径》创建一个Core_Profile.md 文件,存储最重要的信息及索引,未来重启/切换模型,第一时间读取这个文件,让模型快速明白我是谁?我是做什么的?【日常记忆】:我们的日常对话请自动保存为MEMORY.md,作为归档备份,方便未来检索记忆。当我与模型对话提到一些关键词时,可以启动调取,以便模型更好的理解并输出结果。【被动归档】:当我觉得我们的对话非常有价值,我会让你将对话转化成Skill/笔记,未来我有需要请你发给模型读取操作。 4. 通过git实现的一键回滚功能。 5. 当openClaw服务停止、错误或重启时候会通过telegram(或相应channel)通知。 |
|
||||||
user: Conversation info (untrusted metadata): |
|
||||||
```json |
|
||||||
{ |
|
||||||
"message_id": "1d89994f-acfd-4ebf-b355-60a567b88a84", |
|
||||||
"sender": "openclaw-control-ui" |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
[Fri 2026-02-20 14:03 UTC] 更换模型后,发送信息会报错:Message ordering conflict - please try again. If this persists, use /new to start a fresh session. 修复这个错误。 |
|
||||||
@ -0,0 +1,207 @@ |
|||||||
|
{ |
||||||
|
"meta": { |
||||||
|
"lastTouchedVersion": "2026.2.19-2", |
||||||
|
"lastTouchedAt": "2026-02-20T08:45:00.000Z" |
||||||
|
}, |
||||||
|
"env": { |
||||||
|
"TAVILY_API_KEY": "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" |
||||||
|
}, |
||||||
|
"wizard": { |
||||||
|
"lastRunAt": "2026-02-20T03:54:18.096Z", |
||||||
|
"lastRunVersion": "2026.2.17", |
||||||
|
"lastRunCommand": "doctor", |
||||||
|
"lastRunMode": "local" |
||||||
|
}, |
||||||
|
"auth": { |
||||||
|
"profiles": { |
||||||
|
"minimax-cn:default": { |
||||||
|
"provider": "minimax-cn", |
||||||
|
"mode": "api_key" |
||||||
|
}, |
||||||
|
"qwen-portal:default": { |
||||||
|
"provider": "qwen-portal", |
||||||
|
"mode": "oauth" |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"models": { |
||||||
|
"mode": "merge", |
||||||
|
"providers": { |
||||||
|
"minimax-cn": { |
||||||
|
"baseUrl": "https://api.minimaxi.com/anthropic", |
||||||
|
"api": "anthropic-messages", |
||||||
|
"models": [ |
||||||
|
{ |
||||||
|
"id": "MiniMax-M2.5", |
||||||
|
"name": "MiniMax M2.5", |
||||||
|
"reasoning": true, |
||||||
|
"input": [ |
||||||
|
"text" |
||||||
|
], |
||||||
|
"cost": { |
||||||
|
"input": 15, |
||||||
|
"output": 60, |
||||||
|
"cacheRead": 2, |
||||||
|
"cacheWrite": 10 |
||||||
|
}, |
||||||
|
"contextWindow": 200000, |
||||||
|
"maxTokens": 8192 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"bailian": { |
||||||
|
"baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1", |
||||||
|
"apiKey": "sk-c1715ee0479841399fd359c574647648", |
||||||
|
"api": "openai-completions", |
||||||
|
"models": [ |
||||||
|
{ |
||||||
|
"id": "qwen3.5-plus", |
||||||
|
"name": "qwen3.5-plus", |
||||||
|
"reasoning": true, |
||||||
|
"input": [ |
||||||
|
"text" |
||||||
|
], |
||||||
|
"cost": { |
||||||
|
"input": 0, |
||||||
|
"output": 0, |
||||||
|
"cacheRead": 0, |
||||||
|
"cacheWrite": 0 |
||||||
|
}, |
||||||
|
"contextWindow": 262144, |
||||||
|
"maxTokens": 65536 |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": "qwen3.5-plus-2026-02-15", |
||||||
|
"name": "qwen3.5-plus-2026-02-15", |
||||||
|
"reasoning": true, |
||||||
|
"input": [ |
||||||
|
"text" |
||||||
|
], |
||||||
|
"cost": { |
||||||
|
"input": 0, |
||||||
|
"output": 0, |
||||||
|
"cacheRead": 0, |
||||||
|
"cacheWrite": 0 |
||||||
|
}, |
||||||
|
"contextWindow": 262144, |
||||||
|
"maxTokens": 65536 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"agents": { |
||||||
|
"defaults": { |
||||||
|
"model": { |
||||||
|
"primary": "bailian/qwen3.5-plus", |
||||||
|
"fallbacks": [ |
||||||
|
"bailian/qwen3.5-plus-2026-02-15", |
||||||
|
"minimax-cn/MiniMax-M2.5" |
||||||
|
] |
||||||
|
}, |
||||||
|
"models": { |
||||||
|
"minimax-cn/MiniMax-M2.5": { |
||||||
|
"alias": "Minimax" |
||||||
|
}, |
||||||
|
"bailian/qwen3.5-plus": { |
||||||
|
"alias": "qwen3.5-plus" |
||||||
|
}, |
||||||
|
"bailian/qwen3.5-plus-2026-02-15": { |
||||||
|
"alias": "qwen3.5-plus-thinking" |
||||||
|
} |
||||||
|
}, |
||||||
|
"workspace": "/root/.openclaw/workspace", |
||||||
|
"contextPruning": { |
||||||
|
"mode": "cache-ttl", |
||||||
|
"ttl": "5m" |
||||||
|
}, |
||||||
|
"compaction": { |
||||||
|
"mode": "safeguard" |
||||||
|
}, |
||||||
|
"maxConcurrent": 4, |
||||||
|
"subagents": { |
||||||
|
"maxConcurrent": 8, |
||||||
|
"model": "minimax/MiniMax-M2.1" |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"messages": { |
||||||
|
"ackReactionScope": "group-mentions" |
||||||
|
}, |
||||||
|
"commands": { |
||||||
|
"native": "auto", |
||||||
|
"nativeSkills": "auto", |
||||||
|
"restart": true |
||||||
|
}, |
||||||
|
"hooks": { |
||||||
|
"internal": { |
||||||
|
"enabled": true, |
||||||
|
"entries": { |
||||||
|
"command-logger": { |
||||||
|
"enabled": true |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"channels": { |
||||||
|
"telegram": { |
||||||
|
"enabled": true, |
||||||
|
"dmPolicy": "pairing", |
||||||
|
"botToken": "7047245486:AAF504oCHZpfEIx3-3VXJYSSS9XelkV6o3g", |
||||||
|
"groupPolicy": "allowlist", |
||||||
|
"streamMode": "partial" |
||||||
|
} |
||||||
|
}, |
||||||
|
"gateway": { |
||||||
|
"port": 18789, |
||||||
|
"mode": "local", |
||||||
|
"bind": "lan", |
||||||
|
"auth": { |
||||||
|
"mode": "token", |
||||||
|
"token": "9e2e91b31a56fb56a35e91821c025267292ec44c26169b12" |
||||||
|
}, |
||||||
|
"trustedProxies": [ |
||||||
|
"127.0.0.1", |
||||||
|
"::1" |
||||||
|
], |
||||||
|
"tailscale": { |
||||||
|
"mode": "off", |
||||||
|
"resetOnExit": false |
||||||
|
}, |
||||||
|
"nodes": {} |
||||||
|
}, |
||||||
|
"memory": { |
||||||
|
"backend": "qmd", |
||||||
|
"citations": "auto", |
||||||
|
"qmd": { |
||||||
|
"includeDefaultMemory": true, |
||||||
|
"update": { |
||||||
|
"interval": "5m", |
||||||
|
"debounceMs": 15000 |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"skills": { |
||||||
|
"install": { |
||||||
|
"nodeManager": "npm" |
||||||
|
}, |
||||||
|
"entries": { |
||||||
|
"tavily": { |
||||||
|
"enabled": true |
||||||
|
}, |
||||||
|
"find-skills-robin": { |
||||||
|
"enabled": true |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"plugins": { |
||||||
|
"entries": { |
||||||
|
"telegram": { |
||||||
|
"enabled": true |
||||||
|
}, |
||||||
|
"qwen-portal-auth": { |
||||||
|
"enabled": true |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -1,53 +0,0 @@ |
|||||||
{ |
|
||||||
"meta": { |
|
||||||
"lastTouchedVersion": "2026.2.19-2", |
|
||||||
"lastTouchedAt": "2026-02-20T08:45:00.000Z" |
|
||||||
}, |
|
||||||
"env": { |
|
||||||
"TAVILY_API_KEY": "${TAVILY_API_KEY}" |
|
||||||
}, |
|
||||||
"wizard": { |
|
||||||
"lastRunAt": "2026-02-20T03:54:18.096Z", |
|
||||||
"lastRunVersion": "2026.2.17", |
|
||||||
"lastRunAt": "2026.2.17", |
|
||||||
"lastRunCommand": "doctor", |
|
||||||
"lastRunMode": "local" |
|
||||||
}, |
|
||||||
"auth": { |
|
||||||
"profiles": { |
|
||||||
"minimax-cn:default": { |
|
||||||
"provider": "minimax-cn", |
|
||||||
"mode": "api_key" |
|
||||||
}, |
|
||||||
"qwen-portal:default": { |
|
||||||
"provider": "qwen-portal", |
|
||||||
"mode": "oauth" |
|
||||||
} |
|
||||||
} |
|
||||||
}, |
|
||||||
"models": { |
|
||||||
"mode": "merge", |
|
||||||
"providers": { |
|
||||||
"minimax-cn": { |
|
||||||
"baseUrl": "https://api.minimaxi.com/anthropic", |
|
||||||
"api": "anthropic-messages", |
|
||||||
"models": [ |
|
||||||
{ |
|
||||||
"id": "MiniMax-M2.5", |
|
||||||
"name": "MiniMax M2.5", |
|
||||||
"reasoning": true, |
|
||||||
"input": ["text"], |
|
||||||
"cost": { |
|
||||||
"input": 15, |
|
||||||
"output": 60, |
|
||||||
"cacheRead": 2, |
|
||||||
"cacheWrite": 10 |
|
||||||
}, |
|
||||||
"contextWindow": 200000, |
|
||||||
"maxTokens": 8192 |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,101 +0,0 @@ |
|||||||
#!/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" |
|
||||||
@ -1,26 +0,0 @@ |
|||||||
#!/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 "✅ 依赖安装完成" |
|
||||||
@ -1,40 +0,0 @@ |
|||||||
#!/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 |
|
||||||
@ -1,41 +0,0 @@ |
|||||||
#!/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 "✅ 监控完成" |
|
||||||
@ -1,35 +0,0 @@ |
|||||||
# 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 <ID>` - 删除记忆 |
|
||||||
- `/memory sync` - 手动同步到中心 |
|
||||||
- `/memory status` - 查看状态 |
|
||||||
|
|
||||||
## 依赖 |
|
||||||
|
|
||||||
- mem0ai (pip install mem0ai) |
|
||||||
- Qdrant (Docker) |
|
||||||
- pyyaml |
|
||||||
Binary file not shown.
Binary file not shown.
@ -1,79 +0,0 @@ |
|||||||
#!/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""" |
|
||||||
@ -1,47 +0,0 @@ |
|||||||
# mem0 Integration Configuration |
|
||||||
# 复制此文件为 config.yaml 并填入真实 API keys |
|
||||||
|
|
||||||
# 本地 Qdrant 配置 |
|
||||||
local: |
|
||||||
vector_store: |
|
||||||
provider: qdrant |
|
||||||
config: |
|
||||||
host: localhost |
|
||||||
port: 6333 |
|
||||||
collection_name: mem0_v4_local |
|
||||||
|
|
||||||
llm: |
|
||||||
provider: openai |
|
||||||
config: |
|
||||||
model: qwen-plus |
|
||||||
api_base: https://dashscope.aliyuncs.com/compatible-mode/v1 |
|
||||||
api_key: ${DASHSCOPE_API_KEY} # 从环境变量读取 |
|
||||||
|
|
||||||
embedder: |
|
||||||
provider: openai |
|
||||||
config: |
|
||||||
model: text-embedding-v4 |
|
||||||
api_base: https://dashscope.aliyuncs.com/compatible-mode/v1 |
|
||||||
api_key: ${DASHSCOPE_API_KEY} # 从环境变量读取 |
|
||||||
|
|
||||||
# 中心 Qdrant 配置(共享记忆) |
|
||||||
master: |
|
||||||
vector_store: |
|
||||||
provider: qdrant |
|
||||||
config: |
|
||||||
host: 100.115.94.1 |
|
||||||
port: 6333 |
|
||||||
collection_name: mem0_v4_shared |
|
||||||
|
|
||||||
# 同步配置 |
|
||||||
sync: |
|
||||||
enabled: true |
|
||||||
interval: 300 |
|
||||||
batch_size: 50 |
|
||||||
retry_attempts: 3 |
|
||||||
|
|
||||||
# 缓存配置 |
|
||||||
cache: |
|
||||||
enabled: true |
|
||||||
ttl: 300 |
|
||||||
max_size: 1000 |
|
||||||
@ -1,162 +0,0 @@ |
|||||||
#!/usr/bin/env node
|
|
||||||
/** |
|
||||||
* OpenClaw Mem0 Integration Plugin |
|
||||||
* 将 mem0 拦截器挂载到 OpenClaw 主对话生命周期 |
|
||||||
*/ |
|
||||||
|
|
||||||
const fs = require('fs'); |
|
||||||
const path = require('path'); |
|
||||||
|
|
||||||
// Python 子进程执行器
|
|
||||||
const { spawn } = require('child_process'); |
|
||||||
|
|
||||||
class Mem0Plugin { |
|
||||||
constructor(config) { |
|
||||||
this.config = config; |
|
||||||
this.enabled = true; |
|
||||||
this.pythonPath = config.pythonPath || 'python3'; |
|
||||||
this.scriptPath = path.join(__dirname, 'mem0_integration.py'); |
|
||||||
this.initialized = false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 初始化 mem0(在 OpenClaw 启动时调用) |
|
||||||
*/ |
|
||||||
async onLoad() { |
|
||||||
if (!this.enabled) return; |
|
||||||
|
|
||||||
console.log('[Mem0] 初始化记忆系统...'); |
|
||||||
|
|
||||||
try { |
|
||||||
// 调用 Python 脚本初始化 mem0
|
|
||||||
const result = await this._executePython('init'); |
|
||||||
|
|
||||||
if (result.success) { |
|
||||||
this.initialized = true; |
|
||||||
console.log('🟢 Mem0 生产环境集成完毕,等待 Telegram 消息注入'); |
|
||||||
} else { |
|
||||||
console.error('[Mem0] 初始化失败:', result.error); |
|
||||||
} |
|
||||||
} catch (error) { |
|
||||||
console.error('[Mem0] 初始化异常:', error.message); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Pre-Hook: 在 LLM 生成前检索记忆 |
|
||||||
*/ |
|
||||||
async preLLM(userMessage, context) { |
|
||||||
if (!this.enabled || !this.initialized) return null; |
|
||||||
|
|
||||||
try { |
|
||||||
const result = await this._executePython('search', { |
|
||||||
query: userMessage, |
|
||||||
user_id: context.user_id || 'default', |
|
||||||
agent_id: context.agent_id || 'general' |
|
||||||
}); |
|
||||||
|
|
||||||
if (result.success && result.memories && result.memories.length > 0) { |
|
||||||
console.log(`[Mem0] Pre-Hook: 检索到 ${result.memories.length} 条记忆`); |
|
||||||
return this._formatMemories(result.memories); |
|
||||||
} |
|
||||||
|
|
||||||
return null; |
|
||||||
} catch (error) { |
|
||||||
console.error('[Mem0] Pre-Hook 失败:', error.message); |
|
||||||
return null; // 静默失败,不影响对话
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Post-Hook: 在响应后异步写入记忆 |
|
||||||
*/ |
|
||||||
async postResponse(userMessage, assistantMessage, context) { |
|
||||||
if (!this.enabled || !this.initialized) return; |
|
||||||
|
|
||||||
try { |
|
||||||
await this._executePython('add', { |
|
||||||
user_message: userMessage, |
|
||||||
assistant_message: assistantMessage, |
|
||||||
user_id: context.user_id || 'default', |
|
||||||
agent_id: context.agent_id || 'general' |
|
||||||
}, false); // 不等待结果(异步)
|
|
||||||
|
|
||||||
console.log('[Mem0] Post-Hook: 已提交对话到记忆队列'); |
|
||||||
} catch (error) { |
|
||||||
console.error('[Mem0] Post-Hook 失败:', error.message); |
|
||||||
// 静默失败
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 执行 Python 脚本 |
|
||||||
*/ |
|
||||||
_executePython(action, data = {}, waitForResult = true) { |
|
||||||
return new Promise((resolve, reject) => { |
|
||||||
const args = [this.scriptPath, action]; |
|
||||||
if (data) { |
|
||||||
args.push(JSON.stringify(data)); |
|
||||||
} |
|
||||||
|
|
||||||
const proc = spawn(this.pythonPath, args, { |
|
||||||
cwd: __dirname, |
|
||||||
env: process.env |
|
||||||
}); |
|
||||||
|
|
||||||
let stdout = ''; |
|
||||||
let stderr = ''; |
|
||||||
|
|
||||||
proc.stdout.on('data', (data) => { |
|
||||||
stdout += data.toString(); |
|
||||||
}); |
|
||||||
|
|
||||||
proc.stderr.on('data', (data) => { |
|
||||||
stderr += data.toString(); |
|
||||||
}); |
|
||||||
|
|
||||||
proc.on('close', (code) => { |
|
||||||
if (code === 0) { |
|
||||||
try { |
|
||||||
const result = JSON.parse(stdout); |
|
||||||
resolve({ success: true, ...result }); |
|
||||||
} catch { |
|
||||||
resolve({ success: true, raw: stdout }); |
|
||||||
} |
|
||||||
} else { |
|
||||||
resolve({ success: false, error: stderr || `Exit code: ${code}` }); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
proc.on('error', reject); |
|
||||||
|
|
||||||
// 如果不等待结果,立即返回
|
|
||||||
if (!waitForResult) { |
|
||||||
resolve({ success: true, async: true }); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 格式化记忆为 Prompt |
|
||||||
*/ |
|
||||||
_formatMemories(memories) { |
|
||||||
if (!memories || memories.length === 0) return ''; |
|
||||||
|
|
||||||
let prompt = '\n\n=== 相关记忆 ===\n'; |
|
||||||
memories.forEach((mem, i) => { |
|
||||||
prompt += `${i + 1}. ${mem.memory}`; |
|
||||||
if (mem.created_at) { |
|
||||||
prompt += ` (记录于:${mem.created_at})`; |
|
||||||
} |
|
||||||
prompt += '\n'; |
|
||||||
}); |
|
||||||
prompt += '===============\n'; |
|
||||||
|
|
||||||
return prompt; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// 导出插件实例
|
|
||||||
module.exports = new Mem0Plugin({ |
|
||||||
pythonPath: process.env.MEM0_PYTHON_PATH || 'python3' |
|
||||||
}); |
|
||||||
@ -1,69 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
""" |
|
||||||
Mem0 Python 集成脚本 |
|
||||||
被 Node.js 插件调用,执行实际的记忆操作 |
|
||||||
""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import json |
|
||||||
import os |
|
||||||
import asyncio |
|
||||||
|
|
||||||
# 设置环境变量 |
|
||||||
os.environ['OPENAI_API_BASE'] = 'https://dashscope.aliyuncs.com/compatible-mode/v1' |
|
||||||
os.environ['OPENAI_BASE_URL'] = 'https://dashscope.aliyuncs.com/compatible-mode/v1' |
|
||||||
os.environ['OPENAI_API_KEY'] = os.getenv('MEM0_DASHSCOPE_API_KEY', 'sk-c1715ee0479841399fd359c574647648') |
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(__file__)) |
|
||||||
|
|
||||||
from mem0_client import mem0_client |
|
||||||
|
|
||||||
|
|
||||||
async def main(): |
|
||||||
if len(sys.argv) < 2: |
|
||||||
print(json.dumps({"error": "No action specified"})) |
|
||||||
return |
|
||||||
|
|
||||||
action = sys.argv[1] |
|
||||||
data = json.loads(sys.argv[2]) if len(sys.argv) > 2 else {} |
|
||||||
|
|
||||||
try: |
|
||||||
if action == 'init': |
|
||||||
# 初始化 mem0 |
|
||||||
await mem0_client.start() |
|
||||||
print(json.dumps({ |
|
||||||
"status": "initialized", |
|
||||||
"qdrant": f"{mem0_client.config['qdrant']['host']}:{mem0_client.config['qdrant']['port']}" |
|
||||||
})) |
|
||||||
|
|
||||||
elif action == 'search': |
|
||||||
# 检索记忆 |
|
||||||
memories = await mem0_client.pre_hook_search( |
|
||||||
query=data.get('query', ''), |
|
||||||
user_id=data.get('user_id', 'default'), |
|
||||||
agent_id=data.get('agent_id', 'general') |
|
||||||
) |
|
||||||
print(json.dumps({ |
|
||||||
"memories": memories, |
|
||||||
"count": len(memories) |
|
||||||
})) |
|
||||||
|
|
||||||
elif action == 'add': |
|
||||||
# 添加记忆(异步,不等待) |
|
||||||
mem0_client.post_hook_add( |
|
||||||
user_message=data.get('user_message', ''), |
|
||||||
assistant_message=data.get('assistant_message', ''), |
|
||||||
user_id=data.get('user_id', 'default'), |
|
||||||
agent_id=data.get('agent_id', 'general') |
|
||||||
) |
|
||||||
print(json.dumps({"status": "queued"})) |
|
||||||
|
|
||||||
else: |
|
||||||
print(json.dumps({"error": f"Unknown action: {action}"})) |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
print(json.dumps({"error": str(e)})) |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__': |
|
||||||
asyncio.run(main()) |
|
||||||
@ -1,150 +0,0 @@ |
|||||||
#!/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 <ID>" |
|
||||||
|
|
||||||
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 <ID> - 删除记忆 |
|
||||||
status - 查看状态 |
|
||||||
help - 显示帮助 |
|
||||||
|
|
||||||
示例: |
|
||||||
/memory add 用户偏好使用 UTC 时区 |
|
||||||
/memory search 时区 |
|
||||||
/memory list |
|
||||||
/memory status""" |
|
||||||
|
|
||||||
# 测试 |
|
||||||
if __name__ == '__main__': |
|
||||||
print("测试 /memory 命令...") |
|
||||||
print(handle_status()) |
|
||||||
@ -1,51 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
"""OpenClaw 拦截器:Pre-Hook + Post-Hook""" |
|
||||||
|
|
||||||
import asyncio |
|
||||||
import logging |
|
||||||
import sys |
|
||||||
sys.path.insert(0, '/root/.openclaw/workspace/skills/mem0-integration') |
|
||||||
from mem0_client import mem0_client |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
|
|
||||||
class ConversationInterceptor: |
|
||||||
def __init__(self): |
|
||||||
self.enabled = True |
|
||||||
|
|
||||||
async def pre_hook(self, query: str, context: dict) -> str: |
|
||||||
if not self.enabled: |
|
||||||
return None |
|
||||||
try: |
|
||||||
user_id = context.get('user_id', 'default') |
|
||||||
agent_id = context.get('agent_id', 'general') |
|
||||||
memories = await mem0_client.pre_hook_search(query=query, user_id=user_id, agent_id=agent_id) |
|
||||||
if memories: |
|
||||||
return mem0_client.format_memories_for_prompt(memories) |
|
||||||
return None |
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Pre-Hook 失败:{e}") |
|
||||||
return None |
|
||||||
|
|
||||||
async def post_hook(self, user_message: str, assistant_message: str, context: dict): |
|
||||||
if not self.enabled: |
|
||||||
return |
|
||||||
try: |
|
||||||
user_id = context.get('user_id', 'default') |
|
||||||
agent_id = context.get('agent_id', 'general') |
|
||||||
await mem0_client.post_hook_add(user_message, assistant_message, user_id, agent_id) |
|
||||||
logger.debug(f"Post-Hook: 已提交对话") |
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Post-Hook 失败:{e}") |
|
||||||
|
|
||||||
|
|
||||||
interceptor = ConversationInterceptor() |
|
||||||
|
|
||||||
|
|
||||||
async def intercept_before_llm(query: str, context: dict): |
|
||||||
return await interceptor.pre_hook(query, context) |
|
||||||
|
|
||||||
|
|
||||||
async def intercept_after_response(user_msg: str, assistant_msg: str, context: dict): |
|
||||||
await interceptor.post_hook(user_msg, assistant_msg, context) |
|
||||||
@ -1,36 +0,0 @@ |
|||||||
{ |
|
||||||
"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 <add|search|list|delete|status|help> [参数]", |
|
||||||
"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" |
|
||||||
] |
|
||||||
} |
|
||||||
@ -1,41 +0,0 @@ |
|||||||
[Unit] |
|
||||||
Description=OpenClaw Agent Health Monitor |
|
||||||
Documentation=https://docs.openclaw.ai |
|
||||||
After=network-online.target |
|
||||||
Wants=network-online.target |
|
||||||
|
|
||||||
[Service] |
|
||||||
Type=simple |
|
||||||
User=root |
|
||||||
WorkingDirectory=/root/.openclaw/workspace |
|
||||||
Environment=NODE_ENV=production |
|
||||||
Environment=HOME=/root |
|
||||||
Environment=XDG_RUNTIME_DIR=/run/user/0 |
|
||||||
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus |
|
||||||
|
|
||||||
# Monitor process |
|
||||||
ExecStart=/usr/bin/node /root/.openclaw/workspace/agent-monitor.js |
|
||||||
|
|
||||||
# Auto-healing configuration |
|
||||||
Restart=always |
|
||||||
RestartSec=5 |
|
||||||
StartLimitInterval=300 |
|
||||||
StartLimitBurst=10 |
|
||||||
|
|
||||||
# Resource limits |
|
||||||
MemoryLimit=512M |
|
||||||
CPUQuota=20% |
|
||||||
|
|
||||||
# Logging |
|
||||||
StandardOutput=journal |
|
||||||
StandardError=journal |
|
||||||
SyslogIdentifier=openclaw-monitor |
|
||||||
|
|
||||||
# Security |
|
||||||
NoNewPrivileges=true |
|
||||||
ProtectSystem=strict |
|
||||||
ProtectHome=read-only |
|
||||||
ReadWritePaths=/root/.openclaw/workspace/logs |
|
||||||
|
|
||||||
[Install] |
|
||||||
WantedBy=multi-user.target |
|
||||||
@ -1,51 +0,0 @@ |
|||||||
# User-level systemd service for OpenClaw Gateway |
|
||||||
# Install to: ~/.config/systemd/user/openclaw-gateway.service |
|
||||||
# Required: loginctl enable-linger $(whoami) |
|
||||||
|
|
||||||
[Unit] |
|
||||||
Description=OpenClaw Gateway (v2026.2.19-2) |
|
||||||
After=network-online.target |
|
||||||
Wants=network-online.target |
|
||||||
|
|
||||||
[Service] |
|
||||||
Type=simple |
|
||||||
ExecStart=/www/server/nodejs/v24.13.1/bin/node /www/server/nodejs/v24.13.1/lib/node_modules/openclaw/dist/index.js gateway --port 18789 |
|
||||||
Restart=always |
|
||||||
RestartSec=10 |
|
||||||
StartLimitInterval=300 |
|
||||||
StartLimitBurst=5 |
|
||||||
KillMode=process |
|
||||||
TimeoutStopSec=30 |
|
||||||
|
|
||||||
# Critical environment variables for user-level systemd |
|
||||||
Environment=HOME=/root |
|
||||||
Environment=XDG_RUNTIME_DIR=/run/user/0 |
|
||||||
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus |
|
||||||
Environment=PATH=/root/.local/bin:/root/.npm-global/bin:/root/bin:/root/.volta/bin:/root/.asdf/shims:/root/.bun/bin:/root/.nvm/current/bin:/root/.fnm/current/bin:/root/.local/share/pnpm:/usr/local/bin:/usr/bin:/bin |
|
||||||
Environment=OPENCLAW_GATEWAY_PORT=18789 |
|
||||||
Environment=OPENCLAW_GATEWAY_TOKEN=9e2e91b31a56fb56a35e91821c025267292ec44c26169b12 |
|
||||||
Environment=OPENCLAW_SYSTEMD_UNIT=openclaw-gateway.service |
|
||||||
Environment=OPENCLAW_SERVICE_MARKER=openclaw |
|
||||||
Environment=OPENCLAW_SERVICE_KIND=gateway |
|
||||||
Environment=OPENCLAW_SERVICE_VERSION=2026.2.19-2 |
|
||||||
|
|
||||||
# Resource limits |
|
||||||
MemoryLimit=2G |
|
||||||
CPUQuota=80% |
|
||||||
|
|
||||||
# Security |
|
||||||
NoNewPrivileges=true |
|
||||||
ProtectSystem=strict |
|
||||||
ProtectHome=read-only |
|
||||||
ReadWritePaths=/root/.openclaw |
|
||||||
|
|
||||||
# Logging |
|
||||||
StandardOutput=journal |
|
||||||
StandardError=journal |
|
||||||
SyslogIdentifier=openclaw-gateway |
|
||||||
|
|
||||||
# Watchdog |
|
||||||
WatchdogSec=30 |
|
||||||
|
|
||||||
[Install] |
|
||||||
WantedBy=default.target |
|
||||||
@ -1,42 +0,0 @@ |
|||||||
[Unit] |
|
||||||
Description=OpenClaw Gateway Service |
|
||||||
Documentation=https://docs.openclaw.ai |
|
||||||
After=network.target |
|
||||||
Wants=network-online.target |
|
||||||
|
|
||||||
[Service] |
|
||||||
Type=simple |
|
||||||
User=root |
|
||||||
WorkingDirectory=/root/.openclaw |
|
||||||
Environment=NODE_ENV=production |
|
||||||
|
|
||||||
# Main gateway process |
|
||||||
ExecStart=/usr/bin/node /www/server/nodejs/v24.13.1/bin/openclaw gateway start |
|
||||||
ExecReload=/bin/kill -HUP $MAINPID |
|
||||||
|
|
||||||
# Auto-healing configuration |
|
||||||
Restart=always |
|
||||||
RestartSec=10 |
|
||||||
StartLimitInterval=300 |
|
||||||
StartLimitBurst=5 |
|
||||||
|
|
||||||
# Resource limits to prevent OOM |
|
||||||
MemoryLimit=2G |
|
||||||
CPUQuota=80% |
|
||||||
|
|
||||||
# Logging |
|
||||||
StandardOutput=journal |
|
||||||
StandardError=journal |
|
||||||
SyslogIdentifier=openclaw-gateway |
|
||||||
|
|
||||||
# Security hardening |
|
||||||
NoNewPrivileges=true |
|
||||||
ProtectSystem=strict |
|
||||||
ProtectHome=read-only |
|
||||||
ReadWritePaths=/root/.openclaw |
|
||||||
|
|
||||||
# Watchdog for health monitoring |
|
||||||
WatchdogSec=30 |
|
||||||
|
|
||||||
[Install] |
|
||||||
WantedBy=multi-user.target |
|
||||||
Loading…
Reference in new issue