在之前的文章中,我探讨了在与AI智能体协作时,角色设定为何仍然重要。不同的视角能以原始上下文无法复制的方式影响输出。但我也提出了一个需要正面解决的局限:每一个全新的上下文窗口都是从零开始的。角色设定每次都需要从头重建对你代码库的理解。

这不仅仅是一个不便之处,而是一个结构性问题。如果每次会话都从白板开始,你的智能体会花费大量代币去重新发现它们已经知道的东西。它们会扫描已经读过的文件,会推断已经被告知的约定。你的代码库越复杂,这个问题就越严重。它无法扩展。

那么,如何在不淹没在上下文中的前提下,赋予智能体持久性的理解呢?

让我用一个类比开始。想想你如何使用百科全书。你不会为了找到一个事实而从头读到尾。你会去查索引,查找你的词条,然后直接跳到正确的页面。如果确切的词条没有列出,你会浏览附近的条目寻找相关概念,然后再次尝试。索引本身并不包含知识,它告诉你知识在哪里。而“持有所有信息”与“知道去哪里查找”之间的区别,恰恰是大多数人在为AI智能体设置记忆时搞错的地方。

本文旨在将智能体记忆视为你对待数据库的方式。它不是一个你可以倾倒智能体可能需要的一切信息的垃圾场,而是一个结构化的、可查询的系统,能够在正确的时间检索到正确的信息。因为,一个原地打转的智能体与一个精准行动的智能体之间的区别,很少在于智能本身,而在于导航能力。

问题:上下文污染

大多数人在与AI智能体合作时的本能是给它们更多。更多文档、更多文件、更多历史。其推理很直接:如果模型能访问一切,它就应该能找出什么是相关的。表面上看,这说得通。更多数据,更好决策。

但这正是数据库类比开始适用的地方。想象一个没有索引、没有查询优化、没有模式的数据库。你将每一条记录都倾倒进一个单一的表中,然后希望在你需要时正确的行会出现。技术上,所有信息都在那里。但实际上,你的查询很慢,结果充满噪音,系统将大部分资源浪费在筛选与当前问题无关的数据上。

这正是当你超载智能体上下文时发生的情况。模型并不会神奇地聚焦在三个关键文件上。它会处理你给它的所有信息,根据任务衡量每一条信息。你引入的噪音越多,模型识别出信号就越困难。我听到你在想:“但模型足够聪明,可以过滤。” 某种程度上是的。但过滤是有代价的。模型需要评估的每一个无关段落,都在与相关段落争夺注意力。

用机器学习术语来说,你是在让智能体在上下文上过拟合。你给了它太多数据点,以至于它开始将噪音视为信号。结果不是得到一个更聪明的智能体,而是一个犹豫不决的、每个表述都加限定语的、试图处理那些本不该被给予的信息的智能体。正是因为输入太宽泛,输出才变得泛泛而谈。

相反的极端同样有问题。不给智能体任何持久化的上下文,它每次会话开始时对你的代码库来说都是陌生人。它会问你已经回答过的问题。它会做出与你数周前就确定的决定相矛盾的假设。它生成的代码技术上正确,但风格上与周围的一切都不一致。最终,你花费在纠正智能体上的时间比你亲自写代码还要多。

最佳点在于两者之间。不是所有,也不是全无。而是结构化的、相关的、可导航的上下文,它能给智能体恰好需要的东西来定位自己,而不会将它淹没在不必要的信息中。问题是如何构建它。有点像给你的AI做一个代码库谷歌搜索。

记忆作为一个松耦合的数据库

如果你退一步,审视智能体记忆的实际作用,你会发现它与数据库概念惊人地吻合:

  • 存储 — 信息存放的地方
  • 检索 — 智能体如何找到所需信息
  • 结构 — 信息如何组织以便高效检索
  • 范围 — 哪些信息被存储,哪些被排除在外

我们首先需要这个的原因很实际:你目前还不能将整个代码库塞进LLM的上下文窗口中。但即使你可以,也解决不了问题。正如我们在上一节提到的,更多上下文并不意味着更好的上下文。在任何一个非平凡的项目中,一个包含整个代码库的智能体仍然会遭受上下文污染。信噪比会让针对特定任务的推理变得更难,而不是更容易。

在传统数据库中,你不会将所有可能的数据存储在一个单一的无结构大对象中。你会设计一个模式。你会定义表、关系和索引。你会思考你需要支持哪些查询,并针对这些访问模式进行优化。模式不是开销,它是数据库有用的原因。

智能体记忆以同样的方式工作。“数据库”是你的智能体可以访问的文件集合。“模式”是这些文件的结构和命名方式。“索引”是告诉智能体去哪里查找的参考文档。“查询”则是触发智能体检索特定信息的提示和指令。

