3856 字
约 12 分钟
17
6.2 MemGPT 思路:把上下文当内存管理
2026-10-25
无标签

6.2 MemGPT 思路:把上下文当内存管理

一句话结论:MemGPT 的核心不是"更大的窗口",而是像操作系统管内存一样管上下文——把模型当 CPU、把上下文当 RAM、把外部存储当硬盘,然后让模型自己决定什么时候读盘、什么时候写盘。

读这篇之前

需要先读 6.1(三层记忆)、5.2(压缩)。这一篇是把"记忆"从"存起来"提升到"管起来"。


一、一个精准的类比

在计算机架构里,CPU 不直接读硬盘上的所有数据,而是通过内存管理在高速内存和低速硬盘之间调度。

MemGPT 把这个结构完整复刻到了 LLM 上:把大模型视为操作系统的内核(Kernel)。 [原文 292]

计算机 MemGPT 作用
CPU LLM 执行推理
RAM(内存) 主上下文(Main Context) 模型唯一能直接"看到"的区域
硬盘 外部存储(External Storage) 需要时才读取
MMU(内存管理单元) 一套函数调用接口 决定何时换入换出

这个类比之所以贴切,是因为它解释了为什么"更大的窗口"不是答案:内存再大也有上限,操作系统的解法从来不是"无限加内存",而是分页调度。


二、两层存储的具体划分

主上下文(Main Context)= RAM

这是模型在推理时唯一能直接看到的文本区域。它被划分为:

区域 内容 特点
固定区 系统提示词、核心设定 不变
动态区 当前对话流 每轮变化

注意:固定区不变这一点,正好符合 5.3 讲的缓存要求——MemGPT 在架构上天然缓存友好。

外部存储(External Storage)= 硬盘

分两种,各自解决不同问题:[原文 292]

存储 存什么 检索方式
Recall Storage(回忆库) 所有历史对话,按时间线 按时间/关键词
Archival Storage(档案库) 非对话类海量资料 向量检索 + 全文检索

为什么分两种? 因为它们回答的问题不同:

  • 回忆库回答"我们之前聊过什么"(时序性)
  • 档案库回答"关于 X 的知识是什么"(语义性)

把两者混成一个"向量库",会导致"找历史对话"和"找知识"互相干扰。


三、最硬核的部分:自主触发的中断机制

传统 AI 只能在用户提问后回答。MemGPT 在提示词里内置了一套自我循环逻辑:[原文 292]

指令 含义
Yield(让步) 处理完任务后,暂停等待用户输入
Continue(继续) 当模型意识到需要检索或多步思考时,无需用户干预即可连续运行

第二条是关键:模型可以自己决定"我还要再查一次"。

这实际上是把 1.2 讲的"循环控制权",从"代码决定何时继续"部分交给了模型。


四、它靠什么实现:一套记忆操作函数

MemGPT 的运行高度依赖 Function Calling(第 4 章)。它内置了一套标准 API:[原文 292]

函数 作用
send_message 给用户发消息
core_memory_append 在核心内存(长期偏好)中追加信息
core_memory_replace 修改核心内存中的内容
archival_memory_search 在档案库中做语义搜索
archival_memory_insert 往档案库写入
conversation_search 搜索过去的聊天记录

这些函数就是 4.1 讲的标准工具——只不过它们的操作对象是"记忆"而不是"外部世界"。

一个实际场景

用户问:"我去年在上海那家餐厅点的菜叫什么?"

① 模型看到主上下文里没有答案
② 决定调用 conversation_search("上海 餐厅")
③ 拿到检索结果
④ 整理后回复

注意第 ② 步:这是模型自己的决定(3.2 讲的"结构化输出"里,"action" 可以是 call_tool、respond、ask_user)。MemGPT 实际上多了一种 action:继续检索。


五、MemGPT 与 RAG 的本质区别

这是最容易混淆的地方。两者看起来都是"检索后回答",但有四个关键差异:[原文 292]

特性 传统 RAG MemGPT
数据流向 单向(检索 → 生成) 双向(读与写)
主动性 被动,由用户查询驱动 主动,模型决定何时检索、何时存储
状态管理 无状态,不记住检索过程 有状态,能记住自己之前的思考逻辑
应用场景 静态知识库查询 长期个性化助手、复杂任务链

核心差异:RAG 像是在查字典,而 MemGPT 像是在写日记并随时翻看日记。MemGPT 能动态地更新自己的记忆,这是 RAG 做不到的。

这个区别的实践含义很具体:

