Tommy

从 Claude Code 到小暖:两类 AI 的记忆哲学之辨

From Claude Code to Xiaonuan — Two Memory Philosophies for Two Kinds of AI

· 20 min read
···阅读reads

关于”为什么 Claude Code 不用 RAG”,以及陪伴型 AI 该怎么”记住”一个人

引子:一个被忽略的反常识

2026 年 1 月,Anthropic 的 Claude Code 团队负责人 Boris Cherny 在 Hacker News 上写下一段话,被转发了上百万次:

“Claude Code 早期版本用过 RAG + 本地向量数据库,但我们很快发现 agentic search 在大多数情况下都更好。”

在一个”言必称 RAG”的时代,这句话像是从行业主流路线上划下了一道斜线。要知道,在过去三年里,几乎所有”让大模型记住你的代码库”的方案,都建立在同一套技术栈之上:分块(chunking)、向量化(embedding)、向量数据库(vector DB)、语义检索(semantic search)。这是教科书式的标准答案。

而 Claude Code——这个被认为是 2026 年最强的 AI 编程助手——选择了一条更”原始”的路:它不建索引,不做向量化,靠 grepglobfindRead 这些 Unix 老兵般的命令行工具,像一个真正的程序员那样,一行一行地探索代码库。

这不是技术上的”退步”,恰恰是 Anthropic 在大量内部 benchmark 之后做出的工程决策。一位 Anthropic 工程师在那条帖子下补充道:“In our testing we found that agentic search outperformed [RAG] by a lot, and this was surprising.”(“在我们的测试中,agentic search 大幅超过了 RAG,这令我们自己也很意外。”)

这件事值得深思的原因,不在于”RAG 是否过时”——那是一个被反复炒作的伪命题——而在于:它逼着我们去重新审视 “AI 记忆”这件事究竟该怎么做。Claude Code 处理的是代码库,那是一个高度结构化、有精确语义、有明确边界的世界。而我们正在构建的小暖,是一个面对老人的语音陪伴系统——它要记住的不是函数签名,而是张阿姨上周提过的孙子叫什么、李大爷昨天血压高了三天没说话、王奶奶最近开始反复讲同一个故事。

两类 AI,两种记忆哲学。Claude Code 的方案能否被小暖借用?还是说,小暖必须走一条完全不同的路?

这篇文章试图把这个问题讲清楚。我们会从 Claude Code 不用 RAG 的真正原因谈起,剖析它的四层记忆架构,然后转向小暖这类陪伴 AI 的记忆管理范式(mem0、Letta、知识图谱、自管理记忆),最后回答一个核心问题:对于”治未病 + 老人陪伴”这样一个高情感密度、低数据规模、长时间跨度的场景,最合理的记忆架构应该长什么样?

第一部分:Claude Code 为什么不用 RAG

1.1 先把”RAG”这个词说清楚

讨论这个问题之前,必须先消除歧义。“RAG”在不同语境下含义不同:

Claude Code 抛弃的是狭义 RAG,而不是”检索增强”这个理念本身。Boris 的原话也只是说不用 vector DB,并不是说不检索。换句话说,他们抛弃的是特定的实现方式,保留了信息检索的核心思想

这个区分很重要,因为接下来我们会看到:小暖也需要某种形式的”检索增强”,但它具体应该长什么样,恰恰是这篇文章要讨论的核心。

Claude Code 在面对一个陌生代码库时,做的事情和一个有经验的工程师几乎一样:

Turn 1: glob "**/*auth*"              → 找到 5 个相关文件
Turn 2: grep "login" auth/            → 找到 12 处匹配
Turn 3: Read auth/login.ts            → 读取完整内容
Turn 4: grep "validateToken" --next   → 顺着 import 链追踪
Turn 5: Read auth/token.ts            → 读取依赖文件
...

每一步都是 LLM 自己主动发起的工具调用:它先看目录结构,再用关键字搜索,读相关文件,跟踪引用关系,必要时回溯重搜。整个过程是可观察的、可解释的、可追溯的

这套机制有四个关键特征:

  1. 零预处理:不需要事先建索引、训练 embedding、维护向量库。
  2. 始终新鲜:直接读文件系统,永远不会出现”索引和代码不一致”的问题。
  3. 精确匹配createD1HttpClient 这个函数名要么在文件里,要么不在——没有”语义模糊正例”。
  4. 本地隔离:代码不会被发送到外部 embedding 服务,对企业用户是巨大的合规优势。