不同之处在于,智能体记忆不需要关系型数据库的刚性。你不是在写SQL。你不需要外键或规范化。你需要的是半结构化数据。足够结构化以便导航,足够灵活以适应项目变化。

这就是为什么Markdown文件成为一个自然的选择。它们是人类可读的,意味着你无需额外工具就能维护它们。它们是可解析的,意味着智能体可以可靠地从它们中提取信息。而且因为它们是使用自然语言编写的,它们直接契合大型语言模型的工作方式。这些模型的核心是词预测器。自然语言格式的半结构化文本正是它们被优化来进行推理的输入类型。JSON模式可能更精确,但一个精心编写的Markdown文件在机器可解析和模型友好之间达到了最佳点。最重要的是,它们通过标题、列表和前置数据提供了足够的结构来组织信息,而无需强加一个僵化的模式。

让我列举一个肯定不全面的列表,说明这在实践中是什么样子:

  • 项目上下文文件 — 项目是什么、关键约定是什么、做了哪些决定。这相当于你数据库的主参考表。
  • 索引文件 — 指向特定信息所在位置的指针。不是信息本身,只是位置。就像一个将键映射到行的数据库索引。
  • 术语表文件 — 领域特定术语及其定义。这消除了歧义,否则智能体会花费代币去推断或猜测。
  • 决策日志 — 为什么做出某些架构或设计选择。这可以防止智能体重新争论已经解决的决定。

这些文件都不需要很大。一个好的索引文件可能只有30行。一个术语表可能有20个条目。其价值不在于你存储了多少信息,而在于你使多少信息能被精确检索。

因此,智能体记忆不是要给模型一个对整个代码库的过目不忘的记忆。而是要构建一个轻量级的、可查询的层,让智能体能够带着意图而不是蛮力来导航。

抽象层

如果你用过任何现代Web框架,你可能用过ORM(对象关系映射)。ORM位于你的应用程序代码和数据库之间。你不用为每个查询写原始SQL,而是与将你的意图转换为数据库操作的对象和方法交互。ORM抽象掉了底层系统的复杂性,这样你就可以专注于你想要做的事情,而不是存储引擎如何工作。

智能体记忆遵循相同的模式。“数据库”是你的代码库、你的文件系统、你的项目历史。原始数据都在那里。但一个直接与这些原始数据交互的智能体,就像为每个操作编写原始SQL一样。它能工作,但速度慢、容易出错,并且迫使智能体处理与当前任务无关的复杂性。

记忆层,即你的Markdown文件、索引、术语表,扮演着ORM的角色。它在智能体和底层复杂性之间提供了一个干净的接口。智能体不用扫描src/下的每个文件来理解项目是做什么的,而是读取一个告诉它这些信息的参考文档。它不用从散落在十二个文件中的上下文线索来推断“DRS”是什么意思,而是查阅术语表。它不用猜测哪个模块处理身份验证,而是去索引中查找。

这不仅仅是为了方便。它是智能体如何花费其代币的根本性转变。没有抽象层,智能体的认知预算花在导航上:查找文件、推断结构、从零开始构建心智模型。有了抽象层,这份预算就花在了实际任务上:编写代码、审查架构、发现错误。

这么说吧。你的智能体花费在弄清楚东西在哪里的每一个代币,都是它本可以用来弄清楚如何处理它们上的代币。抽象层正是将平衡从导航转向执行的关键。

这听起来可能是一个应用ORM类比奇怪的地方,但如果你想想,其实不然。ORM并没有让数据库变得更简单。数据库仍然存在,带着它所有的复杂性。ORM只是意味着你的应用程序代码不需要关心这种复杂性。智能体记忆做的是同样的事情。你的代码库仍然复杂。记忆层只是意味着你的智能体不需要在每次开始新会话时都重新发现这种复杂性。

索引文件:百科全书模式

好吧,让我们更深入地看看这些参考文件实际长什么样。因为只有当你能在五分钟内实现它并立即看到效果时,这个概念才有用。

最简单也最有效的模式是索引文件。把它想象成你代码库的目录。它不解释事物如何工作,而是用一行话告诉智能体事物在哪里以及它们是做什么的。智能体首先读取这个文件,定位自己,然后直接导航到相关的源文件。

以下是一个现实参考文件的例子:

# REFERENCE.md — 项目索引

## 核心脚本

