版本 0.10 数据模型设计
生成时间:2026-01-12 14:30:00
最后更新:2026-01-12 (Memory 系统重设计)
YOLOX 技术方案:数据模型设计 (V0.10)
本方案基于 React Native + Golang (Eino) + PostgreSQL/Supabase + Milvus 架构,针对用户冷启动、动态 Prompt 组装、Memory 系统及知识库需求进行数据建模。
数据归属说明
由于 Memory 系统的复杂性,数据模型按服务边界划分:
| 服务 | 管理的数据 | 说明 |
|---|---|---|
| yolox-server (Backend) | users, conversations, messages, topics 等 | 用户基础数据、会话管理 |
| yolox-rag (RAG) | user_profiles, memory_items, conversation_summaries 等 | Memory 存储与检索 |
Backend 通过 RPC/HTTP 调用 RAG 服务获取 Memory 数据,不直接读写 Memory 相关表。
1. Backend 数据表设计 (yolox-server)
users (用户基础表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 用户唯一标识 | PRIMARY KEY, DEFAULT gen_random_uuid() |
| phone_number | VARCHAR(20) | 手机号(用于登录) | NOT NULL, UNIQUE, INDEX |
| nickname | VARCHAR(64) | 用户昵称 | NOT NULL |
| avatar_url | TEXT | 头像存储地址 (R2) | - |
| created_at | TIMESTAMPTZ | 注册时间 | NOT NULL, DEFAULT NOW() |
| last_login | TIMESTAMPTZ | 最后登录时间 | - |
| is_onboarded | BOOLEAN | 是否完成冷启动问卷 | NOT NULL, DEFAULT FALSE |
onboarding_surveys (问卷配置表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 问卷 ID | PRIMARY KEY |
| title | VARCHAR(255) | 问卷标题 | NOT NULL |
| questions | JSONB | 题目列表 (含题干、选项、单多选类型) | NOT NULL |
| is_active | BOOLEAN | 是否启用 | DEFAULT TRUE |
| version | INTEGER | 版本号 | NOT NULL |
user_onboarding_responses (用户问卷结果表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 记录 ID | PRIMARY KEY |
| user_id | UUID | 用户 ID | FOREIGN KEY users.id |
| survey_id | UUID | 问卷 ID | FOREIGN KEY onboarding_surveys.id |
| answers | JSONB | 用户回答内容 (选项 ID 列表) | NOT NULL |
| created_at | TIMESTAMPTZ | 提交时间 | DEFAULT NOW() |
topics (话题配置表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 话题 ID | PRIMARY KEY |
| title | VARCHAR(128) | 话题标题 | NOT NULL |
| cover_image | TEXT | 话题封面图 (R2) | - |
| button_text | VARCHAR(32) | 按钮文案 | DEFAULT '开始对话' |
| priority | INTEGER | 权重级别 (用于 Banner 展示) | DEFAULT 0 |
| category | VARCHAR(64) | 话题分类 (关系/健康/人生) | INDEX |
| system_prompt_template | TEXT | 该话题的基础 System Prompt | NOT NULL |
| is_recommended | BOOLEAN | 是否作为冷启动推荐候选 | DEFAULT FALSE |
conversations (会话管理表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 会话 ID | PRIMARY KEY |
| user_id | UUID | 用户 ID | FOREIGN KEY users.id, INDEX |
| topic_id | UUID | 关联话题 ID | FOREIGN KEY topics.id |
| title | VARCHAR(255) | 会话标题 (AI 自动生成或手动修改) | - |
| is_starred | BOOLEAN | 是否收藏 | DEFAULT FALSE |
| status | VARCHAR(20) | 状态 (active/archived) | DEFAULT 'active' |
| created_at | TIMESTAMPTZ | 创建时间 | INDEX |
| updated_at | TIMESTAMPTZ | 最后活跃时间 | INDEX |
messages (对话消息表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 消息 ID | PRIMARY KEY |
| conversation_id | UUID | 会话 ID | FOREIGN KEY conversations.id, INDEX |
| role | VARCHAR(20) | 角色 (user/assistant/system) | NOT NULL |
| content | TEXT | 文本内容 | NOT NULL |
| audio_url | TEXT | 语音文件地址 (R2) | - |
| message_type | VARCHAR(20) | 类型 (text/voice/insight) | DEFAULT 'text' |
| metadata | JSONB | 扩展信息 (ASR 原始结果/Token 消耗等) | - |
| created_at | TIMESTAMPTZ | 发送时间 | DEFAULT NOW() |
insights (对话总结/Artifacts 表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | Insight ID | PRIMARY KEY |
| conversation_id | UUID | 会话 ID | FOREIGN KEY conversations.id |
| content | TEXT | 总结内容 (Markdown) | NOT NULL |
| user_feedback | INTEGER | 用户反馈 (1:有用, -1:无用, 0:未评价) | DEFAULT 0 |
| created_at | TIMESTAMPTZ | 生成时间 | DEFAULT NOW() |
verification_codes (验证码表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 验证码记录 ID | PRIMARY KEY |
| phone_number | VARCHAR(20) | 手机号 | NOT NULL, INDEX |
| code | VARCHAR(6) | 验证码(6位数字) | NOT NULL |
| expires_at | TIMESTAMPTZ | 过期时间(通常5-10分钟) | NOT NULL |
| is_used | BOOLEAN | 是否已使用 | NOT NULL, DEFAULT FALSE |
| created_at | TIMESTAMPTZ | 创建时间 | NOT NULL, DEFAULT NOW() |
invitation_codes (邀请码表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 邀请码 ID | PRIMARY KEY |
| code | VARCHAR(32) | 邀请码(唯一标识) | NOT NULL, UNIQUE, INDEX |
| created_by | UUID | 创建者用户 ID(管理员) | FOREIGN KEY users.id |
| expires_at | TIMESTAMPTZ | 过期时间(1个月有效期) | NOT NULL |
| is_used | BOOLEAN | 是否已使用 | NOT NULL, DEFAULT FALSE |
| used_by | UUID | 使用该邀请码的用户 ID | FOREIGN KEY users.id |
| used_at | TIMESTAMPTZ | 使用时间 | - |
| created_at | TIMESTAMPTZ | 创建时间 | NOT NULL, DEFAULT NOW() |
2. RAG Memory 数据表设计 (yolox-rag)
Memory 系统采用分层存储架构,将用户记忆拆分为细粒度的可检索单元
2.1 Memory 分层模型
┌─────────────────────────────────────────────────────────────────────┐
│ User Memory Architecture │
├─────────────────────────────────────────────────────────── ──────────┤
│ Layer 1: User Profile (用户画像) │
│ • 基础信息、沟通风格、性格特征、核心困扰 │
│ • 更新频率:低,仅在新信息出现时更新 │
├─────────────────────────────────────────────────────────────────────┤
│ Layer 2: Memory Items (记忆条目) │
│ • 事实记忆、事件记忆、情绪记忆、偏好记忆等 │
│ • 更新频率:中高,每次对话可能提取多条 │
│ • 支持向量检索 + 时间衰减 │
├─────────────────────────────────────────────────────────────────────┤
│ Layer 3: Conversation Summaries (对话摘要) │
│ • 每次对话的结构化摘要 │
│ • 关联到具体的 conversation_id │
├─────────────────────────────────────────────────────────────────────┤
│ Layer 4: Information Boundaries (信息边界) │
│ • 标记哪些信息已知,避免重复提问 │
└─────────────────────────────────────────────────────────────────────┘
2.2 user_profiles (用户画像表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| user_id | UUID | 用户 ID | PRIMARY KEY |
| basic_info | JSONB | 基础信息 | NOT NULL, DEFAULT '' |
| communication_style | JSONB | 沟通风格 | NOT NULL, DEFAULT '' |
| personality | JSONB | 性格特征 | NOT NULL, DEFAULT '' |
| core_concerns | TEXT[] | 核心困扰标签列表 | NOT NULL, DEFAULT '' |
| updated_at | TIMESTAMPTZ | 最后更新时间 | DEFAULT NOW() |
| version | INTEGER | 版本号(乐观锁) | DEFAULT 1 |
字段说明:
// basic_info 示例
{
"age": 28,
"gender": "female",
"occupation": "产品经理",
"location": "北京"
}
// communication_style 示例
{
"expression": "细腻", // 表达方式
"emotion": "敏感", // 情绪特点
"language": "偏文艺" // 语言风格
}
// personality 示例
{
"mbti": "INFJ",
"traits": ["内向", "共情力强", "追求完美"]
}
// core_concerns 示例
["异地恋问题", "职业倦怠", "原生家庭"]
2.3 memory_items (记忆条目表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 记忆 ID | PRIMARY KEY, DEFAULT gen_random_uuid() |
| user_id | UUID | 用户 ID | NOT NULL, INDEX |
| memory_type | VARCHAR(32) | 记忆类型 | NOT NULL, INDEX |
| category | VARCHAR(64) | 分类标签 | INDEX |
| content | TEXT | 记忆内容(自然语言) | NOT NULL |
| structured_data | JSONB | 结构化数据(可选) | DEFAULT '' |
| source_conversation_id | UUID | 来源会话 ID | - |
| source_message_ids | UUID[] | 来源消息 ID 列表 | DEFAULT '' |
| confidence | FLOAT | 置信度 (0-1) | DEFAULT 0.8 |
| importance | INTEGER | 重要度 (1-5) | DEFAULT 3 |
| is_verified | BOOLEAN | 是否经用户确认 | DEFAULT FALSE |
| is_deleted | BOOLEAN | 是否软删除 | DEFAULT FALSE |
| superseded_by | UUID | 被哪条记忆取代 | - |
| expires_at | TIMESTAMPTZ | 过期时间(临 时性记忆) | - |
| created_at | TIMESTAMPTZ | 创建时间 | DEFAULT NOW(), INDEX |
| updated_at | TIMESTAMPTZ | 更新时间 | DEFAULT NOW() |
memory_type 枚举值:
| 类型 | 说明 | 示例 |
|---|---|---|
fact | 事实记忆 | "和男友异地恋3年" |
event | 事件记忆 | "昨天因为视频通话吵架了" |
emotion | 情绪记忆 | "对这段关系感到疲惫" |
preference | 偏好记忆 | "喜欢在晚上聊天" |
goal | 目标记忆 | "想要改善沟通模式" |
progress | 进展记忆 | "开始尝试每天视频通话" |
category 枚举值:
| 分类 | 说明 |
|---|---|
relationship | 亲密关系 |
health | 身心健康 |
career | 职业发展 |
family | 家庭关系 |
finance | 财务相关 |
general | 通用/其他 |
2.4 conversation_summaries (对话摘要表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 摘要 ID | PRIMARY KEY, DEFAULT gen_random_uuid() |
| conversation_id | UUID | 会话 ID | NOT NULL, UNIQUE |
| user_id | UUID | 用户 ID | NOT NULL, INDEX |
| summary | TEXT | 对话摘要(200-500字) | NOT NULL |
| key_points | TEXT[] | 关键要点列表 | DEFAULT '' |
| extracted_memory_ids | UUID[] | 提取的记忆 ID 列表 | DEFAULT '' |
| topic_tags | VARCHAR(64)[] | 话题标签 | DEFAULT '' |
| emotional_tone | VARCHAR(32) | 整体情绪基调 | - |
| created_at | TIMESTAMPTZ | 创建时间 | DEFAULT NOW() |
2.5 information_boundaries (信息边界表)
| 字段名 | 类型 | 说明 | 约束 |
|---|---|---|---|
| id | UUID | 记录 ID | PRIMARY KEY, DEFAULT gen_random_uuid() |
| user_id | UUID | 用户 ID | NOT NULL, INDEX |
| question_type | VARCHAR(64) | 问题类型 | NOT NULL |
| is_known | BOOLEAN | 是否已知 | DEFAULT TRUE |
| source_memory_id | UUID | 对应记忆条目 ID | - |
| last_asked_at | TIMESTAMPTZ | 最后询问时间 | - |
| created_at | TIMESTAMPTZ | 创建时间 | DEFAULT NOW() |
question_type 常见值:
age- 年龄occupation- 职业location- 所在地relationship_status- 关系状态partner_info- 伴侣信息health_condition- 健康状况family_situation- 家庭情况
UNIQUE 约束: (user_id, question_type)
3. 向量数据库设计 (Milvus)
3.1 knowledge_base (知识库 - Module 2)
| 字段名 | 类型 | 说明 | 备注 |
|---|---|---|---|
| pk | Int64 | 主键 ID | 自动增长 |
| vector | FloatVector(1536) | 知识片段向量 | text-embedding-3-small |
| content | String | 知识文本内容 | 原始文本 |
| topic_category | String | 话题分类标签 | 用于 Pre-filtering |
| knowledge_type | String | 知识类型 | expert/case/skill |
| source_ref | String | 来源引用 | 书名/链接/脚本库 ID |
3.2 memory_vectors (用户记忆向量 - Module 1)
| 字段名 | 类型 | 说明 | 备注 |
|---|---|---|---|
| pk | Int64 | 主键 ID | 自动增长 |
| memory_id | String | 关联 memory_items.id | 用于回查 PostgreSQL |
| user_id | String | 用户 ID | 用于过滤 |
| vector | FloatVector(1536) | 记忆内容向量 | text-embedding-3-small |
| memory_type | String | 记忆类型 | 用于过滤 |
| category | String | 分类标签 | 用于过滤 |
| importance | Int32 | 重要度 | 用于排序/过滤 |
| created_at | Int64 | 创建时间戳 | 用于时间衰减计算 |
索引配置:
index_params = {
"index_type": "IVF_FLAT", # 或 HNSW
"metric_type": "IP", # Inner Product
"params": {"nlist": 128}
}
4. 关系与索引说明
4.1 服务间数据关系
┌─────────────────────────────────────────────────────────────────────┐
│ Backend (yolox-server) │
│ ┌─────────┐ ┌───────────────┐ ┌──────────┐ │
│ │ users │───▶│ conversations │───▶│ messages │ │
│ └────┬────┘ └───────────────┘ └──────────┘ │
│ │ │ │
└───────┼─────────────────┼───────────────────────────────────── ──────┘
│ user_id │ conversation_id
▼ ▼
┌───────────────────────────────────────────────────────────────────┐
│ RAG (yolox-rag) │
│ ┌───────────────┐ ┌──────────────┐ ┌────────────────────────┐ │
│ │ user_profiles │ │ memory_items │ │ conversation_summaries │ │
│ └───────────────┘ └──────────────┘ └────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │memory_vectors │ (Milvus) │
│ └───────────────┘ │
└───────────────────────────────────────────────────────────────────┘
4.2 Backend 核心索引
| 表 | 索引 | 用途 |
|---|---|---|
| users | (phone_number) | 手机号登录快速查询 |
| conversations | (user_id, is_starred, updated_at DESC) | 侧边栏历史列表 |
| messages | (conversation_id, created_at ASC) | 对话消息流加载 |
| verification_codes | (phone_number, expires_at, is_used) | 验证码查询 |
| invitation_codes | (code, is_used, expires_at) | 邀请码验证 |
4.3 RAG Memory 核心索引
| 表 | 索引 | 用途 |
|---|---|---|
| memory_items | (user_id, memory_type) WHERE NOT is_deleted | 按类型查询记忆 |
| memory_items | (user_id, category) WHERE NOT is_deleted | 按分类查询记忆 |
| memory_items | (user_id, created_at DESC) WHERE NOT is_deleted | 时间排序 |
| memory_items | (user_id, importance DESC) WHERE NOT is_deleted | 重要度排序 |
| conversation_summaries | (user_id, created_at DESC) | 最近对话摘要 |
| information_boundaries | (user_id, question_type) UNIQUE | 信息边界查询 |
5. Memory 检索策略
5.1 混合检索算法
在 Prompt 组装时,RAG 服务使用以下策略检索相关记忆:
最终分数 = 向量相似度 × 时间衰减权重 × (重要度/5) × 话题相关性加权
其中:
- 时间衰减:decay = 0.5 ^ (age_days / 30),半衰期 30 天
- 话题加权:当前话题相关的记忆 × 1.3
5.2 Context Window 预算分配
Module 1 总预算约 3000 tokens:
| 组成部分 | Token 预算 | 策略 |
|---|---|---|
| User Profile | ~500 | 固定加载 |
| Memory Items (Top 5-10) | ~1000 | 向量检索 + 排序 |
| Recent Events (Top 3) | ~600 | 按时间筛选 |
| Last Conversation Summary | ~500 | 固定加载 |
| Information Boundaries | ~400 | 固定加载 |
6. 基础设施关联
| 基础设施 | 用途 |
|---|---|
| PostgreSQL (Backend) | 存储用户信息、会话、消息、话题配置等 |
| PostgreSQL (RAG) | 存储 Memory 结构化数据(user_profiles, memory_items 等) |
| Milvus | 存储知识库向量 (knowledge_base) 和记忆向量 (memory_vectors) |
| Cloudflare R2 | 存储头像、话题封面、语音文件等二进制资源 |
| 消息队 列 | Backend 触发 RAG 异步提取记忆任务 |
7. 废弃说明
user_memories (已废弃)
原设计将所有用户记忆存储在单表的三个字段中:
persona(JSONB)history_summary(TEXT)information_boundary(JSONB)
废弃原因:
history_summary为全量文本,无法增量更新- 无法按语义检索相关记忆
- 无时间衰减机制
- 无法溯源到具体对话
迁移方案:数据拆分写入新的 user_profiles、memory_items、information_boundaries 表。