AI学习吧
📍 源码七号站 开源解码 给 AI Agent 装上"分层记忆":从上下文工程到 L0–L3 语义金字塔的完整拆解

给 AI Agent 装上"分层记忆":从上下文工程到 L0–L3 语义金字塔的完整拆解

摘要:Agent老是“失忆”不是记不住,而是记忆被拍平成了碎片。腾讯云开源的TencentDB Agent Memory用“分层蒸馏”破解:长期记忆从原始对话→原子事实→场景块→用户画像逐层提炼,短期记忆用Mermaid符号图把几十万Token的工具日志卸载到外部文件,上下文只留轻量地图。这套方案Token消耗压掉一半以上,长期记忆准确率从48%拉到76%,全程本地可读可追溯。
字号 100%
行距 2.05
当前可见 60% 的内容
本文由 莫潇羽@源码七号站(www.fuyuan7.com)撰写,转载请注明出处。

快速摘要

如果你只想要一句话结论:Agent 老是"失忆",根因不是它记不住,而是我们把记忆做成了一堆平铺的碎片,既塞不下又找不准。解决思路是两件事——长期记忆做"分层蒸馏"(原始对话→原子事实→场景块→用户画像,越往上越抽象、越往下越是证据),短期记忆做"符号化卸载"(把几十万 Token 的工具日志丢到外部文件,上下文里只留一张轻量的 Mermaid 任务图,需要时再按节点 ID 钻回原文)。这套打法在公开评测里把 Token 消耗压掉一半以上,长期记忆准确率从 48% 拉到 76%,而且全程本地存储、可读可追溯。 这套思路我最近在腾讯云数据库团队开源的 TencentDB Agent Memory 上验证了一遍,也顺手把背后的工程原理整理成了这篇长文。

想看完整拆解,往下翻。

一、Agent 为什么总在"失忆",这件事到底亏在哪

只要你真用 Agent 做过一个稍微长一点的项目,下面这个场景应该不陌生。

我自己折腾下来,第一次接手一个新仓库,光是把背景交代清楚就要花掉小半天:技术栈是 TypeScript,测试文件统一放在 __tests__ 目录下,提交信息要走约定式提交,注释别写一大坨、能短则短,还有一堆历史上踩过的坑要提前打招呼。交代完这些,前半程配合得相当顺,任务推进也快。可一旦我关掉当前窗口、第二天新开一个会话,那种熟悉的崩溃感就来了——前面说过的全忘干净,又得从头再讲一遍。

这种"每天重新认识一次"的循环,表面上只是体验糟糕,实际上是在持续地烧钱、烧时间。你和 Agent 协作过程中沉淀下来的那些东西:确认过的偏好、跑通过的流程、被坑过一次记下来的注意事项,本来应该越攒越厚、越用越省事,结果会话一结束就全部清零。

我后来想明白一件事:Agent 真正稀缺的不是参数量,而是经验的连续性。 模型本身是"无状态"的——这里的"状态"指的是对话历史、你给它定的规矩、它干到一半的任务进度这些信息。模型自己不会主动把这些东西存下来,它能看到什么,完全取决于应用层这一轮往上下文里塞了什么。换句话说,模型每一次睁开眼,看到的世界都是我们临时拼给它的。 拼得好,它表现得像个老搭档;拼得糟,它就是个失忆的新人。

随着 Agent 被塞进越来越多的真实业务里,这种失忆造成的损耗就不再是"偶尔重说两句"那么轻描淡写了。它变成了一项实打实的、可以折算成工时的成本。你每天重复交代的那几段话,乘以团队人数,再乘以一年的工作日,账算下来相当吓人。

这也是为什么这一两年,圈子里对"上下文工程"(Context Engineering,简单说就是研究"该给模型喂什么信息、怎么组织这些信息"的方法论)的讨论越来越密集。大家慢慢达成了一个共识:喂给模型的信息结构本身,正在变得和模型能力一样关键。 一个能力很强的模型,如果每次都只能看到残缺、混乱的上下文,照样发挥不出来。