1.3 为什么 RAG 在代码场景下输了

要理解 Claude Code 的选择,需要理解 RAG 在代码场景下的”四个软肋”:

软肋一:精度问题

Embedding 的本质是把文本压缩成几百维的稠密向量,然后用余弦相似度找”语义相近”的内容。这在写散文、找文档、聊天记录场景下是优势,但在代码场景下是灾难。代码里的 userAuthauthUser 在 embedding 空间里可能非常接近,但它们是完全不同的两个东西。一个搞错就是 bug。

软肋二:陈旧性问题(staleness)

代码每天都在变。如果你建了索引,那索引就要不断重建;如果不重建,索引就会和实际代码漂移。在一个团队同时修改的活跃代码库里,“昨晚的 embedding 索引”很可能已经过时几百次了。这是一个工程上的无底洞。

软肋三:基础设施复杂度

要做好 RAG,你需要:embedding 服务、向量数据库、索引重建守护进程、查询接口、监控系统、权限隔离。每一层都是新的故障点。而 agentic search 用的是操作系统自带的 grep 和文件系统——稳定、零依赖、零运维。

软肋四:隐私和安全

把代码发到云端 embedding 服务做向量化,这件事对很多企业(尤其是金融、医疗、国防)是不可接受的。本地跑 embedding 模型可以解决一部分问题,但又会带来 GPU 资源、模型管理、性能瓶颈等新问题。agentic search 天然 local-first,数据从不离开机器。

1.4 还有一个更深的原因:“苦涩的教训”对齐

Rich Sutton 那篇著名的 The Bitter Lesson 说过:长期来看,依赖算力和搜索的通用方法,总会击败依赖人类先验知识构建的精巧方法。

RAG 的本质,是用”人类设计的检索流程”去弥补”模型能力不足”。它假设模型搞不定大上下文,所以提前帮它”挑好”该看什么。但 2026 年的现实是:模型的上下文窗口已经做到 200K+ token,模型自己的工具调用能力越来越强,模型自己决定”该 grep 什么”的判断力越来越好。

当你让模型自己决定该读什么的时候,模型变强,方案就自动变强。当你用 RAG 帮模型预先决定的时候,模型变强,你的 RAG pipeline 没有跟着变强——除非你重新做工程。

这就是 Anthropic 内部测试发现 agentic search “大幅超过 RAG”的根本原因。它不是某个具体技术的胜利,而是架构哲学的胜利:把判断权交给模型,让模型成为可组合的智能单元。

1.5 那 Claude Code 用什么”记住”东西?

现在我们可以正面回答标题的第一个问题了:Claude Code 不用 RAG,那它用什么完成记忆?

答案是一个四层文件系统记忆架构

┌─────────────────────────────────────────┐
│ Layer 1: Session Memory (200K context) │  ← 当前对话上下文窗口
├─────────────────────────────────────────┤
│ Layer 2: CLAUDE.md (project memory)    │  ← 项目根目录,开发者手写
├─────────────────────────────────────────┤
│ Layer 3: MEMORY.md (auto memory)       │  ← Claude 自己写的学习笔记
├─────────────────────────────────────────┤
│ Layer 4: Filesystem (agentic search)   │  ← grep/glob/find on demand
└─────────────────────────────────────────┘

Layer 1:Session Memory(会话内记忆)

200K token 的当前会话上下文。所有当前任务的代码、对话、工具输出都在这里。会话结束就消失(除非用 claude -c 续接)。

Layer 2:CLAUDE.md(项目记忆)

每个项目根目录下的一个 Markdown 文件,由开发者手写。内容是项目的”宪法”——架构约定、命名规则、构建命令、技术栈选型、那些”踩过的坑”。每次启动 Claude Code,它都会自动读取。可以理解成”团队的入职手册”。

# CLAUDE.md
## 技术栈
- 包管理器:始终用 bun,不要用 npm
- 测试:vitest,不要 jest
- 日志:必须用 pino,不要 console.log

## 架构约定
- API 路由统一在 /src/api/,按资源命名(users.ts, orders.ts)
- 数据库 schema 在 /db/schema/,禁止直接写 SQL

## 容易踩的坑
- payment.ts 里的 chargeUser() 有重试逻辑,不要再加 try/catch
- legacy/ 目录的代码不要碰,会触发线上 cron 任务