| 脚本 | 用途 |
|------|------|
| `src/api/server.py` | API入口点,初始化路由和中间件 |
| `src/workers/processor.py` | 后台任务处理器,处理异步任务队列 |
| `src/services/billing.py` | Stripe集成,订阅生命周期管理 |
| `src/services/notifications.py` | 多渠道通知分发(邮件、Slack、Webhook) |
| `src/auth/middleware.py` | JWT验证,基于角色的访问控制 |
| `scripts/migrate.sh` | 数据库迁移运行器,支持回滚 |

## 配置

| 文件 | 用途 |
|------|------|
| `config/settings.yaml` | 特定环境的应用程序配置 |
| `config/permissions.yaml` | 角色定义和资源级访问规则 |
| `.env` | API密钥和机密(不提交) |

## 关键目录

| 目录 | 内容 |
|------|------|
| `src/services/` | 业务逻辑,每个领域一个模块 |
| `src/api/routes/` | 按资源分组的路由处理器 |
| `src/workers/` | 后台作业和定时任务 |
| `migrations/` | 数据库迁移文件,按时间戳排序 |

智能体不需要递归遍历src/来理解项目。它读取这个文件,找到相关条目,然后直接跳转到源代码。如果任务与计费有关,它就去src/services/billing.pyconfig/settings.yaml。如果任务与访问控制有关,它就从src/auth/middleware.pyconfig/permissions.yaml开始。无需猜测,无需扫描。

现在考虑当你的项目使用领域特定术语时会发生什么。每个代码库都有自己的词汇表。缩写、内部名称、在你的上下文中含义非常具体但在通用用法中含义不同的概念。一个智能体第一次遇到这些术语时有两个选择:从周围的代码推断含义,这需要花费代币且有出错的风险;或者查阅术语表。

# GLOSSARY.md — 领域术语

| 术语 | 定义 |
|------|------|
| **租户** | 一个隔离的客户工作区。所有数据都限定在租户范围内。多租户在数据库和API层强制执行。 |
| **席位** | 租户内一个可计费的用户。计费按席位进行,根据套餐分层。 |
| **Webhook 中继** | 将事件扇出到客户注册的 Webhook URL 的内部系统。支持指数退避重试。 |
| **迁移** | 版本化的、有序的数据库架构变更。迁移在生产环境只向前;回滚仅在暂存环境存在。 |
| **作业** | 由工作池处理的异步工作单元。作业通过Redis排队,按优先级等级先进先出处理。 |
| **功能标志** | 用于按租户启用或禁用功能的运行时开关。通过管理API管理,本地缓存。 |

这是六个条目。智能体读它只需要不到一秒钟。但影响是巨大的。没有这个文件,智能体在代码中遇到“中继”时,必须判断:这是指网络中继、事件中继,还是其他完全不同的东西?有了术语表,就没有歧义。这个术语在一个地方被定义一次,智能体就可以继续前进。

这种模式的美妙之处在于,即使索引没有包含智能体正在寻找的确切内容,它仍然能提供价值。扫描参考文件会暴露相关术语、邻近模块和缩小搜索范围的结构模式。这和在百科全书索引中翻阅的体验是一样的。你可能没有找到“事件分发”这个词条,但你看到了“Webhook中继”和“通知”,你已经离你需要的东西更近了。索引将盲搜变成了引导式搜索。

共享记忆,个体视角

在我之前的文章中,我描述了角色设定如何激活同一模型内的不同参考框架。一个安全工程师和一个后端开发人员看着同一个端点,但看到的东西不同。这种机制对于单个任务效果很好。但是,当多个角色设定需要在一个更大的工作上协作时会发生什么?

在一个真实的团队中,这是通过共享上下文来解决的。每个人都可以访问相同的代码库、相同的文档、相同的项目看板。这个共享层是让每个人保持一致的东西。但每个团队成员仍然带来他们自己的专业知识、自己的优先级、自己的心智模型。共享上下文不会让每个人都以同样的方式思考。它给了他们一个共同的起点,从那里可以产生富有成效的分歧。

智能体角色设定的工作方式相同。参考文件、术语表、决策日志——这些构成了共享记忆层。每个角色设定都从同一个事实来源读取。安全工程师知道“租户”是什么意思,因为它在术语表里。架构师知道计费逻辑在哪里,因为它在索引里。集成工程师知道选择了哪种API版本控制策略,因为它在决策日志里。他们都不需要重新发现这些信息。它已经在那里,结构清晰且可访问。

但有趣的是这里。尽管所有角色设定共享同一个记忆层,但它们的使用方式却不同。安全工程师阅读config/permissions.yaml时会考虑权限提升。后端开发人员阅读它时会考虑角色查找的查询性能。架构师阅读它时会考虑当添加新资源类型时权限模型是否还能扩展。同一个文件,同样的信息,不同的视角。共享记忆并没有将多个角色设定扁平化为一个,而是释放了它们去专注于自己最擅长的事情。