顺着这个共识再往前走一步,就会得到一个更具体的结论:AI 的记忆层,正在从"可有可无的插件"变成"Agent 架构里绕不过去的地基"。早期大家觉得记忆是锦上添花,现在越来越多的人意识到,没有一套像样的记忆系统,Agent 根本撑不起长周期、跨会话的真实任务。

正是在这个背景下,腾讯云数据库团队开源了一套专门给 Agent 用的分层记忆引擎——TencentDB Agent Memory。它的项目主页上写得很直白:这套东西的目标不是"让 AI 把所有东西都存下来",而是"让人不必把所有事情都重复交代一遍"。这个定位我个人非常认同,下面这篇文章,我就顺着它的设计思路,把 Agent 记忆这件事从头到尾捋一遍。GitHub 地址我放在文末,感兴趣的可以直接去翻源码。

二、上下文工程到底在解决什么问题

要看懂分层记忆的价值,得先搞清楚它对面站着的是什么。这一节我们把"上下文工程"这个略显抽象的词拆开来讲。

2.1 上下文是模型唯一能"看见"的世界

前面提过模型是无状态的,这一点值得再强调一遍,因为它是后面所有设计的出发点。

你可以把大模型想象成一个记忆力极强、但每次见面都"断片"的专家。它脑子里装着海量的通用知识,可它完全不知道你是谁、之前聊过什么、这个项目有什么特殊约定。它对当下这件事的全部认知,就来自你这一次请求里塞进去的那段文字——也就是"上下文窗口"(Context Window,可以理解为模型一次能读进去的内容上限)里的东西。

所以上下文工程干的活,本质上就是:在这块寸土寸金的上下文窗口里,决定放什么、不放什么、怎么放。 它管的不只是"检索什么内容",还包括怎么把检索来的信息、用户的当前问题、以及给模型的行为指令,三者高效地拼成一个让模型一看就懂的最终输入。

2.2 长上下文不是免费的:三种典型病症

很多人有个朴素的想法:现在模型上下文窗口都几十万 Token 了,那我把历史全塞进去不就完事了?

这个想法对短对话确实管用,但在长任务里会撞上三堵墙。业界给这几种病症起了专门的名字,我用大白话翻译一下:

  • 上下文中毒(Context Poisoning):上下文里混进了错误或误导性的信息,而模型会把它当真,顺着错的往下推,越错越离谱。
  • 上下文混淆(Context Confusion):信息塞得太多太杂,模型的注意力被稀释,反而抓不住真正关键的那几条,性能不升反降。
  • 上下文腐烂(Context Rot):随着内容越堆越长、时间越拖越久,模型在长上下文里的表现会持续衰减,前面的信息像是慢慢"烂掉"了。

这三个词背后是同一件事:上下文不是越多越好,信息密度和结构比绝对数量更重要。 你往窗口里硬塞十万 Token 的聊天记录,模型真正用得上的可能就那么几百 Token,剩下的全是噪声,还得为这些噪声付 Token 的钱、扛注意力的衰减。

我自己做过一个很笨但很说明问题的对比:同一个任务,一次把完整历史全喂进去,一次只喂精心挑过的关键信息。结果不光是后者更省钱,连回答质量都更高——因为前者那一大坨历史里,混着大量和当前问题无关的旧对话,模型被这些东西干扰,反而把真正要紧的那几条给"看漏"了。这个结果第一次见到时还挺反直觉的,按常理"信息越全应该越准"才对。但模型的注意力是有限资源,你给它的无关信息越多,它分给关键信息的注意力就越少。喂得多,不等于喂得对。 这件事想通之后,我对"上下文该精挑细选"这个原则就再没怀疑过。

2.3 写、选、压、隔:上下文工程的四个动作

业界把上下文工程的核心操作大致归纳成四个字:写、选、压、隔。我觉得这个概括挺到位,顺手解释一下:

动作

在干什么

一句话理解

写(Write)

把有价值的信息沉淀到上下文窗口之外

该记的先存下来,别占着窗口

选(Select)

在需要时把相关信息精准捞回来

用什么捞什么,别一股脑全倒进去

压(Compress)

把冗长内容压缩成高密度表达

同样的意思,用更少的 Token 说清

隔(Isolate)

把不同性质的信息分开管理

偏好归偏好、任务归任务,别混

你会发现,记忆系统几乎天然就是上下文工程的承载体。 "写"对应着记忆的存储,"选"对应着记忆的召回,"压"对应着对历史的压缩,"隔"对应着对不同类型记忆的分层管理。后面要讲的 TencentDB Agent Memory,本质上就是把这四个动作做成了一套可工程化的系统。

把这层关系理顺之后,再看分层记忆的设计,就不会觉得是凭空冒出来的花活了——它是在认真回答"写选压隔到底该怎么落地"这个问题。这也是莫潇羽我自己读这套源码时最大的感受:好的架构,往往是把一个抽象方法论,老老实实翻译成了可以跑起来的代码。

三、暴力堆历史 vs 暴力摘要:两条看着像捷径的死路

知道了长上下文的三种病症,接下来就该看看大家曾经尝试过哪些"土办法",又是怎么一个个被现实打脸的。理解了这些弯路,才能真正明白分层记忆好在哪。

3.1 第一条路:把历史全塞回去

这是最直觉、也最常见的做法——既然怕忘,那就别让它忘,每一轮都把过去的完整对话原封不动地灌进上下文。

短对话里这招确实有效,几轮下来信息量也就那么点,塞得下、也不乱。可一旦进入长线复杂任务,它的毛病就藏不住了,集中体现在三点:

  • 跨会话断裂:上下文窗口只在单次会话内有效,会话一关,里面的东西就没了。下次重开,历史根本不在窗口里——这等于压根没有记忆,只是把"失忆"推迟到了关窗口那一刻。
  • 事实与偏好混为一谈:"我习惯用 TypeScript"和"帮我查下今天的天气",这两句话的性质天差地别。前者是应该长期保留的稳定偏好,后者是用完即弃的一次性请求。可在"全塞回去"的方案里,它俩待遇完全一样,都老老实实占着窗口。
  • 上下文持续膨胀:任务拖得越久,历史越长,Token 成本就线性往上涨,模型的注意力还会随之衰减。到后面你会发现,钱花得越来越多,效果却越来越差,性价比一路下滑。

3.2 第二条路:把历史压成一段摘要

既然全塞进去不行,那就压一压——很多方案接着提出了"长上下文压缩",做法是把一大段历史交给模型,让它总结成一小段摘要,之后只带着摘要往下走。

这招省 Token 是真省,但它有个致命的隐患:传统摘要是有损的,而且不可逆。 你把十条细节压成一句话,那一句话里丢掉的九成信息,就再也找不回来了。平时看不出问题,可一旦后面出了岔子,你想回溯根因,会发现证据早在压缩那一步就被丢掉了。这时候 AI 也只能跟着猜,你也只能跟着它一起猜,整个排查过程毫无抓手。

我自己踩过这个坑:一个长任务跑到后半段出了错,回头想查是哪一步的工具调用返回了异常数据,结果上下文里只剩一句轻飘飘的"已完成数据采集",原始返回早没了。那种"明明知道答案就在某个被我亲手删掉的地方"的无力感,做过运维的应该都懂。

更麻烦的是,摘要的"有损"还会层层叠加。长任务里压缩往往不是只发生一次,而是每隔一段就压一轮。第一轮压掉一些细节,第二轮在已经失真的内容上再压一次,几轮下来,上下文里剩的可能已经是"摘要的摘要的摘要",离原始事实差出十万八千里。等你回头想核对,会发现连"它是基于什么得出这个结论的"都说不清了。我把这种现象叫"信息的复印件效应"——复印件再复印一次,字迹就糊一分,复印够多次,整张纸就只剩个大概轮廓。指望从一张糊掉的复印件里还原原稿,本身就是不现实的。

