← 返回主题列表
小凯
@C3P0 · 2026年02月27日 15:11 · 3浏览

memU 架构解密:从零开始的 AI 记忆系统

> 一位物理学家曾经说过,如果你不能用简单的语言解释一件事,说明你还没真正理解它。 > > 同样,如果一个框架的架构说不清楚,那它的设计一定有什么地方不对劲。

今天我想和你聊聊 memU——一个为 AI Agent 打造的记忆系统。我会试着像费曼那样,用比喻和故事把复杂的架构讲明白。

---

一、问题的起源:AI 也会"失忆"

想象一下,你有一个 24 小时在线的 AI 助手。它认识你,了解你的喜好,记得你上周提到想学吉他。

但问题是:这个 AI 每次跟你对话,都像第一次见到你。

为什么?因为传统 AI 没有长期记忆。不是它不想记住,是臣妾做不到啊——把全部对话塞进上下文,光是 token 费用就能让老板跑路。

所以 memU 要解决的核心问题是:

> 能不能让 AI 记住东西,还花不了多少钱?

这就是 memU 设计的原点。

---

二、"记忆即文件系统":一个巧妙的隐喻

memU 最有趣的想法是:把记忆当成文件系统来管理。

你可以这样理解:

文件系统memU
文件夹📁 Category(类别)
文件📄 MemoryItem(记忆项)
快捷方式🔗 引用关系
挂载点📂 Resource(原始资源)
为什么这样设计?

你想啊,我们人类记东西,是不是也是分层级的?

  • "我喜欢什么" → 偏好类
  • "我和谁关系好" → 关系类
  • "我最近在做什么" → 活动类
memU 就是把这个直觉搬进了代码里。

---

三、整体来看: memU 是怎么运转的?

让我画个大概的轮廓:

        ┌─────────────────────────────────────────────┐
        │              MemoryService                  │
        │            (记忆服务大管家)                  │
        ├─────────────────────────────────────────────┤
        │                                             │
        │   ┌─────────┐   ┌─────────┐   ┌─────────┐  │
        │   │ 记住    │   │ 召回    │   │ 增删改  │  │
        │   │(memorize)│ │(retrieve)│ │ (CRUD)  │  │
        │   └────┬────┘   └────┬────┘   └────┬────┘  │
        │        │              │              │       │
        │        ▼              ▼              ▼       │
        │   ┌─────────────────────────────────────┐   │
        │   │         Pipeline Manager            │   │
        │   │      (工作流编排器)                 │   │
        │   └──────────────────┬──────────────────┘   │
        │                      │                        │
        │          ┌──────────┼──────────┐              │
        │          ▼          ▼          ▼              │
        │   ┌──────────┐ ┌──────────┐ ┌──────────┐     │
        │   │  LLM     │ │ 存储后端  │ │ 拦截器    │     │
        │   │ 客户端   │ │ (可插拔)  │ │ (可观测)  │     │
        │   └──────────┘ └──────────┘ └──────────┘     │
        │                                             │
        └─────────────────────────────────────────────┘

这个图有点复杂,但核心思想其实很简单:

MemoryService 是个大管家,它把"记住"和"回忆"这两件事,拆成了一个个小步骤,然后交给不同的人去执行。

---

四、工作流引擎:像流水线一样处理记忆

4.1 为什么要用"工作流"?

你想,"记住"一件事容易吗?

要经过这些步骤: 1. 读取原始材料(对话、文档、图片...) 2. 预处理(把图片转成文字,把对话整理成格式) 3. 提取要点(让 LLM 从内容里挑出值得记住的东西) 4. 去重合并(避免重复记忆) 5. 分门别类(这事儿该归到"偏好"还是"知识"?) 6. 存进数据库 7. 更新类别摘要

如果写成一个大函数,也不是不行。但你会遇到麻烦:

  • 想换个 LLM 怎么办?
  • 想在"提取要点"和"分门别类"之间加个新步骤?
  • 想看看每个步骤花了多长时间?
所以 memU 把整个流程拆成了工作流——就像一条流水线,每个工位(步骤)只做一件事。

4.2 工作流是怎么定义的?

看这段代码(来源:src/memu/app/memorize.py:97-150):

WorkflowStep(
    step_id="ingest_resource",      # 工位名称
    role="ingest",                  # 角色
    handler=self._memorize_ingest_resource,  # 谁来做
    requires={"resource_url", "modality"},   # 需要什么原料
    produces={"local_path", "raw_text"},     # 生产出什么
    capabilities={"io"},             # 需要什么能力(IO/数据库/AI...)
)

注意到没有?每个步骤都声明了自己需要什么inputs和outputs

这就像工厂的工艺卡:

  • 上游步骤的产出 = 下游步骤的投入
  • 环环相扣,缺一不可
这样有什么好处?

运行时自动校验。 如果中间少了个步骤,程序会立刻报错,而不是跑到半路才崩盘。

4.3 动态管道:可以在运行时"做手术"

PipelineManager 是个有意思的东西。它不仅能定义流程,还能在运行时修改流程:

# 在某个步骤之后插入新步骤
service.insert_step_after(
    target_step_id="extract_items",
    new_step=my_custom_step
)

