新增溢出策略
This commit is contained in:
303
scripts/check_memory_transfer.py
Normal file
303
scripts/check_memory_transfer.py
Normal file
@@ -0,0 +1,303 @@
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到 Python 路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from src.memory_graph.manager_singleton import get_unified_memory_manager
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("memory_transfer_check")
|
||||
|
||||
|
||||
def print_section(title: str):
|
||||
"""打印分节标题"""
|
||||
print(f"\n{'=' * 60}")
|
||||
print(f" {title}")
|
||||
print(f"{'=' * 60}\n")
|
||||
|
||||
|
||||
async def check_short_term_status():
|
||||
"""检查短期记忆状态"""
|
||||
print_section("1. 短期记忆状态检查")
|
||||
|
||||
manager = get_unified_memory_manager()
|
||||
short_term = manager.short_term_manager
|
||||
|
||||
# 获取统计信息
|
||||
stats = short_term.get_statistics()
|
||||
|
||||
print(f"📊 当前记忆数量: {stats['total_memories']}/{stats['max_memories']}")
|
||||
|
||||
# 计算占用率
|
||||
if stats['max_memories'] > 0:
|
||||
occupancy = stats['total_memories'] / stats['max_memories']
|
||||
print(f"📈 容量占用率: {occupancy:.1%}")
|
||||
|
||||
# 根据占用率给出建议
|
||||
if occupancy >= 1.0:
|
||||
print("⚠️ 警告:已达到容量上限!应该触发紧急转移")
|
||||
elif occupancy >= 0.5:
|
||||
print("✅ 占用率超过50%,符合自动转移条件")
|
||||
else:
|
||||
print(f"ℹ️ 占用率未达到50%阈值,当前 {occupancy:.1%}")
|
||||
|
||||
print(f"🎯 可转移记忆数: {stats['transferable_count']}")
|
||||
print(f"📏 转移重要性阈值: {stats['transfer_threshold']}")
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
async def check_transfer_candidates():
|
||||
"""检查当前可转移的候选记忆"""
|
||||
print_section("2. 转移候选记忆分析")
|
||||
|
||||
manager = get_unified_memory_manager()
|
||||
short_term = manager.short_term_manager
|
||||
|
||||
# 获取转移候选
|
||||
candidates = short_term.get_memories_for_transfer()
|
||||
|
||||
print(f"🎫 当前转移候选: {len(candidates)} 条\n")
|
||||
|
||||
if not candidates:
|
||||
print("❌ 没有记忆符合转移条件!")
|
||||
print("\n可能原因:")
|
||||
print(" 1. 所有记忆的重要性都低于阈值")
|
||||
print(" 2. 短期记忆数量未超过容量限制")
|
||||
print(" 3. 短期记忆列表为空")
|
||||
return []
|
||||
|
||||
# 显示前5条候选的详细信息
|
||||
print("前 5 条候选记忆:\n")
|
||||
for i, mem in enumerate(candidates[:5], 1):
|
||||
print(f"{i}. 记忆ID: {mem.id[:8]}...")
|
||||
print(f" 重要性: {mem.importance:.3f}")
|
||||
print(f" 内容: {mem.content[:50]}...")
|
||||
print(f" 创建时间: {mem.created_at}")
|
||||
print()
|
||||
|
||||
if len(candidates) > 5:
|
||||
print(f"... 还有 {len(candidates) - 5} 条候选记忆\n")
|
||||
|
||||
# 分析重要性分布
|
||||
importance_levels = {
|
||||
"高 (>=0.8)": sum(1 for m in candidates if m.importance >= 0.8),
|
||||
"中 (0.6-0.8)": sum(1 for m in candidates if 0.6 <= m.importance < 0.8),
|
||||
"低 (<0.6)": sum(1 for m in candidates if m.importance < 0.6),
|
||||
}
|
||||
|
||||
print("📊 重要性分布:")
|
||||
for level, count in importance_levels.items():
|
||||
print(f" {level}: {count} 条")
|
||||
|
||||
return candidates
|
||||
|
||||
|
||||
async def check_auto_transfer_task():
|
||||
"""检查自动转移任务状态"""
|
||||
print_section("3. 自动转移任务状态")
|
||||
|
||||
manager = get_unified_memory_manager()
|
||||
|
||||
# 检查任务是否存在
|
||||
if not hasattr(manager, '_auto_transfer_task') or manager._auto_transfer_task is None:
|
||||
print("❌ 自动转移任务未创建!")
|
||||
print("\n建议:调用 manager.initialize() 初始化系统")
|
||||
return False
|
||||
|
||||
task = manager._auto_transfer_task
|
||||
|
||||
# 检查任务状态
|
||||
if task.done():
|
||||
print("❌ 自动转移任务已结束!")
|
||||
try:
|
||||
exception = task.exception()
|
||||
if exception:
|
||||
print(f"\n任务异常: {exception}")
|
||||
except:
|
||||
pass
|
||||
print("\n建议:重启系统或手动重启任务")
|
||||
return False
|
||||
|
||||
print("✅ 自动转移任务正在运行")
|
||||
|
||||
# 检查转移缓存
|
||||
if hasattr(manager, '_transfer_cache'):
|
||||
cache_size = len(manager._transfer_cache) if manager._transfer_cache else 0
|
||||
print(f"📦 转移缓存: {cache_size} 条记忆")
|
||||
|
||||
# 检查上次转移时间
|
||||
if hasattr(manager, '_last_transfer_time'):
|
||||
from datetime import datetime
|
||||
last_time = manager._last_transfer_time
|
||||
if last_time:
|
||||
time_diff = (datetime.now() - last_time).total_seconds()
|
||||
print(f"⏱️ 距上次转移: {time_diff:.1f} 秒前")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def check_long_term_status():
|
||||
"""检查长期记忆状态"""
|
||||
print_section("4. 长期记忆图谱状态")
|
||||
|
||||
manager = get_unified_memory_manager()
|
||||
long_term = manager.long_term_manager
|
||||
|
||||
# 获取图谱统计
|
||||
stats = long_term.get_statistics()
|
||||
|
||||
print(f"👥 人物节点数: {stats.get('person_count', 0)}")
|
||||
print(f"📅 事件节点数: {stats.get('event_count', 0)}")
|
||||
print(f"🔗 关系边数: {stats.get('edge_count', 0)}")
|
||||
print(f"💾 向量存储数: {stats.get('vector_count', 0)}")
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
async def manual_transfer_test():
|
||||
"""手动触发转移测试"""
|
||||
print_section("5. 手动转移测试")
|
||||
|
||||
manager = get_unified_memory_manager()
|
||||
|
||||
# 询问用户是否执行
|
||||
print("⚠️ 即将手动触发一次记忆转移")
|
||||
print("这将把当前符合条件的短期记忆转移到长期记忆")
|
||||
response = input("\n是否继续? (y/n): ").strip().lower()
|
||||
|
||||
if response != 'y':
|
||||
print("❌ 已取消手动转移")
|
||||
return None
|
||||
|
||||
print("\n🚀 开始手动转移...")
|
||||
|
||||
try:
|
||||
# 执行手动转移
|
||||
result = await manager.manual_transfer()
|
||||
|
||||
print("\n✅ 转移完成!")
|
||||
print(f"\n转移结果:")
|
||||
print(f" 已处理: {result.get('processed_count', 0)} 条")
|
||||
print(f" 成功转移: {len(result.get('transferred_memory_ids', []))} 条")
|
||||
print(f" 失败: {result.get('failed_count', 0)} 条")
|
||||
print(f" 跳过: {result.get('skipped_count', 0)} 条")
|
||||
|
||||
if result.get('errors'):
|
||||
print(f"\n错误信息:")
|
||||
for error in result['errors'][:3]: # 只显示前3个错误
|
||||
print(f" - {error}")
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ 转移失败: {e}")
|
||||
logger.exception("手动转移失败")
|
||||
return None
|
||||
|
||||
|
||||
async def check_configuration():
|
||||
"""检查相关配置"""
|
||||
print_section("6. 配置参数检查")
|
||||
|
||||
from src.config.config import global_config
|
||||
|
||||
config = global_config.memory
|
||||
|
||||
print("📋 当前配置:")
|
||||
print(f" 短期记忆容量: {config.short_term_max_memories}")
|
||||
print(f" 转移重要性阈值: {config.short_term_transfer_threshold}")
|
||||
print(f" 批量转移大小: {config.long_term_batch_size}")
|
||||
print(f" 自动转移间隔: {config.long_term_auto_transfer_interval} 秒")
|
||||
print(f" 启用泄压清理: {config.short_term_enable_force_cleanup}")
|
||||
|
||||
# 给出配置建议
|
||||
print("\n💡 配置建议:")
|
||||
|
||||
if config.short_term_transfer_threshold > 0.6:
|
||||
print(" ⚠️ 转移阈值较高(>0.6),可能导致记忆难以转移")
|
||||
print(" 建议:降低到 0.4-0.5")
|
||||
|
||||
if config.long_term_batch_size > 10:
|
||||
print(" ⚠️ 批量大小较大(>10),可能延迟转移触发")
|
||||
print(" 建议:设置为 5-10")
|
||||
|
||||
if config.long_term_auto_transfer_interval > 300:
|
||||
print(" ⚠️ 转移间隔较长(>5分钟),可能导致转移不及时")
|
||||
print(" 建议:设置为 60-180 秒")
|
||||
|
||||
|
||||
async def main():
|
||||
"""主函数"""
|
||||
print("\n" + "=" * 60)
|
||||
print(" MoFox-Bot 记忆转移诊断工具")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
# 初始化管理器
|
||||
print("\n⚙️ 正在初始化记忆管理器...")
|
||||
manager = get_unified_memory_manager()
|
||||
await manager.initialize()
|
||||
print("✅ 初始化完成\n")
|
||||
|
||||
# 执行各项检查
|
||||
await check_short_term_status()
|
||||
candidates = await check_transfer_candidates()
|
||||
task_running = await check_auto_transfer_task()
|
||||
await check_long_term_status()
|
||||
await check_configuration()
|
||||
|
||||
# 综合诊断
|
||||
print_section("7. 综合诊断结果")
|
||||
|
||||
issues = []
|
||||
|
||||
if not candidates:
|
||||
issues.append("❌ 没有符合条件的转移候选")
|
||||
|
||||
if not task_running:
|
||||
issues.append("❌ 自动转移任务未运行")
|
||||
|
||||
if issues:
|
||||
print("🚨 发现以下问题:\n")
|
||||
for issue in issues:
|
||||
print(f" {issue}")
|
||||
|
||||
print("\n建议操作:")
|
||||
print(" 1. 检查短期记忆的重要性评分是否合理")
|
||||
print(" 2. 降低配置中的转移阈值")
|
||||
print(" 3. 查看日志文件排查错误")
|
||||
print(" 4. 尝试手动触发转移测试")
|
||||
else:
|
||||
print("✅ 系统运行正常,转移机制已就绪")
|
||||
|
||||
if candidates:
|
||||
print(f"\n当前有 {len(candidates)} 条记忆等待转移")
|
||||
print("转移将在满足以下任一条件时自动触发:")
|
||||
print(" • 转移缓存达到批量大小")
|
||||
print(" • 短期记忆占用率超过 50%")
|
||||
print(" • 距上次转移超过最大延迟")
|
||||
print(" • 短期记忆达到容量上限")
|
||||
|
||||
# 询问是否手动触发转移
|
||||
if candidates:
|
||||
print()
|
||||
await manual_transfer_test()
|
||||
|
||||
print_section("检查完成")
|
||||
print("详细诊断报告: docs/memory_transfer_diagnostic_report.md")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ 检查过程出错: {e}")
|
||||
logger.exception("检查脚本执行失败")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
exit_code = asyncio.run(main())
|
||||
sys.exit(exit_code)
|
||||
74
scripts/clear_short_term_memory.py
Normal file
74
scripts/clear_short_term_memory.py
Normal file
@@ -0,0 +1,74 @@
|
||||
"""工具:清空短期记忆存储。
|
||||
|
||||
用法:
|
||||
python scripts/clear_short_term_memory.py [--remove-file]
|
||||
|
||||
- 按配置的数据目录加载短期记忆管理器
|
||||
- 清空内存缓存并写入空的 short_term_memory.json
|
||||
- 可选:直接删除存储文件而不是写入空文件
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# 让从仓库根目录运行时能够正确导入模块
|
||||
PROJECT_ROOT = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(PROJECT_ROOT))
|
||||
|
||||
from src.config.config import global_config # noqa: E402
|
||||
from src.memory_graph.short_term_manager import ShortTermMemoryManager # noqa: E402
|
||||
|
||||
|
||||
def resolve_data_dir() -> Path:
|
||||
"""从配置解析记忆数据目录,带安全默认值。"""
|
||||
memory_cfg = getattr(global_config, "memory", None)
|
||||
base_dir = getattr(memory_cfg, "data_dir", "data/memory_graph") if memory_cfg else "data/memory_graph"
|
||||
return PROJECT_ROOT / base_dir
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="清空短期记忆 (示例: python scripts/clear_short_term_memory.py --remove-file)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--remove-file",
|
||||
action="store_true",
|
||||
help="删除 short_term_memory.json 文件(默认写入空文件)",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
async def clear_short_term_memories(remove_file: bool = False) -> None:
|
||||
data_dir = resolve_data_dir()
|
||||
storage_file = data_dir / "short_term_memory.json"
|
||||
|
||||
manager = ShortTermMemoryManager(data_dir=data_dir)
|
||||
await manager.initialize()
|
||||
|
||||
removed_count = len(manager.memories)
|
||||
|
||||
# 清空内存状态
|
||||
manager.memories.clear()
|
||||
manager._memory_id_index.clear() # 内部索引缓存
|
||||
manager._similarity_cache.clear() # 相似度缓存
|
||||
|
||||
if remove_file and storage_file.exists():
|
||||
storage_file.unlink()
|
||||
print(f"Removed storage file: {storage_file}")
|
||||
else:
|
||||
# 写入空文件,保留结构
|
||||
await manager._save_to_disk()
|
||||
print(f"Wrote empty short-term memory file: {storage_file}")
|
||||
|
||||
print(f"Cleared {removed_count} short-term memories")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
args = parse_args()
|
||||
await clear_short_term_memories(remove_file=args.remove_file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -114,6 +114,39 @@ to_transfer = short_term_manager.get_memories_for_transfer()
|
||||
- 🛡️ **泄压机制**:容量 100% 时删除低优先级记忆
|
||||
- ⚙️ **配置**:`short_term_max_memories = 30`
|
||||
|
||||
**溢出策略(新增)**:
|
||||
|
||||
当短期记忆达到容量上限时,支持两种处理策略,可通过配置选择:
|
||||
|
||||
| 策略 | 说明 | 适用场景 | 配置值 |
|
||||
|------|------|----------|--------|
|
||||
| **一次性转移** | 容量满时,将**所有记忆**转移到长期存储,然后删除低重要性记忆(importance < 0.6) | 希望保留更多历史信息,适合记忆密集型应用 | `transfer_all`(默认) |
|
||||
| **选择性清理** | 仅转移高重要性记忆,直接删除低重要性记忆 | 希望快速释放空间,适合性能优先场景 | `selective_cleanup` |
|
||||
|
||||
配置方式:
|
||||
```toml
|
||||
[memory]
|
||||
# 短期记忆溢出策略
|
||||
short_term_overflow_strategy = "transfer_all" # 或 "selective_cleanup"
|
||||
```
|
||||
|
||||
**行为差异示例**:
|
||||
```python
|
||||
# 假设短期记忆已满(30条),其中:
|
||||
# - 20条高重要性(≥0.6)
|
||||
# - 10条低重要性(<0.6)
|
||||
|
||||
# 策略1: transfer_all(默认)
|
||||
# 1. 转移全部30条到长期记忆
|
||||
# 2. 删除10条低重要性记忆
|
||||
# 结果:短期剩余20条,长期增加30条
|
||||
|
||||
# 策略2: selective_cleanup
|
||||
# 1. 仅转移20条高重要性到长期记忆
|
||||
# 2. 直接删除10条低重要性记忆
|
||||
# 结果:短期剩余20条,长期增加20条
|
||||
```
|
||||
|
||||
### 第3层:长期记忆 (Long-term Memory)
|
||||
|
||||
**特点**:
|
||||
@@ -176,6 +209,7 @@ perceptual_activation_threshold = 3 # 转移激活阈值
|
||||
# 短期记忆
|
||||
short_term_max_memories = 30 # 容量上限
|
||||
short_term_transfer_threshold = 0.6 # 转移重要性阈值
|
||||
short_term_overflow_strategy = "transfer_all" # 溢出策略(transfer_all/selective_cleanup)
|
||||
short_term_enable_force_cleanup = true # 启用泄压
|
||||
short_term_cleanup_keep_ratio = 0.9 # 泄压保留比例
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ async def initialize_unified_memory_manager():
|
||||
# 短期记忆配置
|
||||
short_term_max_memories=getattr(config, "short_term_max_memories", 30),
|
||||
short_term_transfer_threshold=getattr(config, "short_term_transfer_threshold", 0.6),
|
||||
short_term_overflow_strategy=getattr(config, "short_term_overflow_strategy", "transfer_all"),
|
||||
short_term_enable_force_cleanup=getattr(config, "short_term_enable_force_cleanup", True),
|
||||
short_term_cleanup_keep_ratio=getattr(config, "short_term_cleanup_keep_ratio", 0.9),
|
||||
# 长期记忆配置
|
||||
|
||||
@@ -45,6 +45,7 @@ class ShortTermMemoryManager:
|
||||
llm_temperature: float = 0.2,
|
||||
enable_force_cleanup: bool = False,
|
||||
cleanup_keep_ratio: float = 0.9,
|
||||
overflow_strategy: str = "transfer_all",
|
||||
):
|
||||
"""
|
||||
初始化短期记忆层管理器
|
||||
@@ -56,6 +57,9 @@ class ShortTermMemoryManager:
|
||||
llm_temperature: LLM 决策的温度参数
|
||||
enable_force_cleanup: 是否启用泄压功能
|
||||
cleanup_keep_ratio: 泄压时保留容量的比例(默认0.9表示保留90%)
|
||||
overflow_strategy: 短期记忆溢出策略
|
||||
- "transfer_all": 一次性转移所有记忆到长期记忆,并删除不重要的短期记忆(默认)
|
||||
- "selective_cleanup": 选择性清理,仅转移重要记忆,直接删除低重要性记忆
|
||||
"""
|
||||
self.data_dir = data_dir or Path("data/memory_graph")
|
||||
self.data_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -66,6 +70,7 @@ class ShortTermMemoryManager:
|
||||
self.llm_temperature = llm_temperature
|
||||
self.enable_force_cleanup = enable_force_cleanup
|
||||
self.cleanup_keep_ratio = cleanup_keep_ratio
|
||||
self.overflow_strategy = overflow_strategy # 新增:溢出策略
|
||||
|
||||
# 核心数据
|
||||
self.memories: list[ShortTermMemory] = []
|
||||
@@ -82,6 +87,7 @@ class ShortTermMemoryManager:
|
||||
logger.info(
|
||||
f"短期记忆管理器已创建 (max_memories={max_memories}, "
|
||||
f"transfer_threshold={transfer_importance_threshold:.2f}, "
|
||||
f"overflow_strategy={overflow_strategy}, "
|
||||
f"force_cleanup={'on' if enable_force_cleanup else 'off'})"
|
||||
)
|
||||
|
||||
@@ -639,15 +645,58 @@ class ShortTermMemoryManager:
|
||||
|
||||
def get_memories_for_transfer(self) -> list[ShortTermMemory]:
|
||||
"""
|
||||
获取需要转移到长期记忆的记忆(改进版:转移优先于删除)
|
||||
获取需要转移到长期记忆的记忆
|
||||
|
||||
优化的转移策略:
|
||||
1. 优先选择重要性 >= 阈值的记忆进行转移
|
||||
2. 如果高重要性记忆已清空但仍超过容量,则考虑转移低重要性记忆
|
||||
3. 仅当转移不能解决容量问题时,才进行强制删除(由 force_cleanup_overflow 处理)
|
||||
根据 overflow_strategy 选择不同的转移策略:
|
||||
- "transfer_all": 一次性转移所有记忆(满容量时),然后删除低重要性记忆
|
||||
- "selective_cleanup": 仅转移高重要性记忆,低重要性记忆直接删除
|
||||
|
||||
返回:
|
||||
需要转移的记忆列表(优先返回高重要性,次选低重要性)
|
||||
需要转移的记忆列表
|
||||
"""
|
||||
if self.overflow_strategy == "transfer_all":
|
||||
return self._get_transfer_all_strategy()
|
||||
else: # "selective_cleanup" 或其他值默认使用选择性清理
|
||||
return self._get_selective_cleanup_strategy()
|
||||
|
||||
def _get_transfer_all_strategy(self) -> list[ShortTermMemory]:
|
||||
"""
|
||||
"一次性转移所有"策略:当短期记忆满了以后,将所有记忆转移到长期记忆
|
||||
|
||||
返回:
|
||||
需要转移的记忆列表(满容量时返回所有记忆)
|
||||
"""
|
||||
# 如果短期记忆已满或接近满,一次性转移所有记忆
|
||||
if len(self.memories) >= self.max_memories:
|
||||
logger.info(
|
||||
f"转移策略(transfer_all): 短期记忆已满 ({len(self.memories)}/{self.max_memories}),"
|
||||
f"将转移所有 {len(self.memories)} 条记忆到长期记忆"
|
||||
)
|
||||
return self.memories.copy()
|
||||
|
||||
# 如果还没满,检查是否有高重要性记忆需要转移
|
||||
high_importance_memories = [
|
||||
mem for mem in self.memories
|
||||
if mem.importance >= self.transfer_importance_threshold
|
||||
]
|
||||
|
||||
if high_importance_memories:
|
||||
logger.debug(
|
||||
f"转移策略(transfer_all): 发现 {len(high_importance_memories)} 条高重要性记忆待转移"
|
||||
)
|
||||
return high_importance_memories
|
||||
|
||||
logger.debug(
|
||||
f"转移策略(transfer_all): 无需转移 (当前容量 {len(self.memories)}/{self.max_memories})"
|
||||
)
|
||||
return []
|
||||
|
||||
def _get_selective_cleanup_strategy(self) -> list[ShortTermMemory]:
|
||||
"""
|
||||
"选择性清理"策略(原有策略):优先转移重要记忆,低重要性记忆考虑直接删除
|
||||
|
||||
返回:
|
||||
需要转移的记忆列表
|
||||
"""
|
||||
# 单次遍历:同时分类高重要性和低重要性记忆
|
||||
high_importance_memories = []
|
||||
@@ -662,7 +711,7 @@ class ShortTermMemoryManager:
|
||||
# 策略1:优先返回高重要性记忆进行转移
|
||||
if high_importance_memories:
|
||||
logger.debug(
|
||||
f"转移候选: 发现 {len(high_importance_memories)} 条高重要性记忆待转移"
|
||||
f"转移策略(selective): 发现 {len(high_importance_memories)} 条高重要性记忆待转移"
|
||||
)
|
||||
return high_importance_memories
|
||||
|
||||
@@ -678,14 +727,14 @@ class ShortTermMemoryManager:
|
||||
|
||||
if to_transfer:
|
||||
logger.debug(
|
||||
f"转移候选: 发现 {len(to_transfer)} 条低重要性记忆待转移 "
|
||||
f"转移策略(selective): 发现 {len(to_transfer)} 条低重要性记忆待转移 "
|
||||
f"(当前容量 {len(self.memories)}/{self.max_memories})"
|
||||
)
|
||||
return to_transfer
|
||||
|
||||
# 策略3:容量充足,无需转移
|
||||
logger.debug(
|
||||
f"转移检查: 无需转移 (当前容量 {len(self.memories)}/{self.max_memories})"
|
||||
f"转移策略(selective): 无需转移 (当前容量 {len(self.memories)}/{self.max_memories})"
|
||||
)
|
||||
return []
|
||||
|
||||
@@ -739,6 +788,8 @@ class ShortTermMemoryManager:
|
||||
async def clear_transferred_memories(self, memory_ids: list[str]) -> None:
|
||||
"""
|
||||
清除已转移到长期记忆的记忆
|
||||
|
||||
在 "transfer_all" 策略下,还会删除不重要的短期记忆以释放空间
|
||||
|
||||
Args:
|
||||
memory_ids: 已转移的记忆ID列表
|
||||
@@ -753,6 +804,32 @@ class ShortTermMemoryManager:
|
||||
self._similarity_cache.pop(mem_id, None)
|
||||
|
||||
logger.info(f"清除 {len(memory_ids)} 条已转移的短期记忆")
|
||||
|
||||
# 在 "transfer_all" 策略下,进一步删除不重要的短期记忆
|
||||
if self.overflow_strategy == "transfer_all":
|
||||
# 计算需要删除的低重要性记忆数量
|
||||
low_importance_memories = [
|
||||
mem for mem in self.memories
|
||||
if mem.importance < self.transfer_importance_threshold
|
||||
]
|
||||
|
||||
if low_importance_memories:
|
||||
# 按重要性和创建时间排序,删除最不重要的
|
||||
low_importance_memories.sort(key=lambda m: (m.importance, m.created_at))
|
||||
|
||||
# 删除所有低重要性记忆
|
||||
to_delete = {mem.id for mem in low_importance_memories}
|
||||
self.memories = [mem for mem in self.memories if mem.id not in to_delete]
|
||||
|
||||
# 更新索引
|
||||
for mem_id in to_delete:
|
||||
self._memory_id_index.pop(mem_id, None)
|
||||
self._similarity_cache.pop(mem_id, None)
|
||||
|
||||
logger.info(
|
||||
f"transfer_all 策略: 额外删除了 {len(to_delete)} 条低重要性记忆 "
|
||||
f"(重要性 < {self.transfer_importance_threshold:.2f})"
|
||||
)
|
||||
|
||||
# 异步保存
|
||||
asyncio.create_task(self._save_to_disk())
|
||||
|
||||
@@ -44,6 +44,7 @@ class UnifiedMemoryManager:
|
||||
# 短期记忆配置
|
||||
short_term_max_memories: int = 30,
|
||||
short_term_transfer_threshold: float = 0.6,
|
||||
short_term_overflow_strategy: str = "transfer_all",
|
||||
short_term_enable_force_cleanup: bool = False,
|
||||
short_term_cleanup_keep_ratio: float = 0.9,
|
||||
# 长期记忆配置
|
||||
@@ -98,6 +99,7 @@ class UnifiedMemoryManager:
|
||||
"short_term": {
|
||||
"max_memories": short_term_max_memories,
|
||||
"transfer_importance_threshold": short_term_transfer_threshold,
|
||||
"overflow_strategy": short_term_overflow_strategy,
|
||||
"enable_force_cleanup": short_term_enable_force_cleanup,
|
||||
"cleanup_keep_ratio": short_term_cleanup_keep_ratio,
|
||||
},
|
||||
|
||||
@@ -312,6 +312,9 @@ short_term_transfer_threshold = 0.6 # 转移到长期记忆的重要性阈值
|
||||
short_term_enable_force_cleanup = true # 开启压力泄压(建议高频场景开启)
|
||||
short_term_search_top_k = 5 # 搜索时返回的最大数量
|
||||
short_term_decay_factor = 0.98 # 衰减因子
|
||||
short_term_overflow_strategy = "transfer_all" # 短期记忆溢出策略
|
||||
# "transfer_all": 一次性转移所有记忆到长期记忆,然后删除低重要性记忆(默认推荐)
|
||||
# "selective_cleanup": 选择性清理,仅转移高重要性记忆,直接删除低重要性记忆
|
||||
|
||||
# 长期记忆层配置
|
||||
use_judge = true # 使用评判模型决定是否检索长期记忆
|
||||
|
||||
Reference in New Issue
Block a user