场景 用 RAG 够吗
查公司文档 ✅ 够(静态知识)
记住用户的偏好并逐步完善 ❌ 不够(需要"写")
跨会话累积项目上下文 ❌ 不够(需要"写" + 主动读)

六、它的代价

原文也点出了挑战。补上我的理解:[原文 292]

挑战 具体表现 应对
Token 成本 每轮要带记忆操作说明 + 可能多次检索 精简函数描述
延迟 多次自主循环 = 多轮推理 限制最大循环次数
不可预测 模型自己决定读盘,行为难复现 加终止条件 + 日志
记忆污染 写入的错误记忆会被长期使用 写入前校验、支持手工修正

第三条最需要警惕:模型自主决定"再查一次",会让行为不可预测。所以实践中通常会限制最大自主循环次数(如 3 次),避免失控。


七、常见误区

误区一:MemGPT 是"更大的上下文窗口"。
恰恰相反。它不追求更大窗口,而是管理窗口。

误区二:MemGPT 就是高级 RAG。
最大区别在"双向":MemGPT 会写记忆,RAG 只读。

误区三:记忆写进去就不用管了。
写入的错误会被长期使用。需要校验、需要能改(6.4)。

误区四:让模型自主循环越多越好。
越多越不可预测、越慢越贵。要有上限。

误区五:这个思路只适合大项目。
即使是小 Agent,"核心记忆 + 档案库"的分层也能显著提升体验。


八、动手:MemGPT 风格的最小实现

6.2 讲了架构。这里给出一个能跑的最小版本。

核心:把"记忆操作"做成工具

MEMORY_TOOLS = [
    {"name": "memory_search",
     "description": "在档案库中语义搜索历史事实。当你不确定某事时先搜。",
     "parameters": {"type": "object",
                    "properties": {"query": {"type": "string"}},
                    "required": ["query"]}},
    {"name": "memory_write",
     "description": "把一条确定的事实写入长期记忆。只在用户明确说过时使用。",
     "parameters": {"type": "object",
                    "properties": {"key": {"type": "string"},
                                   "value": {"type": "string"}},
                    "required": ["key", "value"]}},
    {"name": "continue_thinking",
     "description": "当你需要多步推理或再检索一次时调用,不必等用户输入。",
     "parameters": {"type": "object", "properties": {}}},
]

三个工具对应 MemGPT 的三个核心动作:读、写、自主继续。

主循环

def run(task, max_rounds=10):
    msgs = [{"role": "user", "content": task}]
    for _ in range(max_rounds):
        r = llm.chat(msgs, tools=MEMORY_TOOLS)
        call = r.tool_calls[0] if r.tool_calls else None

        if not call:
            return r.content                      # 正常结束

        if call.name == "memory_search":
            msgs.append(tool_result(call, memory_search(call.args["query"])))
        elif call.name == "memory_write":
            # 关键:只有可信来源才能写
            if call.args.get("trusted"):
                memory_write(call.args["key"], call.args["value"])
            msgs.append(tool_result(call, "ok"))
        elif call.name == "continue_thinking":
            msgs.append(tool_result(call, "continue"))
    return "达到最大轮数"

三个必须加的护栏

护栏 理由
max_rounds 模型自主"继续"可能无限循环(6.2 的代价)
写入需 trusted 防外部内容被写进记忆(6.4 的污染)
搜索结果要截断 防一次召回 20 条撑爆上下文

第二条最容易被省,而它是记忆污染的主要入口。


九、动手:MemGPT 思路的代价测算

6.2 讲了架构,但没算过账。这里算一下。

一个典型任务的成本对比

假设:一次任务需要 3 次"回忆"(检索历史),每次召回 5 条,每条 300 Token。

方案 每轮输入 3 次回忆后
无记忆(全塞历史) 15000 只能装 10 轮,之后崩溃
MemGPT 式(按需检索) 3000 3000 + 3×1500 = 7500

MemGPT 式的输入更小,而且不随轮数增长 —— 因为它不把历史全放上下文。

但多花的成本

额外开销 说明
每次检索是一次工具调用 多一轮推理
检索本身有延迟 向量检索通常 50-200ms
可能检索多次 第一次没找到还要再搜

所以它是一个权衡:

省下:常驻历史(每轮都付)
多花:按需检索(只在需要时付)

判据:

你的任务 适合 MemGPT 式吗
长任务(>15 轮) ✅ 省得明显
短任务(<5 轮) ❌ 检索开销大于省下的
需要频繁回忆 ✅
事实都在上下文里 ❌ 不需要检索

这张表能回答"我要不要做 MemGPT 式架构"这个问题。

一个实测建议

