THOUGHT 关联与合并 — 设计文档

版本: v0.1 (设计阶段) 日期: 2026-02-16 状态: 方向已定,待实施


核心洞察

传统思维工具(Notion、Obsidian、思维导图)的逻辑是:用户主动组织 → 形成结构

Kept 应该反过来:用户随口说 → AI 发现结构 → 用户感到惊喜

用户不应该"管理"想法。某天展开一条想法,发现下面安静地躺着几条相关的旧想法——"原来我一直在想这件事"。这就是 aha moment。

设计原则:懂你但不说破。 关联引擎在后台默默工作,用户感受到的是 "Kept 越来越懂我",但说不清为什么。


一、关联引擎(混合方案)

三层关联,任一层命中即建立连接:

第一层:LLM 主题标签(主关联)

在现有 prompt 中扩展 THOUGHT 输出,新增 themes 数组:

{
  "type": "THOUGHT",
  "display_text": "远程办公更高效",
  "content": "...",
  "themes": ["工作方式", "效率"]
}

规则:

为什么这是主关联:

第二层:实体重叠(辅助关联)

从已有的 people 字段 + 从 content 中提取的地点/事物实体:

实现方式: 复用 LLM 已输出的 people 数组,未来可扩展提取 entities。

第三层:语义向量(兜底发现)

使用 Apple 原生 NaturalLanguage 框架的 NLEmbedding

为什么是兜底:

匹配策略

新 THOUGHT 录入 →
  1. 提取 themes,查询已有 THOUGHT 中 themes 有交集的 → 强关联
  2. 查询 people/entities 有重叠的 → 弱关联
  3. 计算 embedding 余弦相似度 ≥ 0.82 的 → 弱关联
  4. 强关联 + 任意弱关联 → 建立连接
  5. 仅弱关联(2条以上弱信号) → 建立连接

二、数据模型变更

Core Data 扩展

MemoryEntity 新增字段:
├── themes: String?           ← JSON: ["工作方式", "效率"](仅 THOUGHT)
├── embedding: Binary?        ← [Float] 序列化,NLEmbedding 128d
├── embeddingModel: String?   ← "NLEmbedding-zh-v1"(标记版本以备升级)
├── linkedMemoryIDs: String?  ← JSON: ["uuid1", "uuid2"](双向关联)
└── threadID: String?         ← 线索标识(同主题 3+ 条时生成)

新增 ThoughtThread 实体(轻量)

ThoughtThread:
├── id: String                ← 唯一标识
├── theme: String             ← 主题名(人类可读)
├── thoughtCount: Int         ← 关联 THOUGHT 数量
├── createdAt: Date
└── lastUpdatedAt: Date

不需要存储 thoughtIDs 列表——通过查询 MemoryEntity.threadID == thread.id 获取。

Prompt 扩展

prompts.js 的 THOUGHT 输出格式中新增:

当类型为 THOUGHT 时,额外输出 themes 字段:
- themes: 1-3 个抽象主题标签(如"职业方向"、"健康生活"、"创意灵感")
- 标签应是概念层面的,不是具体关键词
- 优先使用以下已有标签(如适用): [动态注入]
- 如果没有合适的已有标签,可以创建新的

三、展示方式

设计张力

memory-types-theory.md 的原则:

"理解体现在行为精准度上,不体现在表达上。懂你但不说破。" 永远不做:"你的本周思考总结"、"基于你的记忆模式,我们发现..."

但完全隐形会浪费关联的价值。 调和方式:

用户主动发现 = 可以展示。AI 主动告知 = 要极度克制。

A. 涟漪式(卡片内关联,MVP 首发)

触发: 用户展开一条 THOUGHT 卡片

展示: 在 content 下方,出现一个安静的关联区域:

┌─────────────────────────────────────┐
│ 💭 远程办公其实更适合我               │
│                                     │
│  [展开后的 content 整理文字...]       │
│                                     │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─        │
│  💭 周二想到的                        │
│  "在家工作效率确实高很多"              │
│                                     │
│  💭 上周四想到的                      │
│  "要不要跟老板提每周两天远程"          │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─        │
└─────────────────────────────────────┘

