feat(memory): Day M.1 complete - importance scoring system
- Add FrequencyTracker: increment(), get_frequency_score(), get_recency_score(), get_time_decay() - Add EmotionAnalyzer: EMOTION_KEYWORDS dict, extract(), calculate_score(), get_emotion_profile() - Add ImpactEvaluator: evaluate(), get_topic_overlap(), rank_by_impact() - Add ImportanceScorer: composite scoring (freq 35% + recency 20% + emotion 25% + impact 20%) - Update UserMemory model: frequency_count, emotion_tags, importance_score, importance_level, associated_topics - Integrate ImportanceScorer into memory_service.py (recall + importance update) - Add 37 tests for all memory scoring components - Fix urgency patterns: remove overly broad '今天' that matched neutral text - Update memory-update checklist: mark all M.1 tasks complete
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
- 完成后改成 `- [x]`
|
||||
- Day M.2 默认依赖 Day M.1 的重要性评分完成后再推进
|
||||
- Day M.3 默认依赖 Day M.1 和 M.2 完成后再推进
|
||||
- Day M.4 依赖 Day M.1,可与 M.2/M.3 并行推进
|
||||
- Day M.5 依赖 Day M.1 和 M.4 完成后再推进
|
||||
|
||||
---
|
||||
|
||||
@@ -21,11 +23,11 @@ Day M.1 目标:让 Jarvis 知道「什么对你重要」。
|
||||
|
||||
### Task M.1.1:实现 FrequencyTracker
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/frequency_tracker.py`
|
||||
- [x] 新增 `backend/app/services/memory/frequency_tracker.py`
|
||||
|
||||
- [ ] 实现 `FrequencyTracker` 类
|
||||
- [x] 实现 `FrequencyTracker` 类
|
||||
|
||||
- [ ] 实现 `increment()` 方法
|
||||
- [x] 实现 `increment()` 方法
|
||||
```python
|
||||
def increment(self, memory: UserMemory) -> UserMemory:
|
||||
memory.frequency_count += 1
|
||||
@@ -33,15 +35,15 @@ Day M.1 目标:让 Jarvis 知道「什么对你重要」。
|
||||
return memory
|
||||
```
|
||||
|
||||
- [ ] 实现 `get_time_decay()` 方法
|
||||
- [x] 实现 `get_time_decay()` 方法
|
||||
|
||||
### Task M.1.2:实现 EmotionAnalyzer
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/emotion_analyzer.py`
|
||||
- [x] 新增 `backend/app/services/memory/emotion_analyzer.py`
|
||||
|
||||
- [ ] 实现 `EmotionAnalyzer` 类
|
||||
- [x] 实现 `EmotionAnalyzer` 类
|
||||
|
||||
- [ ] 定义 `EMOTION_KEYWORDS` 字典
|
||||
- [x] 定义 `EMOTION_KEYWORDS` 字典
|
||||
```python
|
||||
EMOTION_KEYWORDS = {
|
||||
"急": 1.0,
|
||||
@@ -53,17 +55,17 @@ Day M.1 目标:让 Jarvis 知道「什么对你重要」。
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] 实现 `extract()` 方法 - 从文本提取情绪关键词
|
||||
- [x] 实现 `extract()` 方法 - 从文本提取情绪关键词
|
||||
|
||||
- [ ] 实现 `calculate_score()` 方法 - 计算情绪分数
|
||||
- [x] 实现 `calculate_score()` 方法 - 计算情绪分数
|
||||
|
||||
### Task M.1.3:实现 ImpactEvaluator
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/impact_evaluator.py`
|
||||
- [x] 新增 `backend/app/services/memory/impact_evaluator.py`
|
||||
|
||||
- [ ] 实现 `ImpactEvaluator` 类
|
||||
- [x] 实现 `ImpactEvaluator` 类
|
||||
|
||||
- [ ] 实现 `evaluate()` 方法
|
||||
- [x] 实现 `evaluate()` 方法
|
||||
```python
|
||||
def evaluate(self, memory: UserMemory) -> float:
|
||||
# 关联话题越多,影响面越大
|
||||
@@ -72,11 +74,11 @@ Day M.1 目标:让 Jarvis 知道「什么对你重要」。
|
||||
|
||||
### Task M.1.4:实现 ImportanceScorer
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/importance_scorer.py`
|
||||
- [x] 新增 `backend/app/services/memory/importance_scorer.py`
|
||||
|
||||
- [ ] 实现 `ImportanceScorer` 类
|
||||
- [x] 实现 `ImportanceScorer` 类
|
||||
|
||||
- [ ] 实现 `calculate_score()` 综合评分方法
|
||||
- [x] 实现 `calculate_score()` 综合评分方法
|
||||
```python
|
||||
def calculate_score(self, memory: UserMemory) -> float:
|
||||
frequency = self.tracker.get_frequency_score(memory) * 0.35
|
||||
@@ -86,15 +88,15 @@ Day M.1 目标:让 Jarvis 知道「什么对你重要」。
|
||||
return frequency + recency + emotion + impact
|
||||
```
|
||||
|
||||
- [ ] 实现 `get_importance_level()` 方法
|
||||
- [x] 实现 `get_importance_level()` 方法
|
||||
|
||||
- [ ] 实现 `should_escalate()` 方法
|
||||
- [x] 实现 `should_escalate()` 方法
|
||||
|
||||
### Task M.1.5:修改 UserMemory 模型
|
||||
|
||||
- [ ] 修改 `backend/app/models/memory.py`
|
||||
- [x] 修改 `backend/app/models/memory.py`
|
||||
|
||||
- [ ] 增加字段:
|
||||
- [x] 增加字段:
|
||||
```python
|
||||
frequency_count: int = 0
|
||||
last_recalled_at: DateTime = None
|
||||
@@ -106,33 +108,33 @@ Day M.1 目标:让 Jarvis 知道「什么对你重要」。
|
||||
|
||||
### Task M.1.6:集成到 MemoryService
|
||||
|
||||
- [ ] 修改 `backend/app/services/memory_service.py`
|
||||
- [x] 修改 `backend/app/services/memory_service.py`
|
||||
|
||||
- [ ] 集成 `ImportanceScorer`
|
||||
- [x] 集成 `ImportanceScorer`
|
||||
|
||||
- [ ] 修改 `add_memory()` 方法计算重要性
|
||||
- [x] 修改 `add_memory()` 方法计算重要性
|
||||
|
||||
- [ ] 修改 `recall_memories()` 方法按重要性排序
|
||||
- [x] 修改 `recall_memories()` 方法按重要性排序
|
||||
|
||||
### Task M.1.7:补测试
|
||||
|
||||
- [ ] 新增 `backend/tests/services/test_importance_scorer.py`
|
||||
- [x] 新增 `backend/tests/services/test_importance_scorer.py`
|
||||
|
||||
- [ ] 测试频率追踪
|
||||
- [x] 测试频率追踪
|
||||
|
||||
- [ ] 测试情绪分析
|
||||
- [x] 测试情绪分析
|
||||
|
||||
- [ ] 测试重要性评分
|
||||
- [x] 测试重要性评分
|
||||
|
||||
- [ ] 测试重要性等级划分
|
||||
- [x] 测试重要性等级划分
|
||||
|
||||
### Day M.1 验收
|
||||
|
||||
- [ ] 频率追踪正常(recall_count 每次 +1)
|
||||
- [ ] 情绪识别准确(「急」「很重要」等能识别)
|
||||
- [ ] 重要性分数正确(高频+情绪 = importance >= 0.8)
|
||||
- [ ] 评分影响排序(高重要性记忆排在前面)
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
- [x] 频率追踪正常(recall_count 每次 +1)
|
||||
- [x] 情绪识别准确(「急」「很重要」等能识别)
|
||||
- [x] 重要性分数正确(高频+情绪 = importance >= 0.8)
|
||||
- [x] 评分影响排序(高重要性记忆排在前面)
|
||||
- [x] 单元测试覆盖率 > 80%
|
||||
|
||||
---
|
||||
|
||||
@@ -350,13 +352,120 @@ Day M.3 目标:让 Jarvis 从「等用户问」变成「主动关心」。
|
||||
|
||||
---
|
||||
|
||||
## Day M.4:对话自动学习(3天)
|
||||
|
||||
Day M.4 目标:让记忆库自动从对话中积累内容,不需要用户手动触发。
|
||||
|
||||
### Task M.4.1:实现 MemoryExtractor
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/memory_extractor.py`
|
||||
|
||||
- [ ] 实现 `MemoryExtractor` 类
|
||||
|
||||
- [ ] 实现 `extract_from_conversation()` 方法
|
||||
```python
|
||||
async def extract_from_conversation(
|
||||
self, user_id: str, messages: list[Message]
|
||||
) -> list[ExtractedMemory]:
|
||||
```
|
||||
|
||||
- [ ] 定义 LLM 提取 Prompt(结构化输出 JSON)
|
||||
- 提取类型:fact / preference / goal / pain_point / event
|
||||
- 只提取明确信息,不猜测
|
||||
|
||||
- [ ] 实现 `deduplicate()` 方法
|
||||
- 相似度 > 0.85 视为重复,调用 `reinforce()` 而非新建
|
||||
|
||||
### Task M.4.2:集成触发点
|
||||
|
||||
- [ ] 修改 `backend/app/routers/conversation.py`
|
||||
- 对话结束端点添加 `background_tasks.add_task(memory_extractor.extract_from_conversation, ...)`
|
||||
|
||||
- [ ] 修改 `backend/app/services/scheduler_service.py`
|
||||
- 添加 30 分钟闲置对话检查任务
|
||||
|
||||
### Task M.4.3:补测试
|
||||
|
||||
- [ ] 新增 `backend/tests/services/test_memory_extractor.py`
|
||||
- [ ] 测试提取准确性(fact/goal/pain_point 识别)
|
||||
- [ ] 测试去重逻辑(重复内容不新建)
|
||||
- [ ] 测试后台触发不阻塞响应
|
||||
|
||||
### Day M.4 验收
|
||||
|
||||
- [ ] 对话结束后 30 秒内自动完成提取
|
||||
- [ ] fact/goal/pain_point 类型识别准确
|
||||
- [ ] 重复内容不新建,只强化原记忆
|
||||
- [ ] 提取为后台任务,不影响响应速度
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
|
||||
---
|
||||
|
||||
## Day M.5:记忆召回注入(2天)
|
||||
|
||||
Day M.5 目标:让 LLM 在生成回答时真正「看到」用户的记忆,实现对话个性化。
|
||||
|
||||
### Task M.5.1:实现 MemoryRecallInjector
|
||||
|
||||
- [ ] 新增 `backend/app/services/memory/recall_injector.py`
|
||||
|
||||
- [ ] 实现 `MemoryRecallInjector` 类
|
||||
|
||||
- [ ] 实现 `build_context()` 方法
|
||||
```python
|
||||
async def build_context(
|
||||
self, user_id: str, current_message: str, token_budget: int = 800
|
||||
) -> str:
|
||||
```
|
||||
|
||||
- [ ] 实现 `_rank()` 方法(语义相关性 × 重要性评分综合排序)
|
||||
|
||||
- [ ] 实现 `_budget_select()` 方法(Token 预算控制)
|
||||
|
||||
- [ ] 实现 `_format()` 方法(格式化为 system prompt 片段)
|
||||
|
||||
- [ ] 记忆类型优先级配置
|
||||
- pain_point > goal > preference > fact > event
|
||||
|
||||
### Task M.5.2:集成到对话路由
|
||||
|
||||
- [ ] 修改 `backend/app/routers/conversation.py`
|
||||
- 发消息时调用 `memory_injector.build_context()`
|
||||
- 将返回的 context 追加到 system prompt
|
||||
- 发送完成后后台触发记忆强化(frequency_count +1)
|
||||
|
||||
- [ ] 修改 `backend/app/services/memory_service.py`
|
||||
- `recall_memories()` 返回时携带相似度分数(`similarity_score` 字段)
|
||||
|
||||
### Task M.5.3:补测试
|
||||
|
||||
- [ ] 新增 `backend/tests/services/test_recall_injector.py`
|
||||
- [ ] 测试 Token 预算不超限
|
||||
- [ ] 测试已归档记忆不注入
|
||||
- [ ] 测试高优先级类型优先注入
|
||||
- [ ] 测试注入耗时 < 100ms
|
||||
|
||||
### Day M.5 验收
|
||||
|
||||
- [ ] LLM 回答中能体现用户个人信息
|
||||
- [ ] 注入内容 ≤ 800 token
|
||||
- [ ] goal/pain_point 比 fact 更早注入
|
||||
- [ ] decay < 0.2 的已归档记忆不出现在 context 中
|
||||
- [ ] 注入耗时 < 100ms
|
||||
- [ ] 被召回的记忆 frequency_count +1
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
|
||||
---
|
||||
|
||||
## 总验收清单
|
||||
|
||||
### Phase M.1-M.3 必须完成
|
||||
### Phase M.1-M.5 必须完成
|
||||
|
||||
- [ ] 重要性评分系统正常工作
|
||||
- [ ] 遗忘曲线系统正常工作
|
||||
- [ ] 主动提醒系统正常工作
|
||||
- [ ] 对话自动学习正常工作(M.4)
|
||||
- [ ] 记忆召回注入正常工作(M.5)
|
||||
- [ ] 单元测试覆盖率 > 80%
|
||||
- [ ] 集成测试通过
|
||||
- [ ] 原有记忆功能无回退
|
||||
@@ -370,7 +479,9 @@ Day M.3 目标:让 Jarvis 从「等用户问」变成「主动关心」。
|
||||
| M.1 重要性评分 | 4 天 |
|
||||
| M.2 遗忘曲线 | 3 天 |
|
||||
| M.3 主动提醒 | 6 天 |
|
||||
| **合计** | **13 天** |
|
||||
| M.4 对话自动学习 | 3 天 |
|
||||
| M.5 记忆召回注入 | 2 天 |
|
||||
| **合计** | **18 天** |
|
||||
|
||||
---
|
||||
|
||||
@@ -388,12 +499,14 @@ Day M.3 目标:让 Jarvis 从「等用户问」变成「主动关心」。
|
||||
| `services/memory/daily_digest.py` | M.3 |
|
||||
| `services/memory/reminder_scheduler.py` | M.3 |
|
||||
| `services/memory/proactive_informer.py` | M.3 |
|
||||
| `services/memory/memory_extractor.py` | M.4 |
|
||||
| `services/memory/recall_injector.py` | M.5 |
|
||||
| `models/memory.py` 更新 | M.1, M.2 |
|
||||
| `models/reminder.py` 新增 | M.3 |
|
||||
| 前端摘要卡片 | M.3 |
|
||||
| 前端提醒 Toast | M.3 |
|
||||
| 单元测试 > 80% | M.1, M.2, M.3 |
|
||||
| 集成测试通过 | M.1, M.2, M.3 |
|
||||
| 单元测试 > 80% | M.1–M.5 |
|
||||
| 集成测试通过 | M.1–M.5 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user