# 智能体聊天助手记忆存储说明

## 一、数据存储位置

### 1. 主要存储：Redis

智能体聊天助手使用 **Redis** 作为记忆数据的持久化存储后端。

- **存储键名格式**：`user_memory_{user_id}`
  - 例如：`user_memory_default`、`user_memory_12345`
- **存储位置**：Redis 数据库（默认 DB 0）
- **数据格式**：JSON 字符串

### 2. 备用存储：内存缓存

如果 Redis 不可用，系统会回退到**内存缓存**（Memory Cache）。

⚠️ **重要提示**：内存缓存只在**单次执行会话内有效**，执行结束后数据会丢失，无法跨会话保留。

### 3. 存储结构

每个用户的记忆数据包含以下字段：

```json
{
  "conversation_history": [
    {
      "role": "user",
      "content": "我的名字叫老七",
      "timestamp": "2024-01-01T10:00:00"
    },
    {
      "role": "assistant",
      "content": "好的，我记住了你的名字是老七。",
      "timestamp": "2024-01-01T10:00:01"
    }
  ],
  "user_profile": {
    // 用户画像信息（可扩展）
  },
  "context": {
    // 上下文信息（可扩展）
  }
}
```

## 二、数据大小限制

### 1. Redis 存储限制

- **单条记录大小**：
  - Redis 理论上单个 key 的值最大可达 **512MB**（默认配置）
  - 实际使用中，受 Redis 服务器配置的 `maxmemory` 限制
  - 当前系统：**无硬编码限制**（取决于 Redis 服务器配置）

- **对话历史累积**：
  - 对话历史会**不断累积**，没有自动截断机制
  - 每次对话会添加 2 条记录（用户消息 + 助手回复）
  - 假设每条消息平均 200 字（约 600 字节），1000 轮对话约 1.2MB

### 2. 实际使用情况

根据当前系统检查：
- 当前用户记忆 key 数量：**1 个**
- 示例 key 大小：**约 5.73 KB**（20 条对话历史）
- Redis 已使用内存：**2.52 MB**
- Redis 最大内存限制：**无限制**（取决于服务器配置）

### 3. 建议的容量规划

| 对话轮数 | 预估大小 | 说明 |
|---------|---------|------|
| 100 轮 | ~120 KB | 适合短期对话 |
| 500 轮 | ~600 KB | 适合中期对话 |
| 1000 轮 | ~1.2 MB | 适合长期对话 |
| 5000 轮 | ~6 MB | 需要监控内存使用 |
| 10000 轮 | ~12 MB | 建议实施截断策略 |

## 三、数据持久化与丢失风险

### 1. 数据持久化机制

#### Redis 持久化（推荐）

- **持久化方式**：取决于 Redis 配置
  - **RDB**：定期快照，默认开启
  - **AOF**：追加日志，可选开启
- **Docker 卷持久化**：
  - 使用 `redis_data` 卷存储数据
  - 即使容器重启，数据也会保留
  - 数据存储在 Docker 卷中，位置：`/var/lib/docker/volumes/redis_data`

#### 内存缓存（不持久化）

- 数据仅存在于进程内存中
- 进程重启后数据丢失
- 仅用于 Redis 不可用时的临时回退

### 2. 数据丢失风险分析

| 场景 | 数据是否丢失 | 说明 |
|------|------------|------|
| Redis 正常重启 | ❌ 不丢失 | 数据已持久化到磁盘 |
| Docker 容器重启 | ❌ 不丢失 | 数据存储在 Docker 卷中 |
| Redis 数据卷被删除 | ✅ **会丢失** | 需要重新创建卷 |
| 超过 TTL 时间 | ✅ **会过期** | 默认 24 小时后过期 |
| Redis 服务器故障 | ⚠️ 取决于持久化配置 | 如果持久化配置不当可能丢失 |
| 使用内存缓存时 | ✅ **会丢失** | 每次执行后丢失 |

### 3. TTL（生存时间）设置

当前配置：
- **TTL**：**86400 秒**（24 小时）
- **位置**：`cache-update` 节点的 `ttl` 配置
- **默认值**：如果未配置，默认 3600 秒（1 小时）

⚠️ **重要**：如果用户在 24 小时内没有新的对话，记忆数据会**自动过期删除**。

## 四、配置说明

### 1. Redis 配置

**环境变量**（`docker-compose.dev.yml`）：
```yaml
REDIS_URL=redis://redis:6379/0
```

**配置文件**（`backend/.env`）：
```env
REDIS_URL=redis://localhost:6379/0
```