这也是结构化文本作为角色设定间通信协议变得至关重要的地方。当一个角色设定的输出需要被另一个角色设定在此基础上构建时,这种交接需要是清晰的。如果架构师将设计决策写成无结构的散文,埋藏在一长段对话中,那么接手它的开发人员就得从段落中解析意图。但是,如果架构师将其写成决策日志中的一个结构化条目,附上背景、考虑的选项和理由,那么开发人员可以在几秒钟内理解并继续前进。

## [已决定] 2026-03-12 — 身份验证策略

**背景:** 需要同时支持集成的API密钥验证和仪表板的基于会话的验证。

**选项:** (A) 统一的中间件处理两者,(B) 每种验证类型使用单独的中间件,(C) 在网关层路由到不同的验证处理器。

**决定:** 选项B — 单独的中间件。

**理由:** 保持每个验证流程独立可测试,并避免随着每种新验证方法的增加而增长的条件分支。对于当前规模,网关路由(C)过于复杂。

这不仅仅是文档。这是智能体与智能体之间的通信。架构师角色设定了这个。开发人员角色设定消费它。安全人员角色设定审查它。每一个都从一个结构化的、可预测的格式中获得他们所需的确切信息。没有歧义,无需重新解读,不浪费代币去弄清楚决定是什么以及为什么。

考虑到这一点,模式就变得清晰了。共享记忆是让所有角色设定保持一致的基础。结构化文本是让它们能够干净地交接工作的协议。而每个角色设定的个体视角,则是将共享信息转化为独特而有价值输出的关键。你不需要复杂的编排框架来让智能体协作,你需要的是结构良好的文件和明确定义的角色。

沟通的复杂性降低了,所以工作的复杂性可以增加。

记忆作为优化,而非必需品

让我明确一点。智能体不需要记忆也能工作。你可以开启一个新会话,把智能体指向你的代码库,它就能搞明白。它会扫描文件,推断约定,拼凑出系统是如何工作的。它并不笨,最终会搞定的。

但“最终”是有代价的。智能体为定位自身而读取的每一个文件,都是花在导航而非执行上的代币。它推断出的每一个约定都可能是一个错误的猜测。它重新发现的每一个决定,都是已经做出但未被记录的决定。智能体在工作,但它比它需要的工作得更辛苦。

记忆改变了这个等式。它不是让智能体变得更聪明,而是让它所处环境更易于导航。一个索引文件并没有增加智能,它消除了摩擦。一个术语表并没有教会智能体新概念,它消除了歧义。一个决策日志并没有改进推理能力,它防止了重复推理。

这就是为什么我把记忆框定为一种优化,而不是必需品。这与为数据库添加索引的区别是一样的。没有索引,数据库也能工作。查询返回正确的结果。但随着数据集的增长,它们返回得更慢,消耗更多资源,性能也更难预测。索引并没有改变数据库能做什么,它改变了它做事的效率。

对于AI智能体来说,其好处在三个维度上叠加:

  • 效率 — 智能体更快地找到相关代码,因为它知道在哪里找,而不是因为它搜索了所有地方。
  • 代币成本 — 更少的代币花在发现上,意味着有更多的代币可用于实际任务,这直接转化为更低的成本和更好的输出质量。
  • 上下文清晰度 — 结构化的、范围明确的输入减少了上下文污染的机会,这意味着智能体的输出保持专注和相关。

当然,真正的问题不是你是否应该构建智能体的记忆。而是当你的项目发展时,你如何维护这种结构。与代码库不同步的索引文件比没有索引更糟糕,因为它们会引入自信的错误信息。这是一个维护承诺,而不是一次性设置。但如果你已经在为你的团队维护文档,将其扩展到服务你的智能体,边际成本很小,但回报巨大。

本文涵盖了检索层:智能体如何导航和访问它们所需的知识。但这里有一个我只稍微触及的相关问题。当多个智能体共同处理一个更大的任务时,它们如何协调?一个智能体的输出如何成为另一个智能体的输入,而不会丢失上下文或产生冲突?那是编排层,它值得一次深入探讨。

现在,从简单的开始。为你的项目写一个索引文件,或者和你最喜欢的AI伙伴一起做。为你的领域术语添加一个术语表。在日志中结构化记录你的决策。这些都是小文件,只需几分钟就能创建。但它们改变了每次智能体会话的起点,从“弄清楚所有东西在哪里”变成了“这是你需要的,现在开始工作”。

仅此转变就比一个更大的上下文窗口更有价值。FINISHED
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)或者 我的个人博客 https://blog.qife122.com/
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