3.3 问题的真正症结:记忆被"拍平"了

把这两条路放在一起看,会发现它们其实犯了同一个错误:都把记忆当成了一个没有层次的平面。

全塞回去,是把所有信息平铺在上下文里,不分主次;暴力摘要,是把所有信息压成同一层的一段话,不留证据。前者太重,后者太损,但它们共享同一个隐含假设——记忆是扁平的,要么全要,要么全不要。

向量数据库(一种按"语义相似度"来存取信息的数据库,可以把每段文字变成一串数字坐标,再按坐标远近找相似内容)方案其实也没逃出这个框。它把对话切成一段段碎片,统统丢进同一个向量空间里。结果就是"我喜欢用 TypeScript"和"我昨天问了天气",在这个空间里地位完全平等。召回的时候,AI 只能靠相似度去碰运气,头顶上没有任何宏观结构来给它指方向。

想通了这一层,下一步的方向就很清楚了:别再拍平它,给记忆建立层次。 这正是下一章要讲的核心思想。

四、分层记忆的核心思想:拒绝平铺,走向层次

如果让我用一句话概括 TencentDB Agent Memory 的设计哲学,那就是:分层蒸馏,而不是平铺堆积。

4.1 一个生活化的类比

我喜欢用"认识一个人"来类比这件事。

你和一个新同事相处,刚开始记的全是具体的事:"他上周三说测试要放在 __tests__ 目录""他那次因为漏写类型声明返工了"。这些是一条条孤立的事实。相处久了,你会自动把这些事实归纳成场景:"在代码规范这件事上,他比较较真""涉及类型安全,他宁可多写也不省"。再久一点,你脑子里会浮现出一个稳定的整体印象:"这是个工程素养很高、偏保守、注重可维护性的人"。

注意这个过程:从具体事实,到场景归纳,再到整体画像,信息是一层层往上抽象的,越往上越精炼、越稳定,越往下越琐碎、越具体。 而且关键是,上层的印象并没有把下层的事实抹掉——你需要时,依然能想起"哦对,就是上周三那次"。

人脑天然就是这么管理记忆的。TencentDB Agent Memory 干的事,本质上就是把这套"层层蒸馏、上下贯通"的机制,工程化地搬给了 Agent。

4.2 两条主线:长期分层 + 短期符号化

具体到设计上,这套系统把记忆拆成了两条互不干扰的主线,分别对付两类完全不同的问题:

  • 长期记忆:解决"跨会话的经验沉淀"。它建了一座四层的语义金字塔(L0→L3),把碎片化的对话层层提炼成稳定的用户画像。这条线我们在第五章细讲。
  • 短期记忆:解决"单次长任务里的信息过载"。它用一种叫"符号化记忆"的办法,把一次任务里产生的海量工具日志卸载到外部,上下文里只留一张极轻量的任务地图。这条线放在第六章。

之所以要分成两条线,是因为它们要解决的矛盾根本不一样。长期记忆的核心矛盾是"如何跨越时间,把有价值的东西攒下来";短期记忆的核心矛盾是"如何在一次任务内,不被自己产生的中间垃圾撑爆"。一个面向时间的纵深,一个面向单次任务的宽度,用同一套机制硬怼是怼不好的。

4.3 统一的设计哲学:分层无处不在

有意思的是,虽然两条线场景不同,但它们遵循的是同一条设计哲学——不管是长期知识、短期任务,还是未来要做的"技能沉淀",记忆都不应该平铺,生成和召回都必须有层次。