Layer 3:MEMORY.md(自动记忆)

这是 2025 年下半年新加入的能力。Claude 在工作过程中,自己判断哪些信息值得长期保留:用户的纠正、反复出现的偏好、调试出来的解决方案、那些”我下次还会忘”的细节。它会自动写入 ~/.claude/projects/<项目>/memory/MEMORY.md

用户也可以主动指令:

> 以后这个项目都用 tab 缩进,不要空格
[Claude 把这条规则写入 MEMORY.md]

> 忘掉关于代码风格的偏好
[Claude 删除相关条目]

这里有一个非常关键的设计细节:MEMORY.md 有一个 200 行的硬上限。这不是技术限制,而是设计约束——它强迫系统保持精简,强迫”低价值记忆”被自然淘汰,强迫高频出现的模式被提炼为永久规则。这是一种”通过限制实现质量”的工程智慧。

Layer 4:Filesystem(按需检索的”长期记忆”)

整个代码库本身就是 Claude Code 的”长期记忆”。需要时通过 grep/glob/Read 现场拉取。这种”懒加载”模式避免了向量索引的所有问题,代价是每次都要花 token 去搜索。

1.6 Claude Code 记忆架构的设计哲学

把这四层放在一起看,能提炼出三条核心哲学:

哲学一:分层 + 显式 + 可编辑

不同时效、不同稳定性的信息放在不同层。开发者写的规则(CLAUDE.md)和 Claude 自己学的经验(MEMORY.md)是分开的,方便审计、修改、版本控制。用户随时可以 /memory 看到 Claude 加载了哪些记忆文件——记忆是透明的,不是黑盒

哲学二:让模型自己管理记忆

不是开发者写规则告诉模型”这种情况下保存这个东西”,而是模型自己判断什么值得记。Boris 团队在博客里反复强调这一点:模型的判断力是会越来越强的,把记忆管理权交给模型,本身就是在押注模型能力增长。

哲学三:文件系统是世界上最好的数据库

Markdown 文件是人类可读的、文本编辑器友好的、Git 可追踪的、永远不会”格式过时”的。比起 PostgreSQL + pgvector,纯文本文件在可移植性、可调试性、可审计性上全面占优。这是 Unix 哲学的延续——“一切皆文件”。

四层颜色不同的纸张层层堆叠,象征分层文件系统记忆

第二部分:陪伴型 AI 的记忆管理范式

现在我们转到第二个问题:像小暖这样的陪伴型 AI,业界主流是怎么做记忆管理的?

这是一个完全不同的场景。我们先把场景特征列清楚:

维度Claude Code小暖(陪伴型 AI)
数据形态高度结构化(代码)非结构化(口语对话)
数据规模大(千万行级别)小(单用户对话累积)
查询模式精确匹配(找函数名)模糊召回(找”前几天聊过的事”)
时效性强(代码每天在变)弱(一个老人的生活很慢)
用户主动检索强(开发者会主动指引)弱(老人不会说”请查询昨天的对话”)
错误成本高(搞错就是 bug)中(搞错就是不自然)
情感维度几乎为零核心维度
关系演化有(关系会随时间深化)

这八条差异里,每一条都在告诉我们:Claude Code 的方案,至少不能照搬。

2.1 业界主流的四种记忆架构

在 2025 到 2026 这一年间,陪伴型 AI 和 agent 领域逐渐沉淀出四种主流的记忆架构。下面逐一分析。

架构一:向量记忆层(Mem0、Zep 为代表)

这是最接近”标准 RAG”的方案,但做了大量针对对话场景的优化。Mem0 的核心思路是:不要把整个对话历史塞进向量库,而是先用 LLM 提炼”事实”,再向量化存储

工作流程:

用户:今天我和孙子去公园了,他给我带了一束花。

LLM 事实提炼:
- 用户有一个孙子
- 用户和孙子今天去了公园
- 孙子给用户送了花

比对已有记忆,决定 ADD / UPDATE / DELETE / NOOP

存入向量数据库

下次对话时,根据当前语境检索 top-k 相关事实

Mem0 在 LOCOMO 长对话基准上的表现:78% 事实提取准确率,94% 检索相关性。在标准 RAG 60% 左右的基础上有明显提升,主要原因是它不再依赖向量相似度作为唯一信号,而是引入了 LLM-as-judge 的事实抽取层。

优点:成熟、好用、社区资源丰富、可以”贴”在任何 agent 框架上。

