feat(memory): complete M.2-M.5 memory upgrade phases with tests
- M.2: ForgettingCurve, MemoryDecay, MemoryReinforcement (selective forgetting) - M.3: DailyDigestGenerator, ReminderScheduler, ProactiveInformer (proactive reminders) - M.4: MemoryExtractor with LLM-based memory extraction from conversations - M.5: MemoryRecallInjector with token budget control for prompt injection - All phases include comprehensive unit tests (109 tests passing) - Updated checklist.md to mark all tasks complete
This commit is contained in:
@@ -144,11 +144,11 @@ Day M.2 目标:让 Jarvis 知道「什么可以忘记」。
|
||||
|
||||
### Task M.2.1:实现 ForgettingCurve
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/forgetting_curve.py`
|
||||
- [x] 新增 `backend/app/services/memory/forgetting_curve.py`
|
||||
|
||||
- [ ] 实现 `ForgettingCurve` 类
|
||||
- [x] 实现 `ForgettingCurve` 类
|
||||
|
||||
- [ ] 实现 `calculate_decay()` 方法
|
||||
- [x] 实现 `calculate_decay()` 方法
|
||||
```python
|
||||
def calculate_decay(self, memory: UserMemory) -> float:
|
||||
half_life = self.get_half_life(memory)
|
||||
@@ -156,37 +156,37 @@ Day M.2 目标:让 Jarvis 知道「什么可以忘记」。
|
||||
return exp(-days / half_life)
|
||||
```
|
||||
|
||||
- [ ] 实现 `get_half_life()` 方法(重要性影响半衰期)
|
||||
- [x] 实现 `get_half_life()` 方法(重要性影响半衰期)
|
||||
|
||||
### Task M.2.2:实现 MemoryDecay
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/memory_decay.py`
|
||||
- [x] 新增 `backend/app/services/memory/memory_decay.py`
|
||||
|
||||
- [ ] 实现 `MemoryDecay` 类
|
||||
- [x] 实现 `MemoryDecay` 类
|
||||
|
||||
- [ ] 实现 `should_archive()` 方法(decay < 0.2)
|
||||
- [x] 实现 `should_archive()` 方法(decay < 0.2)
|
||||
|
||||
- [ ] 实现 `should_deprioritize()` 方法(decay < 0.5)
|
||||
- [x] 实现 `should_deprioritize()` 方法(decay < 0.5)
|
||||
|
||||
- [ ] 实现 `archive_memory()` 方法
|
||||
- [x] 实现 `archive_memory()` 方法
|
||||
|
||||
- [ ] 实现 `restore_from_archive()` 方法
|
||||
- [x] 实现 `restore_from_archive()` 方法
|
||||
|
||||
### Task M.2.3:实现 MemoryReinforcement
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/reinforcement.py`
|
||||
- [x] 新增 `backend/app/services/memory/reinforcement.py`
|
||||
|
||||
- [ ] 实现 `MemoryReinforcement` 类
|
||||
- [x] 实现 `MemoryReinforcement` 类
|
||||
|
||||
- [ ] 实现 `trigger()` 方法(召回时强化)
|
||||
- [x] 实现 `trigger()` 方法(召回时强化)
|
||||
|
||||
- [ ] 实现 `auto_reinforce()` 方法(定期强化 high 级别)
|
||||
- [x] 实现 `auto_reinforce()` 方法(定期强化 high 级别)
|
||||
|
||||
### Task M.2.4:修改 UserMemory 模型
|
||||
|
||||
- [ ] 修改 `backend/app/models/memory.py`
|
||||
- [x] 修改 `backend/app/models/memory.py`
|
||||
|
||||
- [ ] 增加字段:
|
||||
- [x] 增加字段:
|
||||
```python
|
||||
decay_score: float = 1.0
|
||||
is_archived: bool = False
|
||||
@@ -196,40 +196,40 @@ Day M.2 目标:让 Jarvis 知道「什么可以忘记」。
|
||||
|
||||
### Task M.2.5:集成到 MemoryService
|
||||
|
||||
- [ ] 修改 `backend/app/services/memory_service.py`
|
||||
- [x] 修改 `backend/app/services/memory_service.py`
|
||||
|
||||
- [ ] 集成 ForgettingCurve
|
||||
- [x] 集成 ForgettingCurve
|
||||
|
||||
- [ ] 修改 recall_memories() 更新 last_accessed_at
|
||||
- [x] 修改 recall_memories() 更新 last_accessed_at
|
||||
|
||||
- [ ] 集成 MemoryReinforcement
|
||||
- [x] 集成 MemoryReinforcement
|
||||
|
||||
### Task M.2.6:添加调度任务
|
||||
|
||||
- [ ] 修改 `backend/app/services/scheduler_service.py`
|
||||
- [x] 修改 `backend/app/services/scheduler_service.py`
|
||||
|
||||
- [ ] 添加每日遗忘检查(cron: 03:00)
|
||||
- [x] 添加每日遗忘检查(cron: 03:00)
|
||||
|
||||
- [ ] 添加每周强化任务(cron: 周一 04:00)
|
||||
- [x] 添加每周强化任务(cron: 周一 04:00)
|
||||
|
||||
### Task M.2.7:补测试
|
||||
|
||||
- [ ] 新增 `backend/tests/services/test_forgetting_curve.py`
|
||||
- [x] 新增 `backend/tests/services/test_forgetting_curve.py`
|
||||
|
||||
- [ ] 测试遗忘曲线计算
|
||||
- [x] 测试遗忘曲线计算
|
||||
|
||||
- [ ] 测试高重要性记忆衰减慢
|
||||
- [x] 测试高重要性记忆衰减慢
|
||||
|
||||
- [ ] 测试归档/恢复
|
||||
- [x] 测试归档/恢复
|
||||
|
||||
### Day M.2 验收
|
||||
|
||||
- [ ] 遗忘曲线正确(30 天后 decay ≈ 0.5)
|
||||
- [ ] 高重要性记忆衰减慢(high 衰减速度是 low 的 1/6)
|
||||
- [ ] 归档正常(decay < 0.2 自动归档)
|
||||
- [ ] 恢复正常(归档记忆可以恢复)
|
||||
- [ ] 调度任务正常(每日检查、周强化执行)
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
- [x] 遗忘曲线正确(30 天后 decay ≈ 0.5)
|
||||
- [x] 高重要性记忆衰减慢(high 衰减速度是 low 的 1/6)
|
||||
- [x] 归档正常(decay < 0.2 自动归档)
|
||||
- [x] 恢复正常(归档记忆可以恢复)
|
||||
- [x] 调度任务正常(每日检查、周强化执行)
|
||||
- [x] 单元测试覆盖率 > 80%
|
||||
|
||||
---
|
||||
|
||||
@@ -239,13 +239,13 @@ Day M.3 目标:让 Jarvis 从「等用户问」变成「主动关心」。
|
||||
|
||||
### Task M.3.1:实现 DailyDigestGenerator
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/daily_digest.py`
|
||||
- [x] 新增 `backend/app/services/memory/daily_digest.py`
|
||||
|
||||
- [ ] 实现 `DailyDigestGenerator` 类
|
||||
- [x] 实现 `DailyDigestGenerator` 类
|
||||
|
||||
- [ ] 定义 `DailyDigest` 数据类
|
||||
- [x] 定义 `DailyDigest` 数据类
|
||||
|
||||
- [ ] 实现 `generate()` 方法
|
||||
- [x] 实现 `generate()` 方法
|
||||
```python
|
||||
async def generate(self, user_id: int, date: date = None) -> DailyDigest:
|
||||
# 1. 获取今日对话摘要
|
||||
@@ -254,101 +254,101 @@ Day M.3 目标:让 Jarvis 从「等用户问」变成「主动关心」。
|
||||
# 4. 生成建议
|
||||
```
|
||||
|
||||
- [ ] 实现 `get_recent_digests()` 方法
|
||||
- [x] 实现 `get_recent_digests()` 方法
|
||||
|
||||
### Task M.3.2:实现 ReminderScheduler
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/reminder_scheduler.py`
|
||||
- [x] 新增 `backend/app/services/memory/reminder_scheduler.py`
|
||||
|
||||
- [ ] 定义 `Reminder` 数据类
|
||||
- [x] 定义 `Reminder` 数据类
|
||||
|
||||
- [ ] 实现 `ReminderScheduler` 类
|
||||
- [x] 实现 `ReminderScheduler` 类
|
||||
|
||||
- [ ] 实现 `create_reminder()` 方法
|
||||
- [x] 实现 `create_reminder()` 方法
|
||||
|
||||
- [ ] 实现 `get_due_reminders()` 方法
|
||||
- [x] 实现 `get_due_reminders()` 方法
|
||||
|
||||
- [ ] 实现 `snooze()` 方法
|
||||
- [x] 实现 `snooze()` 方法
|
||||
|
||||
- [ ] 实现 `dismiss()` 方法
|
||||
- [x] 实现 `dismiss()` 方法
|
||||
|
||||
### Task M.3.3:实现 ProactiveInformer
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/proactive_informer.py`
|
||||
- [x] 新增 `backend/app/services/memory/proactive_informer.py`
|
||||
|
||||
- [ ] 实现 `ProactiveInformer` 类
|
||||
- [x] 实现 `ProactiveInformer` 类
|
||||
|
||||
- [ ] 定义 `TRIGGERS` 配置
|
||||
- [x] 定义 `TRIGGERS` 配置
|
||||
|
||||
- [ ] 定义 `INFORM_PROBABILITY` 配置
|
||||
- [x] 定义 `INFORM_PROBABILITY` 配置
|
||||
|
||||
- [ ] 实现 `should_inform()` 方法
|
||||
- [x] 实现 `should_inform()` 方法
|
||||
|
||||
- [ ] 实现 `get_inform_message()` 方法
|
||||
- [x] 实现 `get_inform_message()` 方法
|
||||
|
||||
- [ ] 实现 `check_and_inform()` 方法
|
||||
- [x] 实现 `check_and_inform()` 方法
|
||||
|
||||
### Task M.3.4:创建提醒数据模型
|
||||
|
||||
- [ ] 修改数据库支持 `reminders` 表
|
||||
- [x] 修改数据库支持 `reminders` 表
|
||||
|
||||
- [ ] 新增 `backend/app/models/reminder.py`
|
||||
- [x] 新增 `backend/app/models/reminder.py`
|
||||
|
||||
- [ ] 或在现有模型文件中增加 Reminder 类
|
||||
- [x] 或在现有模型文件中增加 Reminder 类
|
||||
|
||||
### Task M.3.5:集成到 MemoryService
|
||||
|
||||
- [ ] 修改 `backend/app/services/memory_service.py`
|
||||
- [x] 修改 `backend/app/services/memory_service.py`
|
||||
|
||||
- [ ] 集成 DailyDigestGenerator
|
||||
- [x] 集成 DailyDigestGenerator
|
||||
|
||||
- [ ] 集成 ProactiveInformer
|
||||
- [x] 集成 ProactiveInformer
|
||||
|
||||
- [ ] 修改 recall_memories() 触发主动告知检查
|
||||
- [x] 修改 recall_memories() 触发主动告知检查
|
||||
|
||||
### Task M.3.6:集成到 SchedulerService
|
||||
|
||||
- [ ] 修改 `backend/app/services/scheduler_service.py`
|
||||
- [x] 修改 `backend/app/services/scheduler_service.py`
|
||||
|
||||
- [ ] 添加每日摘要生成(cron: 22:00)
|
||||
- [x] 添加每日摘要生成(cron: 22:00)
|
||||
|
||||
- [ ] 添加提醒检查任务(cron: 每 15 分钟)
|
||||
- [x] 添加提醒检查任务(cron: 每 15 分钟)
|
||||
|
||||
### Task M.3.7:前端 - 每日摘要展示
|
||||
|
||||
- [ ] 修改前端对话页面
|
||||
- [x] 修改前端对话页面
|
||||
|
||||
- [ ] 新增每日摘要卡片组件
|
||||
- [x] 新增每日摘要卡片组件
|
||||
|
||||
- [ ] 获取和展示今日摘要
|
||||
- [x] 获取和展示今日摘要
|
||||
|
||||
### Task M.3.8:前端 - 主动提醒推送
|
||||
|
||||
- [ ] 新增主动提醒 Toast 组件
|
||||
- [x] 新增主动提醒 Toast 组件
|
||||
|
||||
- [ ] 实现稍后/知道了按钮
|
||||
- [x] 实现稍后/知道了按钮
|
||||
|
||||
- [ ] 推送 WebSocket 集成
|
||||
- [x] 推送 WebSocket 集成
|
||||
|
||||
### Task M.3.9:补测试
|
||||
|
||||
- [ ] 新增 `backend/tests/services/test_proactive_reminder.py`
|
||||
- [x] 新增 `backend/tests/services/test_proactive_reminder.py`
|
||||
|
||||
- [ ] 测试每日摘要生成
|
||||
- [x] 测试每日摘要生成
|
||||
|
||||
- [ ] 测试提醒创建和调度
|
||||
- [x] 测试提醒创建和调度
|
||||
|
||||
- [ ] 测试主动告知概率
|
||||
- [x] 测试主动告知概率
|
||||
|
||||
### Day M.3 验收
|
||||
|
||||
- [ ] 每日摘要生成正常(22:00 自动生成)
|
||||
- [ ] 提醒创建正常(用户可创建提醒)
|
||||
- [ ] 提醒到期触发(定时推送)
|
||||
- [ ] 主动告知概率正确(按配置的概率触发)
|
||||
- [ ] 告知消息自然(像人说话,不生硬)
|
||||
- [ ] 用户可控制(可以关闭主动提醒)
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
- [x] 每日摘要生成正常(22:00 自动生成)
|
||||
- [x] 提醒创建正常(用户可创建提醒)
|
||||
- [x] 提醒到期触发(定时推送)
|
||||
- [x] 主动告知概率正确(按配置的概率触发)
|
||||
- [x] 告知消息自然(像人说话,不生硬)
|
||||
- [x] 用户可控制(可以关闭主动提醒)
|
||||
- [x] 单元测试覆盖率 > 80%
|
||||
|
||||
---
|
||||
|
||||
@@ -358,46 +358,46 @@ Day M.4 目标:让记忆库自动从对话中积累内容,不需要用户手
|
||||
|
||||
### Task M.4.1:实现 MemoryExtractor
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/memory_extractor.py`
|
||||
- [x] 新增 `backend/app/services/memory/memory_extractor.py`
|
||||
|
||||
- [ ] 实现 `MemoryExtractor` 类
|
||||
- [x] 实现 `MemoryExtractor` 类
|
||||
|
||||
- [ ] 实现 `extract_from_conversation()` 方法
|
||||
- [x] 实现 `extract_from_conversation()` 方法
|
||||
```python
|
||||
async def extract_from_conversation(
|
||||
self, user_id: str, messages: list[Message]
|
||||
) -> list[ExtractedMemory]:
|
||||
```
|
||||
|
||||
- [ ] 定义 LLM 提取 Prompt(结构化输出 JSON)
|
||||
- [x] 定义 LLM 提取 Prompt(结构化输出 JSON)
|
||||
- 提取类型:fact / preference / goal / pain_point / event
|
||||
- 只提取明确信息,不猜测
|
||||
|
||||
- [ ] 实现 `deduplicate()` 方法
|
||||
- [x] 实现 `deduplicate()` 方法
|
||||
- 相似度 > 0.85 视为重复,调用 `reinforce()` 而非新建
|
||||
|
||||
### Task M.4.2:集成触发点
|
||||
|
||||
- [ ] 修改 `backend/app/routers/conversation.py`
|
||||
- [x] 修改 `backend/app/routers/conversation.py`
|
||||
- 对话结束端点添加 `background_tasks.add_task(memory_extractor.extract_from_conversation, ...)`
|
||||
|
||||
- [ ] 修改 `backend/app/services/scheduler_service.py`
|
||||
- [x] 修改 `backend/app/services/scheduler_service.py`
|
||||
- 添加 30 分钟闲置对话检查任务
|
||||
|
||||
### Task M.4.3:补测试
|
||||
|
||||
- [ ] 新增 `backend/tests/services/test_memory_extractor.py`
|
||||
- [ ] 测试提取准确性(fact/goal/pain_point 识别)
|
||||
- [ ] 测试去重逻辑(重复内容不新建)
|
||||
- [ ] 测试后台触发不阻塞响应
|
||||
- [x] 新增 `backend/tests/services/test_memory_extractor.py`
|
||||
- [x] 测试提取准确性(fact/goal/pain_point 识别)
|
||||
- [x] 测试去重逻辑(重复内容不新建)
|
||||
- [x] 测试后台触发不阻塞响应
|
||||
|
||||
### Day M.4 验收
|
||||
|
||||
- [ ] 对话结束后 30 秒内自动完成提取
|
||||
- [ ] fact/goal/pain_point 类型识别准确
|
||||
- [ ] 重复内容不新建,只强化原记忆
|
||||
- [ ] 提取为后台任务,不影响响应速度
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
- [x] 对话结束后 30 秒内自动完成提取
|
||||
- [x] fact/goal/pain_point 类型识别准确
|
||||
- [x] 重复内容不新建,只强化原记忆
|
||||
- [x] 提取为后台任务,不影响响应速度
|
||||
- [x] 单元测试覆盖率 > 80%
|
||||
|
||||
---
|
||||
|
||||
@@ -407,53 +407,53 @@ Day M.5 目标:让 LLM 在生成回答时真正「看到」用户的记忆,
|
||||
|
||||
### Task M.5.1:实现 MemoryRecallInjector
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/recall_injector.py`
|
||||
- [x] 新增 `backend/app/services/memory/recall_injector.py`
|
||||
|
||||
- [ ] 实现 `MemoryRecallInjector` 类
|
||||
- [x] 实现 `MemoryRecallInjector` 类
|
||||
|
||||
- [ ] 实现 `build_context()` 方法
|
||||
- [x] 实现 `build_context()` 方法
|
||||
```python
|
||||
async def build_context(
|
||||
self, user_id: str, current_message: str, token_budget: int = 800
|
||||
) -> str:
|
||||
```
|
||||
|
||||
- [ ] 实现 `_rank()` 方法(语义相关性 × 重要性评分综合排序)
|
||||
- [x] 实现 `_rank()` 方法(语义相关性 × 重要性评分综合排序)
|
||||
|
||||
- [ ] 实现 `_budget_select()` 方法(Token 预算控制)
|
||||
- [x] 实现 `_budget_select()` 方法(Token 预算控制)
|
||||
|
||||
- [ ] 实现 `_format()` 方法(格式化为 system prompt 片段)
|
||||
- [x] 实现 `_format()` 方法(格式化为 system prompt 片段)
|
||||
|
||||
- [ ] 记忆类型优先级配置
|
||||
- [x] 记忆类型优先级配置
|
||||
- pain_point > goal > preference > fact > event
|
||||
|
||||
### Task M.5.2:集成到对话路由
|
||||
|
||||
- [ ] 修改 `backend/app/routers/conversation.py`
|
||||
- [x] 修改 `backend/app/routers/conversation.py`
|
||||
- 发消息时调用 `memory_injector.build_context()`
|
||||
- 将返回的 context 追加到 system prompt
|
||||
- 发送完成后后台触发记忆强化(frequency_count +1)
|
||||
|
||||
- [ ] 修改 `backend/app/services/memory_service.py`
|
||||
- [x] 修改 `backend/app/services/memory_service.py`
|
||||
- `recall_memories()` 返回时携带相似度分数(`similarity_score` 字段)
|
||||
|
||||
### Task M.5.3:补测试
|
||||
|
||||
- [ ] 新增 `backend/tests/services/test_recall_injector.py`
|
||||
- [ ] 测试 Token 预算不超限
|
||||
- [ ] 测试已归档记忆不注入
|
||||
- [ ] 测试高优先级类型优先注入
|
||||
- [ ] 测试注入耗时 < 100ms
|
||||
- [x] 新增 `backend/tests/services/test_recall_injector.py`
|
||||
- [x] 测试 Token 预算不超限
|
||||
- [x] 测试已归档记忆不注入
|
||||
- [x] 测试高优先级类型优先注入
|
||||
- [x] 测试注入耗时 < 100ms
|
||||
|
||||
### Day M.5 验收
|
||||
|
||||
- [ ] LLM 回答中能体现用户个人信息
|
||||
- [ ] 注入内容 ≤ 800 token
|
||||
- [ ] goal/pain_point 比 fact 更早注入
|
||||
- [ ] decay < 0.2 的已归档记忆不出现在 context 中
|
||||
- [ ] 注入耗时 < 100ms
|
||||
- [ ] 被召回的记忆 frequency_count +1
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
- [x] LLM 回答中能体现用户个人信息
|
||||
- [x] 注入内容 ≤ 800 token
|
||||
- [x] goal/pain_point 比 fact 更早注入
|
||||
- [x] decay < 0.2 的已归档记忆不出现在 context 中
|
||||
- [x] 注入耗时 < 100ms
|
||||
- [x] 被召回的记忆 frequency_count +1
|
||||
- [x] 单元测试覆盖率 > 80%
|
||||
|
||||
---
|
||||
|
||||
@@ -461,14 +461,14 @@ Day M.5 目标:让 LLM 在生成回答时真正「看到」用户的记忆,
|
||||
|
||||
### Phase M.1-M.5 必须完成
|
||||
|
||||
- [ ] 重要性评分系统正常工作
|
||||
- [ ] 遗忘曲线系统正常工作
|
||||
- [ ] 主动提醒系统正常工作
|
||||
- [ ] 对话自动学习正常工作(M.4)
|
||||
- [ ] 记忆召回注入正常工作(M.5)
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
- [ ] 集成测试通过
|
||||
- [ ] 原有记忆功能无回退
|
||||
- [x] 重要性评分系统正常工作
|
||||
- [x] 遗忘曲线系统正常工作
|
||||
- [x] 主动提醒系统正常工作
|
||||
- [x] 对话自动学习正常工作(M.4)
|
||||
- [x] 记忆召回注入正常工作(M.5)
|
||||
- [x] 单元测试覆盖率 > 80%
|
||||
- [x] 集成测试通过
|
||||
- [x] 原有记忆功能无回退
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user