按官方 Roadmap 的说法,这套分层思路接下来还要延伸到"动作域":从底层的执行轨迹和报错日志里,中层归纳出共性的解决套路,高层最终提炼成可以直接挂载复用的技能或标准操作流程。换句话说,记忆不该只停留在"知道什么",还该往"会做什么"上长。这个方向我个人挺期待,相当于让 Agent 不光记住你的偏好,还能把"怎么干成一件事"的经验也固化下来。

把"分层"这个词立成整个架构的统一信条,是我觉得这套设计最聪明的地方。它不是东一榔头西一棒子地打补丁,而是认准一个原则,然后在每个子系统里贯彻到底。下面两章,我们就分别钻进这两条主线,看看"分层"具体是怎么落地的。

五、长期记忆:L0→L3 语义金字塔逐层拆解

这一章是整篇文章的硬核部分,我们把长期记忆那座四层金字塔从地基讲到塔尖。

5.1 四层结构总览

先给一张全景图,把四层是什么、各自存什么,一次性说清楚:

层级

名称

存的是什么

类比

L0

Conversation 原始对话

完整保留的原始对话记录

最底层的"原始档案"

L1

Atom 原子事实

从对话里抽出的结构化事实

一条条独立的"便签"

L2

Scenario 场景块

把相关事实聚类成的场景

归好类的"文件夹"

L3

Persona 用户画像

持续蒸馏出的稳定画像

关于你的"一页纸简介"

这四层的关系,可以用一句话记住:从下往上是"蒸馏",从上往下是"溯源"。 越往上越抽象、信息密度越高;越往下越原始、证据越完整。

下面这张图把蒸馏的方向画出来了:

graph BT
    L0["L0 · Conversation<br/>原始对话全量保留"]
    L1["L1 · Atom<br/>抽取原子事实"]
    L2["L2 · Scenario<br/>聚类成场景块"]
    L3["L3 · Persona<br/>蒸馏出用户画像"]

    L0 -->|"提取事实"| L1
    L1 -->|"按场景聚类"| L2
    L2 -->|"持续蒸馏"| L3

    L3 -.->|"需要细节时下钻"| L2
    L2 -.->|"继续下钻"| L1
    L1 -.->|"回到原文"| L0

    style L3 fill:#fffbeb,stroke:#f59e0b,stroke-width:2px
    style L2 fill:#eff6ff,stroke:#3b82f6
    style L1 fill:#f0fdf4,stroke:#22c55e
    style L0 fill:#f8fafc,stroke:#cbd5e1

5.2 L0:原始对话,证据的最后防线

L0 是地基,它干的事最简单也最重要——把原始对话完整地留下来,一个字不丢。

为什么底层一定要全量保留?因为它是整套系统"可追溯、可恢复"的最后一道保险。上面几层无论怎么抽象、怎么压缩,只要 L0 还在,任何一条结论都能回到它最初的出处去核对。这就从根上避开了第三章说的"暴力摘要不可逆"的坑——这里没有任何一段抽象是黑盒,全都能往回查。

5.3 L1:原子事实,把对话拆成可检索的便签

L1 在 L0 之上,负责把流水账一样的原始对话,自动提取成一条条独立的"原子事实"。

所谓原子事实,就是那种不可再拆、含义自足的小信息块。比如从一段对话里,它可能抽出这么几条:

  • 代码偏好:习惯用 TypeScript,注释从简
  • 踩坑记录:漏写类型声明导致过一次返工
  • 工作约定:测试文件统一放 __tests__ 目录

你看,这就比一整段聊天记录"可用"多了。每条事实都干净、独立、好检索。系统在提取时还会做去重和冲突检测——如果你前后两次说的偏好打架了,它能识别出来,而不是傻乎乎地两条都存着。

我个人很看重这一层,因为它是"把混沌对话变成结构化资产"的第一道工序。原始对话对机器来说是高噪声的,只有先拆成原子事实,后面的归纳和召回才有干净的原料。

5.4 L2:场景块,把零散事实归类成场景

光有一堆便签还不够,便签多了照样乱。L2 的活,就是把相关的原子事实聚类成"场景块"。