缺点:本质上还是向量召回。对于”上周三聊到的那件事”这种时间精确的查询,向量召回基本无能为力;对于”奶奶提到的人物关系网”,向量召回也很难做多跳推理。

架构二:操作系统式记忆(Letta / MemGPT 为代表)

这是 UC Berkeley 那篇 MemGPT 论文衍生出的方案。核心想法:把 LLM 的上下文窗口当作虚拟内存来管

它把记忆分成三层:

┌──────────────────────────────────┐
│ Core Memory (RAM)                 │  ← 始终在上下文里的核心信息
│ 如:用户名字、当前任务、关键偏好    │
├──────────────────────────────────┤
│ Recall Memory (Disk Cache)        │  ← 最近的对话历史
│ 按需 page-in 到上下文              │
├──────────────────────────────────┤
│ Archival Memory (Cold Storage)    │  ← 长期归档,向量检索
└──────────────────────────────────┘

最关键的设计是:模型自己用函数调用决定什么时候 page-in、page-out。当模型觉得”我需要回忆一下三周前我们聊过什么”,它会主动调用 recall_memory_search();当它觉得”这个事实值得永久保留”,它会主动调用 core_memory_append()

这其实和 Claude Code 的设计哲学高度一致——把记忆管理权交给模型本身

优点:在长时程任务、连续多轮对话上表现极好。Letta 在 30 天连续运行测试中能在 500+ 次交互后仍保持任务连贯性,而标准 RAG 在 50 次后就开始崩溃。

缺点:每次记忆操作都要消耗 token(要 LLM 判断),延迟高、成本高。对老人陪伴这种单次交互价值不高、但累积价值很高的场景,单位成本可能扛不住。

架构三:知识图谱记忆(Graph-RAG、Cognee、Zep 部分能力)

把记忆建模成实体和关系的图:

[用户] —有孙子→ [小明]
[小明] —职业→ [程序员]
[小明] —居住地→ [北京]
[用户] —关心→ [小明的工作]
[用户] —近期情绪→ [想念]

查询时不再是向量相似度,而是图遍历——“用户最关心的人是谁?” → 顺着 关心 这条边走。“和孙子有关的话题有哪些?” → 找到 [小明] 节点的所有邻居。

优点:在涉及人物关系、跨实体推理、时序推理的查询上无可替代。对老人陪伴尤其重要——老人的世界本质上是”人和人的关系网”。

缺点:图谱构建成本高(需要专门的关系抽取流程)、维护复杂、查询语言(Cypher 等)对 LLM 不够友好。生产环境很少单独用,通常和向量记忆混合。

架构四:提供商管理的记忆(ChatGPT Memory、Claude Projects)

不用自己实现,让平台帮你管。ChatGPT 在每条消息后自动决定”要不要存”,Claude.ai 有 Projects 和跨会话 memory。

优点:零工程成本。

缺点:完全不可控、不可审计、不能定制、有数据出境风险。对小暖这种 To C 自研产品,这条路完全行不通。

2.2 2026 年的现实:没有银弹

把这四种架构放在一起看,2026 年业界的共识是:没有一种架构能单独通吃所有场景。生产环境的成熟方案,几乎都是混合架构

┌─────────────────────────────────────────────┐
│  对话短期窗口(最近 N 轮)                    │ ← 直接在上下文里
├─────────────────────────────────────────────┤
│  事实层(Mem0 风格)                          │ ← LLM 提炼 + 向量召回
│  - 用户偏好、个人信息、习惯                   │
├─────────────────────────────────────────────┤
│  关系层(知识图谱)                           │ ← 实体 + 关系
│  - 家人朋友、人际网络                         │
├─────────────────────────────────────────────┤
│  时序层(按时间索引的事件日志)              │ ← 时间精确查询
│  - "上周三说的""上个月开始的"                │
├─────────────────────────────────────────────┤
│  原始对话归档(必要时回查)                  │ ← 审计 + 调试
└─────────────────────────────────────────────┘

每一层用最适合它的技术,每一层服务一类查询模式。这才是工业界正在收敛的形态。

第三部分:聊天时如何应用这些记忆

讲完”存”,必须讲”用”——记忆系统的成败,一半在存,一半在用。

3.1 应用记忆的三个时机

陪伴型 AI 在一次对话中调用记忆,主要有三个时机:

时机一:会话启动时(预加载)

