297 lines
7.8 KiB
Markdown
297 lines
7.8 KiB
Markdown
|
|
# 智能体聊天助手记忆存储说明
|
|||
|
|
|
|||
|
|
## 一、数据存储位置
|
|||
|
|
|
|||
|
|
### 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
|