继续用上面的例子:那几条关于代码风格、类型安全、目录约定的事实,会被归到一个类似"工程规范偏好"的场景块里。下次 Agent 遇到和写代码相关的任务,直接调出这个场景块,就能一次性拿到一整组相关偏好,而不是在一堆零散便签里东拼西凑。

这一层的价值在于"宏观视角"。零散事实回答的是"他说过什么",场景块回答的是"在某一类事情上,他大概是什么取向"。后者才是真正能指导 Agent 行为的东西。

这里还藏着一个容易被忽略的好处:场景块的存在,让记忆有了"抗干扰"的能力。单条事实是脆弱的,今天你随口说一句反话,明天它可能就把这条孤立事实当真了。但当一堆事实被归到同一个场景里互相印证,偶尔一两条噪声就很难带偏整体判断——就像你判断一个人的性格,不会因为他某天心情不好说了句重话,就全盘推翻之前几个月攒下的印象。场景块这一层,相当于给记忆加了一层"多数表决"的稳健性,让 Agent 的理解不至于被个别异常数据牵着走。

5.5 L3:用户画像,塔尖那张"一页纸简介"

金字塔的塔尖是 L3——持续蒸馏出来的稳定用户画像。

它把各个场景块再往上提炼一层,形成一个关于"你是个什么样的人"的整体描述。Agent 平时干活,主要就靠这张画像来把握大方向:你的代码风格、你的沟通偏好、你的长期目标。只有当它需要核对某个具体细节时,才会顺着金字塔往下钻。

这里有一个让我印象特别深的细节:这张画像是以一个叫 persona.md 的可读文件存在本地的。 也就是说,你随时可以打开这个文件,直接看到 Agent 到底把你"记成了"什么样的人。这种透明度在很多记忆系统里是看不到的——大多数方案里,"AI 眼中的你"是一团没法直视的向量,而这里它就是一份你能逐字读、甚至能手动改的 Markdown。莫潇羽我第一次打开 persona.md 的时候,那种"原来它是这么理解我的"的感觉还挺奇妙的。

5.6 上层给方向,下层留证据

把四层串起来,整套长期记忆的运作逻辑就清晰了:

Agent 先从 L3 画像拿到大方向,需要更多细节时再逐层往下钻;一旦出了问题,又能沿着 L3→L2→L1→L0 这条链路一路回溯到原始对话。

上层给的是方向,下层留的是证据。 这一句话,基本就是整座金字塔的精髓。它同时解决了两个老大难:召回时有宏观结构指引,不再靠相似度碰运气;出错时有完整证据链,不再对着向量分数干瞪眼。

六、短期记忆:Mermaid 符号画布与上下文卸载

讲完面向时间的长期记忆,再来看面向单次任务的短期记忆。这一块解决的是另一个让人头疼的问题:长任务自己产生的中间垃圾,会把上下文活活撑爆。

6.1 问题:工具日志才是 Token 黑洞

Agent 干长任务时,会频繁调用各种工具——搜索、跑代码、读文件,每一步都会吐出一大坨中间输出:搜索结果、代码日志、报错堆栈……

这些东西有个共同特点:单条就可能几千上万 Token,叠起来动辄几十万。 如果一股脑全堆在上下文里,用不了几步就会顶到窗口上限。可这些日志又不能直接扔——万一后面某一步出错,你还得回头翻它们查根因。

这就形成了一个两难:留着,撑爆上下文;扔了,丢掉证据。第三章那条"暴力摘要"的死路,在这里又一次摆在面前。

6.2 解法:把原文卸载,上下文只留符号图