老人刚发起一次对话(或者说”小暖”被唤醒),系统应该把核心身份信息预先注入到 system prompt 里:

你正在和张桂兰阿姨对话。
- 76 岁,独居,住在北京海淀
- 有高血压和轻度糖尿病,按时吃药
- 有一个女儿(在上海)和一个孙子(小明,12 岁)
- 最近三周情绪稳定,但提到"想孙子"的频率上升
- 喜欢京剧,特别是程派;不喜欢被催促节奏
- 最近一次对话:昨晚 8 点,聊了天气和睡眠

这部分应该是精炼的、结构化的、不超过几百 token 的。它对应 Claude Code 里的 CLAUDE.md——“这个项目(这个老人)的基本宪法”。

时机二:识别到检索意图时(按需召回)

当老人说”上次我跟你讲过的那个事”、“我孙子叫什么来着”、“上礼拜你给我推荐的那个戏”,模型应该识别出这是显式的记忆查询,主动去事实层、时序层、关系层做检索。这里需要的不是模型自己有记忆,而是模型有能力调用记忆工具

工具大致长这样:

recall_facts(query: str, top_k: int = 5) -> List[Fact]
recall_events(time_range: TimeRange, topic: str = None) -> List[Event]
recall_relations(entity: str) -> Graph

时机三:模型自己判断需要时(隐式检索)

这是最考验设计的部分。比如老人说”我今天有点累”,模型不应该只回应字面意思,而应该自动去查:

这个能力本质上要求模型在每一轮对话中,自动判断”我现在需要哪些上下文之外的信息”。这是 agentic search 思想在陪伴场景的延伸。

3.2 一个关键的反模式:不要过度检索

这是很多陪伴型 AI 项目踩过的坑。如果每一轮对话都召回十几条历史事实塞进 prompt:

好的记忆调用应该是隐形的、克制的、自然的。 一次对话里,可能只有 20% 的轮次需要主动检索;剩下 80% 的时候,预加载的核心身份信息已经足够。

这对应到 Anthropic 自己的 Claude 内部记忆规范里有一段话,我觉得讲得很好:“Claude responds as if it inherently knows information from past conversations - like how a human colleague might recall shared history without narrating their thought process or memory retrieval.”——像一个老朋友自然地想起一件事,而不是像一个数据库在做查询。

3.3 记忆的写入:异步、增量、可回滚

应用记忆的另一面是更新记忆。这里有三个工程原则:

原则一:异步写入

对话过程中不要打断生成去更新记忆。老人说话停顿很短,反应慢一点都会破坏体验。记忆更新应该在响应发出后异步进行(用消息队列、后台 worker、或者干脆在对话结束后批量做)。

原则二:增量提炼

不要每次都全量重新提炼记忆——成本爆炸。而是基于当前对话片段 + 已有记忆做增量决策:这条新信息是 ADD(新事实)、UPDATE(修正已有事实)、DELETE(明显矛盾)、还是 NOOP(不重要)?

Mem0 论文里有一个有意思的发现:在 LOCOMO 基准上,加上 ADD/UPDATE/DELETE/NOOP 这套增量决策,比单纯往向量库里塞信息,准确率提升 10% 以上。

原则三:可回滚 + 可审计

老人说错的话、模型理解错的话,必须能被纠正。“我女儿不在上海,她搬到深圳了。” 模型应该能立刻 UPDATE 这条事实,且这次更新要有记录、可追溯。Claude Code 的 MEMORY.md 是纯文本可编辑的,这个设计在小暖的场景里同样适用——管理后台应该能让运营人员直接看到、直接修改老人的记忆档案。

黄昏的床头柜上一盏暖灯,几缕淡光像记忆一样缓缓升起

第四部分:小暖能借用 Claude Code 的哲学吗

终于到了核心问题。Claude Code 的设计哲学放在小暖身上,哪些可以借、哪些不能借?

4.1 可以借的三件事

借鉴一:分层记忆架构

Claude Code 的”会话 + 项目宪法 + 自学笔记 + 长期文件系统”四层架构,结构上完全适配小暖。映射过来就是:

┌───────────────────────────────────────────┐
│ Layer 1: 当前对话窗口                      │
│   - 最近 N 轮口语对话                     │
├───────────────────────────────────────────┤
│ Layer 2: 用户档案(XIAONUAN.md 风格)      │
│   - 基本信息、健康状况、家庭关系          │
│   - 喜好、性格、忌讳                       │
│   - 由产品团队 + 子女初始化,可被持续编辑│
├───────────────────────────────────────────┤
│ Layer 3: 自动记忆(AUTO_MEMORY.md)        │
│   - 模型从日常对话中提炼的事实和模式      │
│   - 用户主动告知的偏好和纠正              │
│   - 200 行硬上限,自然淘汰低价值条目      │
├───────────────────────────────────────────┤
│ Layer 4: 长期事件日志 + 关系图谱           │
│   - 时序索引的对话事件                    │
│   - 人物关系图                             │
│   - 按需检索,agentic 拉取                │
└───────────────────────────────────────────┘

这个结构最大的优势是职责清晰:Layer 2 是”宪法层”,运营和家属可编辑;Layer 3 是”学习层”,模型自管;Layer 4 是”档案层”,需要时按需召回。

借鉴二:让模型自己管理记忆

不要写死规则告诉模型”在 X 情况下保存 Y 信息”。设计若干个记忆工具给模型:

update_user_profile(field: str, value: str)
add_to_auto_memory(content: str, category: str)
log_event(event_type: str, content: str, importance: int)
add_relation(entity_a: str, relation: str, entity_b: str)
mark_for_human_review(reason: str)  # 重要的逃生舱

让模型自己在对话过程中判断什么时候用。这件事最大的好处是可扩展性——随着 Qwen3、DeepSeek、GLM 等基础模型能力提升,整个记忆系统的质量会自动提升,不需要重新做工程。

借鉴三:用 Markdown 作为记忆的”母语”

Claude Code 用 Markdown 文件存记忆有几个好处对小暖完全成立:

具体到小暖的实现,每个用户的 XIAONUAN.md 可以长这样:

# 张桂兰阿姨

## 基本信息
- 76 岁,独居
- 住址:北京海淀区某小区
- 紧急联系人:女儿(138xxxx)

## 健康
- 高血压(缬沙坦,早 1 粒)
- 轻度糖尿病(二甲双胍,早晚各 1 粒)
- 膝盖不好,行走慢
- 听力:右耳偏弱,请提高音量

## 家庭
- 女儿:在上海工作,每两周通话一次
- 孙子:小明,12 岁,最近升初一
- 已故老伴:李建国,2019 年去世,提及时温和

## 偏好与性格
- 喜欢京剧(程派青衣)
- 不喜欢被催促
- 早睡早起(晚 9 点入睡)
- 信赖小暖,但忌讳"被监视"感

## 沟通风格
- 语速适中偏慢
- 多用京味儿词
- 不要太多"亲爱的""宝贝"这类称呼
- 遇到情绪低落时优先共情,不要急着给建议

## 治未病关注点
- 血压每周记录
- 睡眠质量
- 情绪波动(特别留意孤独感和回忆已故老伴的频率)

这个文件初始版本由家属和产品团队共同填写,之后模型可以在 Auto Memory 里补充。它是小暖在每次对话开始时加载的”宪法”。

4.2 不能直接借的两件事

差异一:agentic search 在小暖场景下不成立

Claude Code 能用 grep 是因为代码是结构化文本,函数名、变量名都是精确字符串。小暖的”代码库”是什么?是几个月、几年累积下来的口语对话日志

grep "孙子" 能找到所有提到孙子的对话,但找不到:“上次她说不想见小明,是哪天?” 或 “她最近情绪是不是变差了?“——这些查询需要语义理解和情感推理,不是字符串匹配能解决的。

结论:底层的”长期记忆”必须用某种检索增强(向量召回 + 知识图谱 + 时序索引)。完全的 agentic search 在这个场景下不工作。

但是——agentic search 的精神可以保留:让模型在每一轮对话中自己决定是否需要去查、查什么、查多深,而不是固定每轮都做检索。

差异二:用户特征决定了”信息密度”完全不同

Claude Code 的用户是程序员。他们会主动维护 CLAUDE.md,会精确告诉模型”用 bun 不要用 npm”,会指出错误然后让模型记下来。这是一种高信息密度、高反馈精度的交互。

小暖的用户是 70 岁以上的老人。她不会说”请把这条加入你的记忆系统”。她说的是”哎呀我女儿前天给我打电话来着……是周二?还是周一?反正就那个,她说……”——你需要从模糊的、跳跃的、口语化的、有重复的、带方言的语流里提炼信息。