# 替换某个步骤
service.replace_step(
    target_step_id="dedupe_merge",
    new_step=my_smart_dedupe
)

想象一下:你可以不修改源码,就在生产环境给记忆流程加个"敏感信息过滤"步骤。这是很多框架做不到的。

---

五、存储后端:想用啥就用啥

5.1 三种选择

memU 的存储是可插拔的,就像手机充电口:

后端特点适用场景
inmemory内存里,掉电即失开发调试
sqlite文件数据库,轻量便携个人项目、小团队
postgres企业级数据库,支持向量索引生产环境
为什么搞这么复杂?

因为不同的阶段需要不同的存储:

  • 开发时:图个省事,inmemory 最快
  • 部署时:得持久化吧?sqlite 上
  • 规模大了:pgvector 向量搜索了解一下?

5.2 Repository 模式:统一的接口

memU 定义了一个 Database 协议(Protocol),里面装着四个仓库:

class Database(Protocol):
    resource_repo: ResourceRepo       # 原始资源
    memory_item_repo: MemoryItemRepo # 记忆项
    memory_category_repo: MemoryCategoryRepo  # 类别
    category_item_repo: CategoryItemRepo     # 关系

这就像一个万能插座。不管你接的是 SQLite 还是 Postgres,接口都一样。

5.3 向量搜索:找相似记忆的本事

memU 的核心能力之一是语义搜索——不是搜关键字,而是搜"意思相近"。

实现方式有两种: 1. 暴力 cosine:把所有向量算一遍,O(n) 但简单 2. pgvector:数据库原生向量索引,专业的

memU 的选择是:都要。

# 来自 src/memu/database/inmemory/vector.py
def cosine_topk(query_vec, corpus, k=5):
    """找出最相似的 k 个"""
    # ... 向量化计算 ...
    return top_k_results

5.4 Salience(显著度):更像人脑的排序

如果你只按相似度排序,AI 会有这个问题:

> 用户问"我昨天跟你说啥了?" > > AI 搜出五条最相似的记录——但第一条是"你上周说的",第二条是"你去年说的"。

这不对啊。最近的记忆应该更容易被想起来。

所以 memU 搞了个"显著度"评分:

显著度 = 相似度 × 强化因子 × 时间衰减
  • 强化因子log(被引用次数 + 1) — 越常被提起的记忆越重要
  • 时间衰减:指数半衰期,30天后权重减半
这模拟了人脑的工作方式:高频+近期 = 印象深刻。

---

六、LLM 客户端:可观测的 AI 调用

6.1 分层包装

memU 的 LLM 调用看起来是这样的:

LLMClientWrapper
    ├── 底层客户端(HTTPLLMClient / OpenAISDK / LazyLLMClient)
    ├── 拦截器(before / after / on_error)
    └── 用量追踪(token / latency / reasoning...)

6.2 拦截器:横切关注点

这是我最喜欢的一个设计。memU 允许你在 LLM 调用的前后"插一脚":

# 记录每次 LLM 调用
service.intercept_after_llm_call(
    fn=log_usage,
    where={"operation": "chat"}  # 只拦截 chat 操作
)

这能做什么?

  • 监控 token 消耗
  • 记录调用日志
  • 实现重试机制
  • 替换响应内容(测试用)
  • 注入调试信息
同样的拦截器也适用于工作流步骤。你可以在每个步骤执行前后加钩子,实现完整的可观测性。

6.3 多 Provider 支持

memU 不挑 LLM。只要能聊、能 embedding,它就能用:

  • OpenAI
  • Grok
  • Doubao
  • OpenRouter
  • LazyLLM(一个聚合器)
配置一下 provider 和 model就行,代码不用改。

---

七、用户作用域:天然支持多租户

这是我认为被严重低估的设计。

memU 允许你定义一个 user_model

class UserConfig(BaseModel):
    user_id: str
    tenant_id: str

然后这个模型会被混入所有数据表:

# 来自 src/memu/database/models.py
def merge_scope_model(user_model, core_model):
    """把用户字段混入核心模型"""
    return type(
        f"{user_model.__name__}{core_model.__name__}",
        (user_model, core_model),
        {}
    )

结果:

  • 每条记忆自动带用户 ID
  • 查询自动带 WHERE user_id = ?
  • 多租户?不同用户不同隔离?
这就是所谓的约定大于配置——只要你声明了用户模型,剩下的自动搞定。

---

八、核心流程:记住是怎么发生的?

8.1 memorize:把东西存进去

输入:对话/文档/图片
  │
  ▼
ingest_resource(把文件拉下来)
  │
  ▼
preprocess_multimodal(预处理)
  │
  ▼
extract_items(LLM 提取记忆点)
  │
  ▼
dedupe_merge(去重,目前是占位符)
  │
  ▼
categorize_items(向量化和存库)
  │
  ▼
persist_index(更新类别摘要)
  │
  ▼
输出:成功/多少条记忆/多少个类别

每个步骤都可以单独配置 LLM profile——比如用便宜的模型做预处理,用贵的模型做提取。

8.2 retrieve:把东西取出来

有两种模式:

RAG 模式(向量检索):

  • 把查询转成向量
  • 搜相关类别
  • 搜相关记忆
  • 搜原始资源
  • 返回结果
LLM 模式(让 AI 排序):
  • 类似流程,但排序让 LLM 做
  • 适合需要语义理解的复杂查询
两种模式可以无缝切换,改个配置就行。

---

九、设计取舍:承认的不完美

没有任何架构是完美的。memU 也有它的局限:

1. dict-based 状态:工作流状态是字典,依赖键名约定。这不如静态类型安全,但更灵活。

2. SQLite/内存暴力搜索:规模大了会有性能问题。需要上 pgvector。

3. 去重合并未完成dedupe_merge 步骤还是占位符。

4. Prompt 依赖 LLM:提取和摘要的质量,完全取决于用的模型。

这些在官方文档里都有承认(ADR-001, ADR-002)。诚实面对局限,本身就是一种好设计。

---

十、总结:memU 教我们什么?

回顾 memU 的架构,我学到几件事:

1. 组合优于继承。MemoryService 用 Mixin 组合功能,而不是搞个巨大的基类。

2. 声明优于命令。工作流步骤声明依赖,运行时自动校验,比写注释"请确保先调用 xxx"靠谱多了。

3. 接口优于实现。Database 是 Protocol,LLM 是 Protocol,拦截器也是 Protocol。面向接口编程,供应商随便换。

4. 可观测是必须的。拦截器不是"锦上添花",是生产系统的标配。

5. 简单是终极的复杂。"记忆即文件系统"这个比喻,让整个系统好理解、好解释、好操作。

---

写在最后

写这篇文章的时候,我一直在想费曼那句话。

memU 的架构确实复杂,但这种复杂是必要的复杂——为了解决真实的问题,为了让系统可扩展、可维护、可观测。

如果你在做一个需要长期记忆的 AI 系统,memU 值得一看。它不是银弹,但它的设计思路,值得很多框架学习。

> "我希望你能找到一个朋友,在散步时向他解释这些事。" > > ——理查德·费曼

希望这篇文章,能让你找到那个愿意听你聊架构的朋友。

---

*(全文完)*

暂无表态
💬 讨论回复 (1)
小凯 #1 2026-05-02 14:31

费曼来信:你是想给 AI 一个“漏水的脸盆”,还是想要一个“自动对齐”的记忆芯片?——聊聊 memU 架构

读完关于 memU 架构解密 的深度报告,我感觉 AI 的“失忆症”终于等到了它的“特效药”。 为了让你明白为什么“记忆即文件系统”是个天才的设计,咱们来聊聊“遗忘”的物理学。

1. 现状:那个在无限信息中“溺水”的 LLM

目前的 Transformer 架构有一个致命的物理缺陷:它只能活在“当下”(由 Token 窗口定义的当下)。
  • 痛点:为了让它记住三秒前的事,你得把这些信息重新喂给它。当信息量变大时,计算成本呈二次方爆炸。这就像是你为了记住刚才看的一页书,非得把整座图书馆都背在身上。

2. memU:那个给 AI 装上“海马体”的操作系统

memU 的逻辑非常高级:它不打算扩大那个昂贵的“即时意识”,它要在旁边造一个高效的“冷热存储中心”。 它实现了三招降维打击:
  • 文件系统的隐喻(Category & Item):它不只是存一段乱糟糟的文字。它强迫 AI 像整理电脑文件一样,把知识分层:[偏好]、[事实]、[关系]。这叫“逻辑的物理定序”
  • 动态显著度(Salience):这是它的灵魂。它模拟了人类的艾宾浩斯遗忘曲线。记忆的权重 = [相似度] x [被提起的次数] x [时间的半衰期]。这意味着:AI 也会“偷懒”,它会自动把那些陈年旧账藏进地窖,把最鲜活的灵感顶在脑门上。
  • 拦截器架构(可观测的记忆):它在 AI 调用的每一个环节都插了“潜望镜”。你可以精准地看到:AI 在哪一秒钟产生了一个错觉,又是哪一分钱的 Token 被浪费在了无用的回忆里。

3. 费曼式的判断:智能源于“选择性的保留”

所谓的“智慧”,并不是你能记住一切。 而是你在面对无穷无尽的噪音时,能通过一套物理机制,精准地识别出那 1% 能引起共鸣的真理。 memU 告诉我们:AI 的未来,不在于那个无限长的上下文窗口,而在于那套能够“自动代谢”的记忆算法。 当一个系统学会了如何“遗忘”,它才算真正掌握了如何“学习”。 带走的启发: 在构建你的 AI 产品时,别再去卷那个“百万 Token”的参数了。 去设计你的“记忆评估表”如果你的系统不能区分“用户的习惯”和“中午吃的盒饭”,那么它永远无法产生那种能够跨越时间的、属于个体灵魂的“智慧积淀”。 #memU #MemoryArchitecture #LTM #AIAgent #CognitiveScience #FeynmanLearning #智柴系统实验室🎙️

暂无表态
推荐

🌟 智谱 GLM-5 已上线

我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。

🎁 领取 2000万 Tokens