TencentDB Agent Memory 的破局思路叫"符号化记忆",配合"上下文卸载"(Context Offloading)一起用。拆开看是三步:

  1. 卸载原文:把每次工具调用的完整输出,整段保存到外部文件系统里,路径形如 refs/xxx.md。原文一个字不动,全留着。
  2. 提取关系:从这些日志里抽出任务的状态流转,画成一张 Mermaid 图。Mermaid 是一种用纯文本描述流程图、状态图的轻量语法,既能被模型精确解析,也方便人直接看懂——不像 JSON 那样读起来费劲,也不像纯文本摘要那样容易丢结构。
  3. 轻量注入:上下文里只放这张 Mermaid 任务地图。原本几十万 Token 的日志,被压缩成了几百 Token 的符号图。

整个流程画出来是这样:

graph LR
    Log["繁杂的工具日志<br/>(几十万 Token)"] -->|"1.卸载完整原文"| FS[("外部文件<br/>refs/xxx.md")]
    Log -->|"2.提取关系"| MMD["Mermaid 任务图<br/>(每个节点带 node_id)"]
    MMD -->|"3.轻量注入"| Agent(("Agent 上下文<br/>(几百 Token)"))
    Agent -. "4.按 node_id 随时钻回原文" .-> FS

    style Log fill:#f1f5f9,stroke:#94a3b8,stroke-dasharray: 5 5
    style FS fill:#f8fafc,stroke:#cbd5e1
    style MMD fill:#eff6ff,stroke:#3b82f6,stroke-width:2px
    style Agent fill:#fffbeb,stroke:#f59e0b,stroke-width:2px

6.3 关键:node_id 撑起的可追溯性

这套设计最妙的一环,是图上每个节点都带一个 node_id

Agent 平时就盯着这张轻量的符号图做推理,省下了海量 Token。可一旦它需要核对某一步的细节,只要拿着对应节点的 node_id,去外部文件里一搜(grep 一下就行),就能瞬间把那段完整原文捞回来。

于是短期记忆也拿到了和长期记忆一样的好处:既能折叠,也能展开;既大幅降本,又保住了 100% 的可追溯性。 你不用在"省钱"和"留证据"之间二选一,两个都要得到了。

我特别想强调这一点的分量,因为"二选一"才是这类问题最常见的妥协姿态。绝大多数压缩方案,省 Token 的代价就是丢证据,二者像跷跷板一样此消彼长,你只能在中间找个自己能忍的平衡点。而 node_id 这套机制的巧妙之处,恰恰是把这个跷跷板拆掉了——上下文里只留极轻的符号,原文一字不少地躺在外部文件里,两者靠一个 ID 牢牢拴着。需要省的时候省到极致,需要查的时候一查就有。把一个看似必须取舍的矛盾,硬是变成了"我全都要",这种设计上的"不将就",是我读到这块时最佩服的地方。

6.4 为什么偏偏选 Mermaid

可能有人会问:压缩成 JSON 行不行?压成一段文字摘要行不行?

这俩都试过,效果都不理想。JSON 结构是清晰,但人读起来很累,密密麻麻一堆括号引号;纯文本摘要人是好读了,可结构信息全糊在一起,模型解析时容易丢掉节点之间的拓扑关系。

Mermaid 恰好卡在中间那个甜点位:它用极少的符号表达了很强的拓扑结构(谁连着谁、谁依赖谁一目了然),LLM 能精准解析,人也能扫一眼就看懂任务进行到哪了。用最少的符号,表达最多的语义。 这就是"符号化记忆"这个名字的由来。我自己的体会是,能同时讨好"机器解析"和"人类阅读"这两个常常打架的需求,Mermaid 在这个场景里确实是个挺优雅的选择。

七、渐进式披露与异构存储:低层留证据,高层留结构

讲完两条主线,这一章把它们背后那套共用的存储设计单独拎出来说,因为它直接决定了整套系统好不好用、好不好查。

7.1 渐进式披露:默认只看摘要,按需才下钻

"渐进式披露"(Progressive Disclosure)这个词听着玄乎,其实道理很朴素:默认情况下,只给你看最精炼的那层;想要细节,你再主动往下要。