### 2. Cache 节点配置

**查询记忆节点**（`cache-query`）：
```python
{
    "id": "cache-query",
    "type": "cache",
    "data": {
        "operation": "get",
        "key": "user_memory_{user_id}",
        "default_value": '{"conversation_history": [], "user_profile": {}, "context": {}}'
    }
}
```

**更新记忆节点**（`cache-update`）：
```python
{
    "id": "cache-update",
    "type": "cache",
    "data": {
        "operation": "set",
        "key": "user_memory_{user_id}",
        "value": '{"conversation_history": {{memory.conversation_history}} + [...], ...}',
        "ttl": 86400  # 24小时
    }
}
```

## 五、优化建议

### 1. 对话历史截断策略

如果对话历史过长，建议实施截断策略：

**方案 A：保留最近 N 条**
```python
# 在 cache-update 节点中，限制 conversation_history 长度
conversation_history = memory.conversation_history[-100:]  # 只保留最近100条
```

**方案 B：按时间截断**
```python
# 只保留最近7天的对话
from datetime import datetime, timedelta
cutoff_date = (datetime.now() - timedelta(days=7)).isoformat()
conversation_history = [
    msg for msg in memory.conversation_history 
    if msg.get('timestamp', '') > cutoff_date
]
```

**方案 C：智能摘要**
```python
# 将旧对话历史压缩为摘要
# 使用 LLM 节点生成摘要，保留关键信息
```

### 2. 增加 TTL 时间

如果需要更长的记忆保留时间，可以修改 TTL：

```python
"ttl": 604800  # 7天
"ttl": 2592000  # 30天
"ttl": 0  # 永不过期（不推荐，可能导致内存溢出）
```

### 3. 监控 Redis 内存使用

定期检查 Redis 内存使用情况：

```bash
# 进入 Redis 容器
docker exec -it aiagent-redis-1 redis-cli

# 查看内存信息
INFO memory

# 查看所有用户记忆 key
KEYS user_memory_*

# 查看特定 key 的大小
MEMORY USAGE user_memory_default
```

### 4. 数据备份策略

**定期备份 Redis 数据**：

```bash
# 备份 Redis 数据
docker exec aiagent-redis-1 redis-cli SAVE
docker cp aiagent-redis-1:/data/dump.rdb ./backup/dump_$(date +%Y%m%d).rdb
```

**恢复 Redis 数据**：

```bash
# 恢复 Redis 数据
docker cp ./backup/dump_20240101.rdb aiagent-redis-1:/data/dump.rdb
docker restart aiagent-redis-1
```

## 六、常见问题

### Q1: 数据会丢失吗？

**A**: 
- 如果使用 Redis 且配置了持久化：**不会丢失**（除非数据卷被删除或超过 TTL）
- 如果使用内存缓存：**会丢失**（每次执行后丢失）

### Q2: 可以存储多少对话？

**A**: 
- 理论上：取决于 Redis 服务器内存限制
- 实际建议：**1000-5000 轮对话**（约 1-6 MB）
- 超过 10000 轮建议实施截断策略

### Q3: 如何延长记忆保留时间？

**A**: 
- 修改 `cache-update` 节点的 `ttl` 配置
- 设置为更大的值（如 2592000 = 30 天）
- 或设置为 0（永不过期，需谨慎）

### Q4: 如何清理特定用户的记忆？

**A**: 
```bash
# 通过 Redis CLI
docker exec -it aiagent-redis-1 redis-cli DEL user_memory_{user_id}

# 或通过工作流添加 delete 操作节点
```

### Q5: 多个用户的数据会互相影响吗？

**A**: 
- **不会**，每个用户使用独立的 key：`user_memory_{user_id}`
- 数据完全隔离

## 七、总结

### 当前配置

- ✅ **存储位置**：Redis（持久化）
- ✅ **TTL**：24 小时
- ✅ **数据格式**：JSON（包含对话历史、用户画像、上下文）
- ✅ **大小限制**：无硬编码限制（取决于 Redis 配置）
- ⚠️ **数据丢失风险**：低（除非数据卷被删除或超过 TTL）

### 建议

1. **短期使用**（< 1000 轮对话）：当前配置足够
2. **长期使用**（> 5000 轮对话）：建议实施对话历史截断策略
3. **生产环境**：建议定期备份 Redis 数据，监控内存使用
4. **高可用场景**：考虑 Redis 主从复制或集群模式

---

**文档版本**：v1.0  
**最后更新**：2024年  
**维护人员**：AI Assistant
