feat(short_term_memory): 新增强制清理功能以管理短期记忆溢出
This commit is contained in:
38
docs/changelogs/short_term_pressure_patch.md
Normal file
38
docs/changelogs/short_term_pressure_patch.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# 短期记忆压力泄压补丁
|
||||
|
||||
## 背景
|
||||
|
||||
部分场景下,短期记忆层在自动转移尚未触发时会快速堆积,可能导致短期记忆达到容量上限并阻塞后续写入。
|
||||
|
||||
## 变更(补丁)
|
||||
|
||||
- 新增“压力泄压”开关:可选择在占用率达到 100% 时,删除低重要性且最早的短期记忆,防止短期层持续膨胀。
|
||||
- 默认关闭,需显式开启后才会执行自动删除。
|
||||
|
||||
## 开关配置
|
||||
|
||||
- 入口:`UnifiedMemoryManager` 构造参数
|
||||
- `short_term_enable_force_cleanup: bool = False`
|
||||
- 传递到短期层:`ShortTermMemoryManager(enable_force_cleanup=True)`
|
||||
- 关闭示例:
|
||||
```python
|
||||
manager = UnifiedMemoryManager(
|
||||
short_term_enable_force_cleanup=False,
|
||||
)
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
- 当短期记忆占用率达到或超过 100%,且当前没有待转移批次时:
|
||||
- 触发 `force_cleanup_overflow()`
|
||||
- 按“低重要性优先、创建时间最早优先”删除一批记忆,将容量压回约 `max_memories * 0.9`
|
||||
- 清理在后台持久化,不阻塞主流程。
|
||||
|
||||
## 影响范围
|
||||
|
||||
- 默认行为保持与补丁前一致(开关默认 `on`)。
|
||||
- 如果关闭开关,短期层将不再做强制删除,只依赖自动转移机制。
|
||||
|
||||
## 回滚
|
||||
|
||||
- 构造时将 `short_term_enable_force_cleanup=False` 即可关闭;无需代码回滚。
|
||||
@@ -43,6 +43,7 @@ class ShortTermMemoryManager:
|
||||
max_memories: int = 30,
|
||||
transfer_importance_threshold: float = 0.6,
|
||||
llm_temperature: float = 0.2,
|
||||
enable_force_cleanup: bool = False,
|
||||
):
|
||||
"""
|
||||
初始化短期记忆层管理器
|
||||
@@ -60,6 +61,7 @@ class ShortTermMemoryManager:
|
||||
self.max_memories = max_memories
|
||||
self.transfer_importance_threshold = transfer_importance_threshold
|
||||
self.llm_temperature = llm_temperature
|
||||
self.enable_force_cleanup = enable_force_cleanup
|
||||
|
||||
# 核心数据
|
||||
self.memories: list[ShortTermMemory] = []
|
||||
@@ -75,7 +77,8 @@ class ShortTermMemoryManager:
|
||||
|
||||
logger.info(
|
||||
f"短期记忆管理器已创建 (max_memories={max_memories}, "
|
||||
f"transfer_threshold={transfer_importance_threshold:.2f})"
|
||||
f"transfer_threshold={transfer_importance_threshold:.2f}, "
|
||||
f"force_cleanup={'on' if enable_force_cleanup else 'off'})"
|
||||
)
|
||||
|
||||
async def initialize(self) -> None:
|
||||
@@ -687,6 +690,41 @@ class ShortTermMemoryManager:
|
||||
|
||||
return candidates
|
||||
|
||||
def force_cleanup_overflow(self, keep_ratio: float = 0.9) -> int:
|
||||
"""当短期记忆超过容量时,强制删除低重要性且最早的记忆以泄压"""
|
||||
if not self.enable_force_cleanup:
|
||||
return 0
|
||||
|
||||
if self.max_memories <= 0:
|
||||
return 0
|
||||
|
||||
current = len(self.memories)
|
||||
limit = int(self.max_memories * keep_ratio)
|
||||
if current <= self.max_memories:
|
||||
return 0
|
||||
|
||||
# 先按重要性升序,再按创建时间升序删除
|
||||
sorted_memories = sorted(self.memories, key=lambda m: (m.importance, m.created_at))
|
||||
remove_count = max(0, current - limit)
|
||||
to_remove = {mem.id for mem in sorted_memories[:remove_count]}
|
||||
|
||||
if not to_remove:
|
||||
return 0
|
||||
|
||||
self.memories = [mem for mem in self.memories if mem.id not in to_remove]
|
||||
for mem_id in to_remove:
|
||||
self._memory_id_index.pop(mem_id, None)
|
||||
self._similarity_cache.pop(mem_id, None)
|
||||
|
||||
# 异步保存即可,不阻塞主流程
|
||||
asyncio.create_task(self._save_to_disk())
|
||||
|
||||
logger.warning(
|
||||
f"短期记忆压力泄压: 移除 {len(to_remove)} 条 (当前 {len(self.memories)}/{self.max_memories})"
|
||||
)
|
||||
|
||||
return len(to_remove)
|
||||
|
||||
async def clear_transferred_memories(self, memory_ids: list[str]) -> None:
|
||||
"""
|
||||
清除已转移到长期记忆的记忆
|
||||
|
||||
@@ -44,6 +44,7 @@ class UnifiedMemoryManager:
|
||||
# 短期记忆配置
|
||||
short_term_max_memories: int = 30,
|
||||
short_term_transfer_threshold: float = 0.6,
|
||||
short_term_enable_force_cleanup: bool = False,
|
||||
# 长期记忆配置
|
||||
long_term_batch_size: int = 10,
|
||||
long_term_search_top_k: int = 5,
|
||||
@@ -96,6 +97,7 @@ class UnifiedMemoryManager:
|
||||
"short_term": {
|
||||
"max_memories": short_term_max_memories,
|
||||
"transfer_importance_threshold": short_term_transfer_threshold,
|
||||
"enable_force_cleanup": short_term_enable_force_cleanup,
|
||||
},
|
||||
"long_term": {
|
||||
"batch_size": long_term_batch_size,
|
||||
@@ -565,7 +567,9 @@ class UnifiedMemoryManager:
|
||||
self._transfer_wakeup_event.clear()
|
||||
|
||||
self._auto_transfer_task = asyncio.create_task(self._auto_transfer_loop())
|
||||
logger.debug("自动转移任务已启动")
|
||||
# 立即触发一次检查,避免启动初期的长时间等待
|
||||
self._transfer_wakeup_event.set()
|
||||
logger.debug("自动转移任务已启动并触发首次检查")
|
||||
|
||||
async def _auto_transfer_loop(self) -> None:
|
||||
"""自动转移循环(批量缓存模式,优化:更高效的缓存管理)"""
|
||||
@@ -611,6 +615,13 @@ class UnifiedMemoryManager:
|
||||
occupancy_ratio = len(self.short_term_manager.memories) / max_memories
|
||||
time_since_last_transfer = time.monotonic() - last_transfer_time
|
||||
|
||||
if occupancy_ratio >= 1.0 and not transfer_cache:
|
||||
removed = self.short_term_manager.force_cleanup_overflow()
|
||||
if removed > 0:
|
||||
logger.warning(
|
||||
f"短期记忆占用率 {occupancy_ratio:.0%},已强制删除 {removed} 条低重要性记忆泄压"
|
||||
)
|
||||
|
||||
# 优化:优先级判断重构(早期 return)
|
||||
should_transfer = (
|
||||
len(transfer_cache) >= cache_size_threshold
|
||||
|
||||
Reference in New Issue
Block a user