- Backend: FastAPI + SQLAlchemy + Celery (Python 3.11+) - Frontend: Vue 3 + TypeScript + Pinia + Tailwind - Admin Frontend: separate Vue 3 app for management - Docker Compose: 9 services orchestration - Specs: design prototypes, memory system PRD, product roadmap Cleanup performed: - Removed temporary debug scripts from backend root - Removed deprecated admin_app.py (embedded UI) - Removed duplicate docs from admin-frontend - Updated .gitignore for Vite cache and egg-info
456 lines
14 KiB
Markdown
456 lines
14 KiB
Markdown
# 记忆智能系统 PRD
|
||
|
||
## 概述
|
||
|
||
**功能名称**: 记忆智能 (Memory Intelligence)
|
||
**版本**: v1.0
|
||
**优先级**: Phase 2.5 (体验增强后、社区化前)
|
||
**目标用户**: 家长 + 3-8 岁儿童
|
||
|
||
### 核心价值
|
||
|
||
让 DreamWeaver 从"故事生成工具"进化为"懂孩子的故事伙伴":
|
||
- **记住孩子**: 偏好、成长阶段、兴趣变化
|
||
- **延续故事**: 角色、世界观跨故事延续
|
||
- **主动关怀**: 适时推送个性化故事建议
|
||
|
||
---
|
||
|
||
## 一、功能模块
|
||
|
||
### 1.1 孩子档案系统 (Child Profile)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| 基础信息 | 显式 | 姓名、年龄、性别 |
|
||
| 兴趣标签 | 显式+隐式 | 恐龙、公主、太空、动物等 |
|
||
| 成长主题 | 显式 | 当前关注:勇气/分享/独立等 |
|
||
| 阅读偏好 | 隐式 | 故事长度、风格、复杂度 |
|
||
| 互动历史 | 隐式 | 喜欢的故事、跳过的故事 |
|
||
|
||
**数据来源**:
|
||
- 显式: 家长主动填写
|
||
- 隐式: 系统从使用行为中学习
|
||
|
||
### 1.2 故事宇宙记忆 (Story Universe)
|
||
|
||
跨故事保持连续性的元素:
|
||
|
||
| 元素 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| 主角设定 | 孩子的故事化身 | "小明是个爱冒险的男孩" |
|
||
| 常驻角色 | 反复出现的配角 | 魔法猫咪"星星"、智慧老树 |
|
||
| 世界观 | 故事发生的宇宙 | 梦幻森林、星际学院 |
|
||
| 成就系统 | 主角的成长轨迹 | "学会了勇敢"、"交到新朋友" |
|
||
|
||
**记忆结构字段**:
|
||
- `protagonist` / `recurring_characters` / `world_settings` / `achievements`(JSON 结构)
|
||
- “延续上一个故事”默认选最近更新的宇宙(按 `updated_at` 倒序)
|
||
|
||
### 1.3 主动推送系统 (Proactive Push)
|
||
|
||
| 触发类型 | 条件 | 推送内容 |
|
||
|----------|------|----------|
|
||
| 时间触发 | 睡前时段 (19:00-21:00) | "今晚想听什么故事?" |
|
||
| 事件触发 | 节日/生日 | 主题故事推荐 |
|
||
| 行为触发 | 3天未使用 | 召回提醒 |
|
||
| 成长触发 | 年龄变化 | 难度升级建议 |
|
||
|
||
**优先级与抑制**:
|
||
- 优先级:事件 > 成长 > 行为 > 时间
|
||
- 抑制:当天已推送不再触发;静默时段(21:00-09:00)延迟;用户关闭推送则不触发
|
||
|
||
---
|
||
|
||
## 二、用户故事
|
||
|
||
### US-1: 创建孩子档案
|
||
```
|
||
作为家长
|
||
我想要创建孩子的专属档案
|
||
以便系统生成更适合孩子的故事
|
||
```
|
||
|
||
**验收标准**:
|
||
- [ ] 可填写孩子基础信息(姓名、年龄、性别)
|
||
- [ ] 可选择兴趣标签(多选)
|
||
- [ ] 可设置当前成长主题
|
||
- [ ] 支持多个孩子档案切换
|
||
|
||
### US-2: 故事角色延续
|
||
```
|
||
作为家长
|
||
我想要故事中的角色能在新故事中再次出现
|
||
以便孩子感受到故事的连续性
|
||
```
|
||
|
||
**验收标准**:
|
||
- [ ] 生成故事时可选择"延续上一个故事"
|
||
- [ ] 系统自动带入主角设定和常驻角色
|
||
- [ ] 新故事引用之前的"成就"
|
||
|
||
### US-3: 睡前故事提醒
|
||
```
|
||
作为家长
|
||
我想要在睡前时段收到故事推荐
|
||
以便养成固定的亲子阅读习惯
|
||
```
|
||
|
||
**验收标准**:
|
||
- [ ] 可设置提醒时间
|
||
- [ ] 推送包含个性化故事建议
|
||
- [ ] 可一键进入故事生成
|
||
|
||
---
|
||
|
||
## 三、数据模型
|
||
|
||
### 3.1 孩子档案表 (child_profiles)
|
||
|
||
```sql
|
||
CREATE TABLE child_profiles (
|
||
id UUID PRIMARY KEY,
|
||
user_id UUID REFERENCES users(id),
|
||
name VARCHAR(50) NOT NULL,
|
||
birth_date DATE,
|
||
gender VARCHAR(10),
|
||
interests JSONB DEFAULT '[]',
|
||
growth_themes JSONB DEFAULT '[]',
|
||
reading_preferences JSONB DEFAULT '{}',
|
||
created_at TIMESTAMP DEFAULT NOW(),
|
||
updated_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
### 3.2 故事宇宙表 (story_universes)
|
||
|
||
```sql
|
||
CREATE TABLE story_universes (
|
||
id UUID PRIMARY KEY,
|
||
child_profile_id UUID REFERENCES child_profiles(id),
|
||
name VARCHAR(100) NOT NULL,
|
||
protagonist JSONB NOT NULL,
|
||
recurring_characters JSONB DEFAULT '[]',
|
||
world_settings JSONB DEFAULT '{}',
|
||
achievements JSONB DEFAULT '[]',
|
||
created_at TIMESTAMP DEFAULT NOW(),
|
||
updated_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
### 3.3 推送配置表 (push_configs)
|
||
|
||
```sql
|
||
CREATE TABLE push_configs (
|
||
id UUID PRIMARY KEY,
|
||
user_id UUID REFERENCES users(id),
|
||
child_profile_id UUID REFERENCES child_profiles(id),
|
||
push_time TIME,
|
||
push_days INTEGER[], -- 0-6 表示周日到周六
|
||
enabled BOOLEAN DEFAULT true,
|
||
created_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
### 3.4 推送事件表 (push_events)
|
||
|
||
```sql
|
||
CREATE TABLE push_events (
|
||
id UUID PRIMARY KEY,
|
||
user_id UUID NOT NULL,
|
||
child_profile_id UUID NOT NULL,
|
||
trigger_type VARCHAR(20) NOT NULL, -- time/event/behavior/growth
|
||
sent_at TIMESTAMP NOT NULL,
|
||
status VARCHAR(20) NOT NULL, -- sent/failed/suppressed
|
||
reason TEXT
|
||
);
|
||
```
|
||
|
||
### 3.5 记忆条目表 (memory_items)
|
||
|
||
用于存储“可解释、可控”的记忆条目(兴趣偏好、成长主题、常驻角色、关键事件等),并支持时序衰减。
|
||
|
||
```sql
|
||
CREATE TABLE memory_items (
|
||
id UUID PRIMARY KEY,
|
||
child_profile_id UUID NOT NULL,
|
||
universe_id UUID,
|
||
type VARCHAR(50) NOT NULL, -- interest/growth/character/event等
|
||
value JSONB NOT NULL, -- 结构化内容
|
||
base_weight FLOAT DEFAULT 1.0, -- 初始权重
|
||
last_used_at TIMESTAMP, -- 最近使用时间
|
||
created_at TIMESTAMP DEFAULT NOW(),
|
||
ttl_days INTEGER -- 可选:过期天数
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## 四、API 设计
|
||
|
||
### 4.1 孩子档案 API
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/profiles` | 获取当前用户的所有孩子档案 |
|
||
| POST | `/api/profiles` | 创建孩子档案 |
|
||
| GET | `/api/profiles/{id}` | 获取单个档案详情 |
|
||
| PUT | `/api/profiles/{id}` | 更新档案 |
|
||
| DELETE | `/api/profiles/{id}` | 删除档案 |
|
||
|
||
### 4.2 故事宇宙 API
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/profiles/{id}/universes` | 获取孩子的故事宇宙列表 |
|
||
| POST | `/api/profiles/{id}/universes` | 创建新宇宙 |
|
||
| GET | `/api/universes/{id}` | 获取宇宙详情 |
|
||
| PUT | `/api/universes/{id}` | 更新宇宙设定 |
|
||
| POST | `/api/universes/{id}/achievements` | 添加成就 |
|
||
|
||
### 4.3 推送配置 API
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/push-configs` | 获取推送配置 |
|
||
| PUT | `/api/push-configs` | 更新推送配置 |
|
||
|
||
---
|
||
|
||
## 五、Prompt 工程
|
||
|
||
### 5.1 带记忆的故事生成 Prompt
|
||
|
||
```
|
||
你是一个专业的儿童故事作家。请为以下孩子创作一个故事:
|
||
|
||
【孩子档案】
|
||
- 姓名: {child_name}
|
||
- 年龄: {age}岁
|
||
- 兴趣: {interests}
|
||
- 当前成长主题: {growth_theme}
|
||
|
||
【故事宇宙】
|
||
- 主角设定: {protagonist}
|
||
- 常驻角色: {recurring_characters}
|
||
- 世界观: {world_settings}
|
||
- 已获成就: {achievements}
|
||
|
||
【本次创作要求】
|
||
- 关键词: {keywords}
|
||
- 延续之前的故事世界观
|
||
- 让主角在故事中有新的成长
|
||
|
||
请创作一个适合{age}岁儿童的故事,约{word_count}字。
|
||
```
|
||
|
||
### 5.2 成就提取 Prompt
|
||
|
||
```
|
||
请分析以下故事,提取主角获得的成长/成就:
|
||
|
||
【故事内容】
|
||
{story_content}
|
||
|
||
请以JSON格式返回:
|
||
{
|
||
"achievements": [
|
||
{"type": "勇气", "description": "克服了对黑暗的恐惧"},
|
||
{"type": "友谊", "description": "帮助了迷路的小兔子"}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 六、前端设计
|
||
|
||
### 6.1 孩子档案页面
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ 我的宝贝 [+添加] │
|
||
├─────────────────────────────────────┤
|
||
│ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||
│ │ 👦 │ │ 👧 │ │ + │ │
|
||
│ │小明 │ │小红 │ │添加 │ │
|
||
│ │5岁 │ │3岁 │ │ │ │
|
||
│ └─────┘ └─────┘ └─────┘ │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 6.2 档案详情页
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ ← 小明的档案 [编辑] │
|
||
├─────────────────────────────────────┤
|
||
│ 基础信息 │
|
||
│ 姓名: 小明 年龄: 5岁 性别: 男 │
|
||
├─────────────────────────────────────┤
|
||
│ 兴趣爱好 │
|
||
│ [恐龙] [太空] [机器人] │
|
||
├─────────────────────────────────────┤
|
||
│ 成长主题 │
|
||
│ ○ 勇气 ● 分享 ○ 独立 ○ 友谊 │
|
||
├─────────────────────────────────────┤
|
||
│ 故事宇宙 │
|
||
│ ┌─────────────────────────────┐ │
|
||
│ │ 🌟 星际冒险 │ │
|
||
│ │ 主角: 小明船长 │ │
|
||
│ │ 伙伴: 机器人小七、外星猫咪 │ │
|
||
│ │ 成就: 3个 │ │
|
||
│ └─────────────────────────────┘ │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 6.3 故事生成时选择档案
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ 为谁创作故事? │
|
||
├─────────────────────────────────────┤
|
||
│ ● 小明 (5岁) │
|
||
│ ○ 小红 (3岁) │
|
||
│ ○ 不使用档案 │
|
||
├─────────────────────────────────────┤
|
||
│ 选择故事宇宙 │
|
||
│ ● 星际冒险 (延续上次) │
|
||
│ ○ 创建新宇宙 │
|
||
├─────────────────────────────────────┤
|
||
│ [下一步: 输入关键词] │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 七、技术实现要点
|
||
|
||
### 7.1 隐式偏好学习
|
||
|
||
```python
|
||
# 基于用户行为更新偏好
|
||
async def update_implicit_preferences(
|
||
child_id: UUID,
|
||
story: Story,
|
||
interaction: Interaction # 完整阅读/跳过/重复播放
|
||
):
|
||
profile = await get_child_profile(child_id)
|
||
|
||
if interaction == "completed":
|
||
# 增加相关标签权重
|
||
for tag in story.tags:
|
||
profile.reading_preferences[tag] = \
|
||
profile.reading_preferences.get(tag, 0) + 1
|
||
elif interaction == "skipped":
|
||
# 降低相关标签权重
|
||
for tag in story.tags:
|
||
profile.reading_preferences[tag] = \
|
||
profile.reading_preferences.get(tag, 0) - 0.5
|
||
```
|
||
|
||
### 7.2 成就自动提取
|
||
|
||
故事生成完成后,异步调用 LLM 提取成就(以 `type + description` 去重):
|
||
|
||
```python
|
||
@celery.task
|
||
async def extract_achievements(story_id: UUID, universe_id: UUID):
|
||
story = await get_story(story_id)
|
||
universe = await get_universe(universe_id)
|
||
|
||
achievements = await llm.extract_achievements(story.content)
|
||
|
||
universe.achievements.extend(achievements)
|
||
await save_universe(universe)
|
||
```
|
||
|
||
### 7.3 推送调度
|
||
|
||
使用 Celery Beat 定时检查推送:
|
||
|
||
```python
|
||
@celery.task
|
||
def check_push_notifications():
|
||
current_time = datetime.now().time()
|
||
current_day = datetime.now().weekday()
|
||
|
||
configs = PushConfig.query.filter(
|
||
PushConfig.enabled == True,
|
||
PushConfig.push_time <= current_time,
|
||
current_day.in_(PushConfig.push_days)
|
||
).all()
|
||
|
||
for config in configs:
|
||
send_push_notification.delay(config.user_id, config.child_profile_id)
|
||
```
|
||
|
||
**执行约束**:
|
||
- 同一孩子每天最多 1 次推送
|
||
- 推送前查询 `push_events` 去重,成功/抑制均需记录
|
||
|
||
### 7.4 时序衰减与记忆评分
|
||
|
||
**目标**:让“越新的记忆影响越大”,避免旧偏好长期干扰。
|
||
|
||
**默认实现(推荐)**:查询时动态计算分数,不直接修改数据库。
|
||
- 记忆分数:`score = base_weight × decay(Δt)`
|
||
- 衰减示例(分段):0-7 天 1.0,8-30 天 0.7,31-90 天 0.4,90 天后 0.2
|
||
- 读取时按 `score` 排序,选 Top N 进入 Prompt
|
||
|
||
**可选实现**:定期批处理降权
|
||
- 每日/每周批量更新 `base_weight`
|
||
- 适合数据量大、读多写少的场景
|
||
|
||
**RAG 场景的衰减用法**:
|
||
- 语义相似度分数 × 时间衰减
|
||
- 可加时间窗口过滤(如仅取最近 90 天)
|
||
|
||
**删除策略(默认不删)**:
|
||
- 默认只降权,不主动删除
|
||
- 可选:对低权重且 180 天未使用的条目执行 TTL 清理
|
||
|
||
---
|
||
|
||
## 八、里程碑
|
||
|
||
### M1: 孩子档案基础
|
||
- [ ] 数据库模型
|
||
- [ ] CRUD API
|
||
- [ ] 前端档案管理页面
|
||
- [ ] 故事生成时选择档案
|
||
|
||
### M2: 故事宇宙
|
||
- [ ] 宇宙数据模型
|
||
- [ ] Prompt 集成
|
||
- [ ] 成就自动提取
|
||
- [ ] 前端宇宙管理
|
||
|
||
### M3: 主动推送
|
||
- [ ] 推送配置 API
|
||
- [ ] Celery Beat 调度
|
||
- [ ] 推送通知集成 (Web Push / 微信)
|
||
|
||
### M4: 隐式学习
|
||
- [ ] 行为埋点
|
||
- [ ] 偏好学习算法
|
||
- [ ] 推荐优化
|
||
|
||
---
|
||
|
||
## 九、风险与应对
|
||
|
||
| 风险 | 影响 | 应对 |
|
||
|------|------|------|
|
||
| 隐私合规 | 高 | 儿童数据加密存储,家长授权机制 |
|
||
| 推送骚扰 | 中 | 默认关闭,用户主动开启 |
|
||
| 记忆膨胀 | 低 | 定期清理旧数据,限制宇宙数量 |
|
||
|
||
---
|
||
|
||
## 十、相关文档
|
||
|
||
- [孩子档案数据模型](./CHILD-PROFILE-MODEL.md)
|
||
- [故事宇宙记忆结构](./STORY-UNIVERSE-MODEL.md)
|
||
- [主动推送触发规则](./PUSH-TRIGGER-RULES.md)
|