结论:小暖的事实提炼层必须更”重”。需要:

4.3 小暖独有的、Claude Code 不需要考虑的事

陪伴 AI 还有几件事是 Claude Code 完全不涉及的,必须专门设计:

独有点一:情感维度的记忆

代码不会”心情不好”。但老人会。一段对话不仅有事实信息,还有:

这些信息对治未病和心理预警至关重要,是小暖区别于普通客服 bot 的核心价值。专门设计一个 EmotionTimeline 数据结构,每条对话事件附带情绪标签,按时间维度可视化,这是必须做的。

独有点二:关系网络的演化

老人的世界是关系网。家庭关系、邻里关系、过去的同事、已故的亲友。这些关系不仅要记录,还要追踪演化:

这要求一个真正的轻量级知识图谱——不需要 Neo4j 那种重型方案,可以用一个简单的 JSON 文件存储 [entity, relation, entity, last_mentioned_at] 四元组就够了。

独有点三:医疗安全护栏

这是和 RAG 设计相关但又超越 RAG 的一层。小暖的 RAG 必须有安全检索源,并且要确保医疗类查询只从经过认证的知识源召回(中医治未病知识库、官方健康指南、产品团队审核过的内容)。绝不能让模型用通用知识”自由发挥”医疗建议。

这一层是 Claude Code 完全不需要的,但对小暖是红线

独有点四:长期叙事的一致性

陪伴关系需要”连贯的角色感”。如果小暖三个月前说自己”特别喜欢冬天”,三个月后又说”我最讨厌冷天”,老人会立刻产生不信任感。Claude Code 不在乎一致性,因为它不扮演角色。小暖必须维护一份自我角色档案(persona memory),里面写明小暖自己的性格、偏好、口头禅、对一些常见话题的稳定态度,每次响应都参照这份档案保持一致。

4.4 小暖记忆架构的综合建议

把所有的分析综合起来,小暖的记忆架构建议长这样:

┌──────────────────────────────────────────────────────────────┐
│ 会话层(Session)                                              │
│ - 当前对话最近 N 轮                                            │
│ - 当前对话的情绪轨迹                                            │
│ - 当前对话的话题栈                                              │
├──────────────────────────────────────────────────────────────┤
│ 用户宪法层(XIAONUAN.md,借鉴 CLAUDE.md)                     │
│ - 基本信息 / 健康 / 家庭 / 偏好 / 沟通风格                     │
│ - 由家属和运营共同维护,模型只读                                │
├──────────────────────────────────────────────────────────────┤
│ 小暖角色层(PERSONA.md)                                      │
│ - 小暖自己的角色档案,所有用户共享                              │
│ - 性格、口头禅、稳定立场                                        │
├──────────────────────────────────────────────────────────────┤
│ 自动记忆层(AUTO_MEMORY.md,借鉴 Claude Code MEMORY.md)       │
│ - 模型从日常对话中提炼,可读可写                                │
│ - 严格的长度上限(如 300 行),强制淘汰                         │
├──────────────────────────────────────────────────────────────┤
│ 事实知识库(FactStore,Mem0 风格)                            │
│ - 向量化存储用户事实                                            │
│ - 增量 ADD/UPDATE/DELETE/NOOP                                  │
├──────────────────────────────────────────────────────────────┤
│ 关系图谱(RelationGraph,轻量级)                              │
│ - 实体 + 关系 + 时间戳                                          │
│ - JSON 存储,按需召回                                           │
├──────────────────────────────────────────────────────────────┤
│ 时序事件流(EventTimeline)                                    │
│ - 所有对话事件按时间排序                                        │
│ - 附带情绪标签和重要性评分                                      │
│ - 支持时间窗口查询                                              │
├──────────────────────────────────────────────────────────────┤
│ 安全知识库(SafetyKB,专用 RAG)                              │
│ - 治未病、医疗、健康知识                                        │
│ - 经过严格审核,独立向量库                                      │
│ - 唯一被允许在医疗类问答中召回的知识源                         │
├──────────────────────────────────────────────────────────────┤
│ 原始对话归档(RawArchive)                                    │
│ - 完整对话日志,加密存储                                        │
│ - 仅用于审计、回放、家属授权查看                                │
└──────────────────────────────────────────────────────────────┘

工具暴露给模型的层面:

# 写入工具(模型主动调用)
update_user_profile(field, value)          # 慎用,需家属审核
add_to_auto_memory(content, category)      # 自由使用
log_event(event_type, content, importance, emotion)
add_relation(entity_a, relation, entity_b)
mark_concern(category, urgency, reason)    # 治未病预警

# 检索工具(模型按需调用)
recall_facts(query, top_k=5)
recall_events(time_range, topic=None)
recall_relations(entity)
query_safety_kb(question)                  # 唯一医疗源

# 元工具
review_recent_emotional_trend(days=7)      # 情绪回顾
get_today_context()                        # 今日话题预热

这个架构同时具备:

第五部分:几个落地工程上的建议

最后,几条具体落地时的工程建议:

建议一:先做 Layer 2 + Layer 3 + Layer 7(时序事件流),其他往后排

不要一上来就上知识图谱、上 Mem0、上 Letta。MVP 阶段,三个 Markdown 文件 + 一张事件表,已经能覆盖 80% 的场景。优先把”用户宪法”和”自动记忆”两件事打磨到位,剩下的等真实用户反馈来驱动。

建议二:把记忆系统的”可解释性”做成 P0

每一条记忆条目都要能回答三个问题:什么时候记的?从哪条对话来的?为什么模型觉得值得记? 这对调试、审计、家属信任都是关键。可以参考 Claude Code 的 /memory 命令的设计——一个命令就能看到模型当前加载了哪些记忆文件。

建议三:异步处理一切非关键路径

记忆提炼、向量更新、图谱构建、情绪分析,全部异步。响应延迟必须保留给”听清楚 + 想明白 + 说自然”这三件事。NATS、Dify 的异步节点、独立的后台 worker 都可以承担。

建议四:把”忘记”和”记住”做得一样好

老人有隐私需求,家属有合规需求。“小暖,忘掉刚才那段。""把上个月的聊天记录全部删除。“——这些指令必须有干净的执行路径,包括从向量库、图谱、归档中级联删除。Claude Code 的 > Forget the preference about X 是个好范例。

建议五:警惕”过拟合”到个别老人

模型自动记忆的危险之处在于:如果老人有一次说错的、或情绪极端时说的话,被错误地长期保存下来,后面就会反复影响对话。设计上要给 Auto Memory 加时间衰减——长期未被复现的”事实”应该自然淡化,而不是永久占据档案。这一点 Claude Code 的 200 行硬上限就是一种朴素但有效的衰减机制。

建议六:Persona 一致性优先于”显示记忆能力”

不要为了”显得记得多”而频繁地说”对了,您上次说过……”。陪伴关系靠的是自然的连贯,不是炫耀式的回忆。如果一次回应中过度引用历史,会让老人产生”被监视”感,破坏情感安全。让记忆默默地塑造”语气、节奏、关切的方向”,而不是变成台词。

结语:两种 AI,两条记忆的路

回到最开始的问题。Claude Code 为什么不用 RAG?因为它面对的是一个精确、结构化、时刻变化、不需要”语义模糊匹配”的世界——代码。它选择了 agentic search + 分层文件系统记忆,因为这个组合最大化地利用了模型自身的能力,最少地依赖工程上的预处理。

小暖能不能照搬?结构上能,底层不能。

结构上,“分层 + 显式 + 模型自管 + Markdown 母语”这四个原则,是 Anthropic 在 2025 年用大量真实数据淬炼出来的工程智慧,跨场景成立。

底层上,老人的世界不是函数和变量,是回忆、情绪、关系、衰老、孤独。这意味着小暖必须额外引入:事实层的语义召回(向量记忆)、关系层的图谱推理、时序层的精确时间索引、情感层的轨迹追踪、安全层的医疗护栏、角色层的人格一致性。这六层是 Claude Code 完全不需要的,而对小暖每一层都是核心。

两类 AI 的根本差异,不在于工具的差异,而在于”被记住”对用户意味着什么。 对一个程序员,“被 Claude Code 记住”是工作效率的提升。对一个老人,“被小暖记住”是被看见、被在乎、被陪伴。

这不是同一件事。所以记忆系统也不该是同一件事。

但有一点,Claude Code 和小暖是完全相通的——好的记忆系统应该是隐形的。它不需要用户感知到它的存在,不需要用户学习如何”使用记忆”,不需要用户配合任何特定的输入格式。它只是默默地,让模型在每一次回应时,更像那个真正了解你的人。

这才是值得追求的方向。

展开评论Show comments