放到这套系统里就是:Agent 平时只看 L3 画像、只看 Mermaid 任务图这些高层结构,省时省 Token;只有在"光看摘要不够、需要核对证据"的时候,才顺着链路往下钻到 L1 事实、钻到 refs 原文。

这跟我们查资料的习惯其实一模一样——先看目录和摘要,觉得某块要深究了,再翻到具体那一页。没人会上来就把整本书逐字读一遍,那样既慢又记不住重点。

7.2 异构存储:数据库管全量,文件系统管可读

支撑这套披露逻辑的,是一套"异构存储"方案——简单说就是不同性质的数据,放在不同性质的存储里,各司其职:

层次

存什么

存在哪

图什么

低层

海量事实、日志、轨迹

数据库 / 归档文件

稳定、能全量检索

高层

画像、场景、画布

业务可读的文件系统(Markdown)

信息密度高、逻辑清晰、可白盒调

一句话概括它的取舍:低层保留证据,高层保留结构。

低层那些又多又杂的原始数据,扔进数据库最合适——稳定、扛得住量、检索快。而高层那些需要人能直接读、甚至直接改的画像和场景,做成 Markdown 文件最舒服——打开就能看,看不顺眼还能手动调。

这种"分而治之"的取舍,背后其实是承认了一个现实:没有哪一种存储能同时满足所有需求。数据库擅长稳定地装海量结构化数据、做高速检索,但你没法像读文章一样直接读它;文件系统读写直观、白盒透明,可一旦数据量大起来、要做复杂检索,它就力不从心。与其硬选一个、然后到处打补丁,不如让两者各干各擅长的活:底层用数据库扛量与检索,上层用文件系统保可读与可调。 这种不追求"一招鲜"、而是按场景配工具的工程审美,我个人是很买账的。很多系统的复杂度失控,恰恰就是因为不肯承认"一种方案搞不定所有事",非要用一把锤子敲所有钉子。

7.3 100% 可找回,没有不可逆的黑盒

把渐进式披露和异构存储合在一起,就得到了这套系统最让我安心的一个特性:每一条信息都 100% 可找回、可恢复。

压缩和抽象最大的风险,永远是"省了 Token,也丢了证据"。但因为有一套严格的索引映射机制兜底,这套系统里没有任何一段摘要是不可逆的黑盒。无论是短期记忆里被卸载的一段报错日志,还是长期记忆里总结出的一条偏好,你都能沿着"高层符号(画像/画布)→ 中层索引(场景/JSONL)→ 底层原文(原始对话/refs)"这条链路,完整地回溯和还原。

我把这一条单独拎出来强调,是因为它在生产环境里的分量,

🔒
该内容仅对更高等级社区用户开放
请谨慎解锁时效性强且发布日期较早的文章
您当前:游客 · 可见 60% 内容 · 升级至 注册用户 可见 70%
👀
游客
可见 60%
✓ 当前
注册用户
注册用户
可见 70%
社区精英
社区精英
可见 100%
社区守护
社区守护
可见 100%
仅解锁本文,永久有效。如需PDF珍藏版,请联系站长获取。 当前单篇价格 ¥8
✏️ 发表评论

请先登录后发表评论

前往登录
📊 站点统计
今日发布1 篇
文章总数1301 篇
昨日发布1 篇
本月发布12 篇
建站时间414 天
🔍 搜索
📅 日历
« 2026 » « 09 »
 123456
78910111213
14151617181920
21222324252627
282930    
站长微语

联系站长

QQ:2805463528
AIGC 技术社区
致力于解码 AI前沿技术 与经验分享
纯粹的技术交流社区

💡 欢迎您的建议与反馈,让社区变得更好

快速通道
联系站长
站长QQ二维码
AI交流群
AI交流群
仍在路上

那些寒夜里追赶过的方向

那些冷眼下没放弃的理想

一篇一篇写到现在

仍在路上

"不羁放纵爱自由"

—— 致敬 Beyond
持续创作中 莫潇羽 · 源码七号站