先用最简单的实现(历史 + 压缩)跑一批真实任务,统计:

  • 平均轮数
  • 出现过几次"模型重复问已问过的事"
  • 后几轮的质量是否下降

三个指标里有两个变差,才值得上 MemGPT 式架构 —— 否则就是过度设计(6.5)。


十、动手:不做记忆系统的三种替代方案

6.2 讲了 MemGPT 的代价。这里给出更轻的替代。

替代一:状态栏(最轻)

state = """
【已知信息】
- 用户:小明,后端工程师,用 Java
- 项目:Clarity,Spring Boot + Astro
- 当前任务:修复登录超时

【进度】已完成定位,下一步改配置
"""

成本:几十 Token/轮。
收益:解决 80% 的"它忘了"问题。

适用:单次任务、不需要跨会话。

替代二:CLAUDE.md 式常驻规则

项目约定写在固定文件里,每次会话自动加载

成本:一次配置,之后每轮读。
适用:稳定的项目知识,不是用户个人偏好。

替代三:会话持久化(最简单的"记忆")

# 会话结束存,开始时读
save_session(id, messages)
messages = load_session(id) if session_id else []

成本:一次 IO。
收益:解决"关掉重开就忘了"。

适用:需要跨会话续接,但不需要"跨任务检索"。

三种替代 vs MemGPT 式

方案 成本 解决
状态栏 极低 单次任务内不忘
CLAUDE.md 极低 项目知识常驻
会话持久化 低 跨会话续接
MemGPT 式 高 跨任务、按需检索

判据:

只是"记住这次" → 状态栏
只是"记住这个项目" → CLAUDE.md
只是"下次还能接着聊" → 会话持久化
要"从半年的历史里找相关的事" → 才需要 MemGPT 式

最后一行才是 MemGPT 的真正适用场景 —— 而绝大多数产品并不需要。


十一、动手:检查点与 MemGPT 的分工

很多人把这两者搞混。它们解决不同的"忘"。

场景 用哪个
任务跑到第 20 轮,怕进程崩 检查点(5.5)
用户换了会话,想问"上月说的事" MemGPT 式检索
长任务中需要回忆"第 3 轮查到的结论" 检查点 + 摘要(5.2)
需要跨任务积累用户画像 长期记忆(6.1)

判据

"忘"的范围:
  本次任务内   → 检查点 / 摘要
  跨会话       → 会话持久化
  跨任务、按需 → 长期记忆 + 检索

一个常见错误

错:用长期记忆存"当前进度"
后果:进度是临时的,存进长期库会污染(6.3)

进度属于检查点,不属于长期记忆。 前者是"任务状态",后者是"用户事实"。

三者的协作

任务开始:从长期记忆检索相关事实(6.1)
任务过程:进度写检查点(5.5)
任务结束:确认的事实写长期记忆(6.4)

三条线各走各的,不混用。


十二、动手:懒检索——什么时候不该检索

6.2 讲的 MemGPT 是"主动检索"。但每次都检索也有代价。

三种不该检索的情况

情况 为什么
问题完全在上下文里 检索只会引入噪声
明显是闲聊("你好") 无信息需求
刚才已经检索过同样内容 重复

一个判断函数

def should_retrieve(query, context, last_searches):
    # ① 上下文里已有答案?
    if answer_in_context(query, context):
        return False
    # ② 闲聊?
    if is_smalltalk(query):
        return False
    # ③ 最近刚搜过?
    if similar_to_recent(query, last_searches, threshold=0.9):
        return False
    return True

收益与代价

每次都检索 按需检索
延迟 每次都 +100ms 只在需要时
成本 每次都多一轮 少
漏检风险 低 有一点

判据:

任务是否需要"外部事实"?
  需要 → 检索
  上下文里有 → 不检索

"按需检索"是 Agent 化的关键一步 —— 它把检索从"固定流程"变成了"模型判断"(4.5 讲的路由思想)。

参考这个模式:把 memory_search 做成工具而不是固定步骤,模型自己决定什么时候调(6.2 的实现就是这样)。


十三、下一篇

MemGPT 是一套完整的架构。但在实际开发中,你往往从更简单的东西开始——比如 ChatMemory。

从最简单的"记住最近几轮",到生产级的上下文管理,中间有一段很长的演进。下一篇讲这段演进路径。

一句话收尾

MemGPT 的思路值得学,但不必照搬。 学它的"分层 + 按需",用你实际需要的复杂度 —— 多数产品用状态栏加会话持久化就够了。

6.2 MemGPT 思路:把上下文当内存管理
https://clxhxhhr.top/posts/4893/
作者
clxstart
发布于
2026-10-25
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。