设计细节:

颜色: 关联区域用 KeptTheme.text.opacity(0.3) —— 比已经很淡的 THOUGHT 色更淡,像纸上的铅笔素描

动画: 涟漪区域跟随 content 一起展开,使用相同的 spring 动画,但 delay 0.1s —— 像水波一样稍后到达

B. 线索(主页安静区域,3+ 条触发)

触发条件: 某个主题的 THOUGHT 数量 ≥ 3

位置: 主页 surfaced 区域和 earlier 区域之间,或者 surfaced 上方

┌─────────────────────────────────────┐
│  你在想的事                          │
│                                     │
│  ┌───────────┐  ┌───────────┐      │
│  │ 工作方式   │  │ 饮食探索   │      │
│  │ 4 条想法   │  │ 3 条想法   │      │
│  │ 最近: 今天  │  │ 最近: 昨天  │      │
│  └───────────┘  └───────────┘      │
│                                     │
│  ── 记忆 ──                          │
│  [正常的记忆卡片列表...]              │
└─────────────────────────────────────┘

设计细节:

线索详情视图(新页面):

┌─────────────────────────────────────┐
│  ← 返回          工作方式            │
│                                     │
│  ○ 今天                              │
│  │ "远程办公其实更适合我"             │
│  │  整理后的内容...                   │
│  │                                   │
│  ○ 3 天前                            │
│  │ "在家工作效率确实高很多"           │
│  │  整理后的内容...                   │
│  │                                   │
│  ○ 上周四                            │
│  │ "要不要跟老板提每周两天远程"       │
│  │  整理后的内容...                   │
│  │                                   │
│  ● 12 天前(最早)                    │
│    "公司新的考勤制度太死板了"         │
│    整理后的内容...                    │
└─────────────────────────────────────┘

四、触发时机

时机 1:录入时关联提示

场景: 用户刚说完一条新 THOUGHT,AI 处理后发现有关联

当前 Toast: "✓ 记住了"

增强 Toast(有关联时): "✓ 记住了,这是你第 3 次想到这件事"

设计细节:

实现:processMemory() 后执行关联匹配,如果命中,修改 Toast 文案

时机 2:线索形成通知(临界点)

场景: 某个主题累积到 3 条 THOUGHT → 推一条本地通知

通知文案: "你最近经常想到「{主题名}」的事"

设计细节:

不做的触发(需要信任门槛,留给未来)

触发方式 不做的原因 未来条件
周回顾通知 像"AI 在定期分析你" 用户主动开启
跨类型关联 ACTION+THOUGHT 关联太主动 种子用户验证后
想法→行动建议 "要不要变成行动"太指导性 人格系统 v1 之后
想法成熟度分析 明显的 AI 分析感 深度信任建立后

原则:触发的边界由信任决定。 目前只做用户主动发现(涟漪)和最克制的被动提示(录入时 + 临界点通知各一次)。随着用户对 Kept 的信任加深,逐步开放更多触发。


五、实施路线

Phase 1(1 周):关联引擎 + 涟漪

端侧:
  - Core Data 新增 themes, embedding, linkedMemoryIDs, threadID 字段
  - NLEmbedding 封装:生成 + 余弦相似度计算
  - 关联匹配服务:新 THOUGHT 保存后触发,匹配已有 THOUGHT
  - MemoryCard 展开区域新增涟漪关联展示
  - Toast 增强:"记住了,这是你第 N 次想到这件事"

云端:
  - prompts.js 新增 themes 输出要求
  - 版本号 → v2.6

Phase 2(1 周):线索

端侧:
  - ThoughtThread Core Data 实体
  - 线索自动生成逻辑(3+ 同主题)
  - 主页"你在想的事"横向滚动区域
  - 线索详情时间线视图(新页面)
  - 线索形成时推送本地通知

Phase 3(未来):深度关联

  - 跨类型关联(THOUGHT ↔ ACTION/INTENT)
  - 线索合并(用户手动或 AI 建议)
  - 周回顾(用户主动开启)
  - 想法 → 行动转化建议

六、设计检验清单

每个实现细节都要过这些检验: