148 lines
5.0 KiB
Markdown
148 lines
5.0 KiB
Markdown
# 记忆系统开发指南 (Development Guide)
|
||
|
||
本文档详细说明了 PRD 中定义的记忆系统的技术实现细节。
|
||
|
||
## 1. 数据库架构变更 (Schema Changes)
|
||
|
||
目前的 `MemoryItem` 表结构尚可,但需要增强字段以支持丰富的情感和元数据。
|
||
|
||
### 1.1 `MemoryItem` 表优化
|
||
建议使用 Alembic 进行迁移,增加以下字段或在 `value` JSON 中规范化以下结构:
|
||
|
||
```python
|
||
# 建议在 models.py 中明确这些字段,或者严格定义 value 字段的 Schema
|
||
class MemoryItem(Base):
|
||
# ... 现有字段 ...
|
||
|
||
# 新增/规范化字段建议
|
||
# value 字段的 JSON 结构规范:
|
||
# {
|
||
# "content": "小兔子战胜了大灰狼", # 记忆的核心文本
|
||
# "keywords": ["勇敢", "森林"], # 用于检索的关键词
|
||
# "emotion": "positive", # 情感倾向: positive/negative/neutral
|
||
# "source_story_id": 123, # 来源故事 ID
|
||
# "confidence": 0.85 # 记忆置信度 (如果是 AI 自动提取)
|
||
# }
|
||
```
|
||
|
||
### 1.2 `StoryUniverse` 表优化 (成就系统)
|
||
目前的成就存储在 `achievements` JSON 字段中。为了支持更复杂的查询(如"获得勇气勋章的所有用户"),建议将其重构为独立关联表,或保持 JSON 但规范化结构。
|
||
|
||
**当前 JSON 结构规范**:
|
||
```json
|
||
[
|
||
{
|
||
"id": "badge_courage_01",
|
||
"type": "勇气",
|
||
"name": "小小勇士",
|
||
"description": "第一次在故事中独自面对困难",
|
||
"icon_url": "badges/courage.png",
|
||
"obtained_at": "2023-10-27T10:00:00Z",
|
||
"source_story_id": 45
|
||
}
|
||
]
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 核心逻辑实现
|
||
|
||
### 2.1 记忆注入逻辑 (Prompt Engineering)
|
||
|
||
修改 `backend/app/api/stories.py` 中的 `_build_memory_context` 函数。
|
||
|
||
**目标**: 生成一段自然的、不仅是罗列数据的 Prompt。
|
||
|
||
**伪代码逻辑**:
|
||
```python
|
||
def format_memory_for_prompt(memories: list[MemoryItem]) -> str:
|
||
"""
|
||
将记忆项转换为自然语言 Prompt 片段。
|
||
"""
|
||
context_parts = []
|
||
|
||
# 1. 角色记忆
|
||
chars = [m for m in memories if m.type == 'favorite_character']
|
||
if chars:
|
||
names = ", ".join([c.value['name'] for c in chars])
|
||
context_parts.append(f"孩子特别喜欢的角色有:{names}。请尝试让他们客串出场。")
|
||
|
||
# 2. 近期情节
|
||
recent_stories = [m for m in memories if m.type == 'recent_story'][:2]
|
||
if recent_stories:
|
||
for story in recent_stories:
|
||
context_parts.append(f"最近发生过:{story.value['summary']}。可以在对话中不经意地提及此事。")
|
||
|
||
# 3. 避雷区 (负面记忆)
|
||
scary = [m for m in memories if m.type == 'scary_element']
|
||
if scary:
|
||
items = ", ".join([s.value['keyword'] for s in scary])
|
||
context_parts.append(f"【绝对禁止】不要出现以下让孩子害怕的元素:{items}。")
|
||
|
||
return "\n".join(context_parts)
|
||
```
|
||
|
||
### 2.2 成就提取与通知流程
|
||
|
||
当前流程在 `app/tasks/achievements.py`。需要完善闭环。
|
||
|
||
**改进后的流程**:
|
||
1. **Story Generation**: 故事生成成功,存入数据库。
|
||
2. **Async Task**: 触发 Celery 任务 `extract_story_achievements`。
|
||
3. **LLM Analysis**: 调用 Gemini 分析故事,提取成就。
|
||
4. **Update DB**: 更新 `StoryUniverse.achievements`。
|
||
5. **Notification (新增)**:
|
||
* 创建一个 `Notification` 或 `UserMessage` 记录(需要新建表或使用 Redis Pub/Sub)。
|
||
* 前端轮询或通过 SSE (Server-Sent Events) 接收通知:"🎉 恭喜!在这个故事里,小明获得了[诚实勋章]!"
|
||
|
||
### 2.3 记忆清理与衰减 (Maintenance)
|
||
|
||
需要一个后台定时任务(Cron Job),清理无效记忆,避免 Prompt 过长。
|
||
|
||
* **频率**: 每天一次。
|
||
* **逻辑**:
|
||
* 删除 `ttl_days` 已过期的记录。
|
||
* 对 `recent_story` 类型的 `base_weight` 进行每日衰减 update(或者只在读取时计算,数据库存静态值,推荐读取时动态计算以减少写操作)。
|
||
* 当 `MemoryItem` 总数超过 100 条时,触发"记忆总结"任务,将多条旧记忆合并为一条"长期印象" (Long-term Impression)。
|
||
|
||
---
|
||
|
||
## 3. API 接口规划
|
||
|
||
### 3.1 获取成长时间轴
|
||
`GET /api/profiles/{id}/timeline`
|
||
|
||
**Response**:
|
||
```json
|
||
{
|
||
"events": [
|
||
{
|
||
"date": "2023-10-01",
|
||
"type": "milestone",
|
||
"title": "初次相遇",
|
||
"description": "创建了角色 [小明]"
|
||
},
|
||
{
|
||
"date": "2023-10-05",
|
||
"type": "story",
|
||
"title": "小明与魔法树",
|
||
"image_url": "..."
|
||
},
|
||
{
|
||
"date": "2023-10-05",
|
||
"type": "achievement",
|
||
"badge": {
|
||
"name": "好奇宝宝",
|
||
"icon": "..."
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 3.2 记忆反馈 (人工干预)
|
||
`POST /api/memories/{id}/feedback`
|
||
|
||
允许家长手动删除或修正错误的记忆。
|
||
* **Action**: `delete` | `reinforce` (强化,增加权重)
|