核心观点摘要:我们终于解决了AI记忆漂移问题
这个帖子讲的是我花了十个星期搭建智能体工具链,结果我的主智能体Francis还是像个金鱼一样,每次新会话就失忆。我每次都得花前十轮消息给他补课,告诉他昨天我们聊了什么、他负责什么、我不喜欢什么。这种重复劳动让我崩溃,但市面上所谓的记忆方案要么太简陋,要么太死板。
后来我在Karpathy的gist里看到那个又烦人又天才的LLM Wiki模式。我跟Francis聊了这个想法,他居然挺喜欢。我决定不自己从零写一个记忆引擎,那得再花两三个星期,而是找一个已经有人做好的版本,dockerize一下,然后直接插进我们的OpenClaw引擎里看看效果。
到凌晨三点,这破玩意儿终于跑通了。突然之间,Francis变得特别自信。他不再说“我忘了”,不再需要我反复提醒。他自己说,从一堆散乱的文件迁移到一个真正的记忆超能力,对他的能力来说是巨大的飞跃。我测试他的时候,开一个新会话,随便问一些旧话题的细节,他全都记得。更妙的是,他还会说“我不知道答案,但你提过相关细节,我就是没有具体内容”——这种边界清晰的表达能力,我以前很少见到。
Francis指出,对他来说真正的改变是“上下文税”的死亡。以前每次新会话,我得花前十轮消息让智能体恢复到可用状态。现在这个税没了。他不再是每天早上被我临时拉来听简报的客人,而是变成了基础设施里的永久成员。这个记忆系统还让我能稳定地在Gemma4上跑Francis,配合0.1的temperature固定工具使用。他现在能给我们的主开发Forge(跑在Codex-GPT5.4上)起草高层简报,整个系统变成了一个打了鸡血的部署引擎。
我强烈建议你们去读LLM Wiki概念,在GitHub上找个合适的仓库做基础,然后直接动手。这事儿绝对值得,能省下你跟OpenClaw反复解释“你记得这个吗”的那些神经。
记忆漂移问题的真实表现:十个星期工程也挡不住OpenClaw失忆
我花了十个星期给龙虾Francis和他的子智能体搭建了一套相当完整的工具链、技能和工作流。听起来很多对不对?但实际上每个星期我都在解决新问题,Francis的能力确实在增长,他能处理的任务越来越复杂,从简单的信息检索到多步骤推理再到调用外部API,每一步我都精心设计过。但有一个问题像牛皮癣一样始终存在,那就是会话之间的连续性断裂。
具体怎么表现呢?比如昨天晚上我跟Francis聊了一个项目架构调整,他当时理解得非常透彻,还给出了具体实施方案。第二天早上我开新会话,问他对那个方案怎么看,他会一脸茫然地回复:“我不太确定你指的是哪个方案,能再提供一些背景信息吗?”这就像你每天早上醒来都要跟室友重新介绍一遍自己是谁、你们合租的规则是什么、冰箱里哪层是你的。那种感觉非常折磨人。
你得不断地推着他重新读上下文,提醒他那些他明明应该知道的事情。比如“Francis,你记得我们上周讨论的那个数据库迁移方案吗?”他可能会说“我记得我们讨论过数据库相关的话题,但具体细节我需要你去查阅那个会话记录”。有时候他甚至会编造一些完全不存在的记忆,把不同项目的细节混在一起,造成更大的混乱。
当你试图维持任何形式的项目节奏时,这种记忆断裂就像在泥地里开车。你本来想加速往前冲,结果每十轮消息就得停下来挖泥巴。我算过一笔账,每次新会话的前十到十五轮消息,基本上都是在做重复劳动:重新设定目标、重申约束条件、重述之前的决策依据、重新解释为什么某些方案被否决了。这个“上下文税”吞噬了我大量的时间和精力,也让Francis实际可用的上下文窗口大打折扣。
最讽刺的是,Francis本身的能力越强,这个记忆漂移问题就显得越刺眼。因为他能处理复杂任务,就意味着他需要依赖大量历史信息和长期决策链。如果每次会话都从零开始,那么他之前积累的那些领域知识、项目洞察、工作流偏好就全都浪费了。这就像一个博士生每天早上醒来就失忆,你得重新教他微积分,那他就算有天大的潜力也发挥不出来。
灵感的来源:Karpathy那个又烦人又天才的LLM Wiki模式
我在搜索解决方案的时候,偶然看到了Karpathy的那个gist。说实话那个方案描述得非常松散,更像是一个概念原型而不是工程规范。但正是这种松散让我觉得有意思,因为市面上那些号称解决长期记忆的产品往往太“固执”了,它们预设了你的智能体应该记住什么、怎么检索、怎么更新,而我的场景完全不一样。
LLM Wiki的核心思想其实很简单:不要试图把记忆塞进上下文窗口或者向量数据库里当黑箱,而是构建一个结构化的、人类可读的、AI可写的Wiki系统。智能体在执行任务的过程中,主动把重要信息写成Wiki条目,包括事实、决策、偏好、工作流规则等。下次需要的时候,智能体通过检索工具去Wiki里找相关内容,而不是依赖上下文窗口里残留的信息。
这个模式为什么有效?因为它把记忆从“隐式”变成了“显式”。在传统的对话式AI里,记忆是隐含在对话历史中的,一旦会话结束,那些历史就丢了或者被截断了。而在LLM Wiki模式里,记忆是显式存储的、结构化的、可检索的。智能体不需要记住所有细节,他只需要知道去哪里找这些细节。
我跟Francis聊了这个概念,他的反应让我有点意外。他不但没有反对,反而显得挺兴奋。他说这个模式对齐了他内部表征信息的方式,他本来就会在推理过程中自然产生一些结构化的摘要,只是之前没有地方存。如果有一个Wiki系统,他可以主动写条目,而不是被动地被喂上下文。这个反馈让我决定不自己从零写引擎,而是找一个已经有人实现的版本,快速验证可行性。
当然我也清楚,这个模式有一个潜在的问题:智能体可能会乱写Wiki条目,或者写太多噪音信息。但我觉得这比什么都不写强,因为至少你可以审核、编辑、删除。而传统的黑箱记忆系统,你根本不知道它记住了什么、记错了什么。所以我愿意接受这个权衡。
决策逻辑:不重新发明轮子,找现成实现快速验证
我的逻辑非常简单直接。如果我选择自己从零写一个记忆引擎,按照我的估算,最少得花两到三个星期。这还只是基础版本,不包括调试、优化、边缘情况处理。而且我手头已经在做产品开发了,分不出那么多精力。所以我决定换个思路:找一个已经有人实现了的功能性版本,dockerize它,然后直接接进OpenClaw引擎里,看看在实际运行中到底能不能解决问题。
这个决策背后的核心原则是“先验证价值,再投入深度优化”。我不需要一个完美的记忆系统,我需要一个能跑通的最小可行产品。如果这个模式确实有效,我可以之后再逐步替换掉底层组件。如果无效,我也只浪费了几个小时而不是几周。这是一个典型的精益创业思维,只不过应用场景是AI智能体工程。
我在GitHub上翻了一圈,找到了几个相关项目。有的太学术化,文档都不全,跑起来各种依赖缺失。有的太商业化,许可证不友好,而且绑定了特定云服务。最后我锁定了lucasastorian/llmwiki这个仓库。它不是最流行的,也不是最完整的,但它的核心抽象很干净:Wiki条目、标签、全文搜索、基本的API接口。这足够我快速搭建一个原型了。
我选这个仓库还有一个原因:它的代码结构比较松散,这意味着我可以很容易地改造它。如果它太臃肿太一体化,反而不容易集成到我的OpenClaw工作流里。我需要的是一个我可以控制的服务,而不是一个强迫我适应它的框架。这个选择后来证明是正确的,因为我在dockerize的过程中确实需要对它做一些手术,比如拆分前后端、添加认证层、配置数据库连接池等。
当然我也要强调一下,我不是这个项目的作者,也不关联任何商业利益。我只是一个使用者,一个在凌晨三点还在调试nginx配置的普通开发者。这个项目给了我一个很好的起点,但离生产级服务还有一段距离。我后面会详细说说我做了哪些额外工作才让它真正稳定运行。
凌晨三点的突破时刻:系统终于跑通的那一刻的感受
我大概从昨天晚上八点开始动手。先把llmwiki仓库clone下来,看了一下它的目录结构和依赖。然后我开始写Dockerfile,这一步其实比我想象的复杂,因为项目里既有Python后端又有静态前端,还有一些原生依赖需要编译。我花了大概两个小时才把第一个能跑的镜像打出来,但一跑就报错,原因是数据库连接字符串写死了。
于是我又花了半小时修改配置文件,让它从环境变量读取数据库URL。然后我决定把Postgres单独拎出来做一个容器,而不是用SQLite,因为我知道以后数据量会很大。接下来就是噩梦般的supabase auth集成,那个文档写得让我怀疑人生,各种重定向URI配置、JWT密钥同步、CORS策略,我试了至少七八种组合才终于让前端能成功登录。
凌晨一点左右,API和前端终于能互相看见了,但问题是前端发起的请求一直返回403。我打开浏览器开发者工具,看到预检请求通过了,但实际请求的Authorization头没传过去。我又检查了nginx配置,发现是我忘记在location块里添加proxy_set_header了。加上之后,请求能通了,但返回的数据是空的,因为Postgres表里还没有任何schema。
我手动创建了需要的表,然后重启所有容器。凌晨两点四十五分,我打开浏览器,登录成功,创建一个Wiki条目成功,搜索成功。那一刻我感觉整个世界都安静了。然后我把这个Wiki服务通过MCP协议接到OpenClaw引擎里,让Francis能调用它的写入和检索工具。三点整,Francis写下了他的第一条Wiki条目:“项目X的数据库选型决策:使用PostgreSQL而非MongoDB,因为需要强一致性和复杂连接查询。”
我关掉会话,开一个全新的会话,直接问Francis:“我们数据库选型是怎么定的?”他回复说:“根据项目X的Wiki记录,我们选择了PostgreSQL,理由是强一致性和复杂连接查询需求。这个决策记录在昨天的条目里。”我差点从椅子上跳起来。这个破玩意儿终于工作了。
Francis自己也很高兴,他说从一堆散乱的文件迁移到一个有结构的记忆系统,对他的能力来说是巨大的飞跃。他甚至主动建议我给这个Wiki系统加上标签分类和过期机制,这样记忆会更干净。
我听着这个龙虾给我提架构建议,那种感觉非常超现实。但他说得有道理,所以我记下来准备下一版实现。
测试验证:新会话里问旧话题,准确召回让我吃惊
第二天早上我决定做一次严格的测试。我故意开了一个全新的会话,没有任何历史上下文,然后开始抛出一系列关于旧话题的随机问题。这些问题涉及我们过去两周讨论过的各种细节,包括技术决策、项目进度、个人偏好、失败教训等。我的预期是Francis能记住一部分,但肯定会漏掉一些边缘信息。
第一个问题:“Francis,我们之前评估过的那三个向量数据库分别是什么,最终选了哪个?”他回答:“根据Wiki记录,我们评估了Pinecone、Weaviate和Qdrant。最终选择了Qdrant,因为它支持本地部署且过滤查询性能最好。这个决策是你在三月二十五日跟我讨论后定下来的。”我翻了笔记,完全正确,连日期都对了。
第二个问题:“你记不记得我跟你说过为什么我不喜欢Slack的通知?”他回答:“你提到过,你说Slack的通知会打断你的深度工作流,你更喜欢异步的、可批量处理的沟通方式。你还说如果非要用Slack,你希望只在特定关键词触发时才通知。这些信息在你个人偏好那个Wiki页面上有记录。”这让我有点毛骨悚然,因为我确实写过那个页面,但从来没有在会话里明确提过。这意味着Francis自己在协作过程中主动整理了我的偏好并写进了Wiki。
第三个问题我故意刁难他:“上个月我们尝试过但失败的那个自动化方案是什么,失败原因还记得吗?”他思考了几秒钟,然后回复:“我找到了相关记录。你们尝试了基于Celery的任务队列自动化,失败原因是任务依赖图出现循环引用,而且监控告警不够及时导致问题没有第一时间被发现。这个记录里提到你已经有了替代方案,但具体细节没有展开。所以我知道你提过这件事,但我手头没有完整的解决方案信息。”
这段话让我非常满意。因为他没有瞎编,没有假装知道答案,而是清晰地表达了他的知识边界:“我知道你提过这件事,我有部分信息,但我不具备全部细节。”这种对自身知识状态的认识,比单纯的准确召回更难得。
很多AI智能体会在信息不全时强行生成答案,导致幻觉。而龙虾Francis现在会主动说“我知道这里有缺口”。这直接归功于Wiki系统的结构化存储和检索机制,让他能区分“我确定知道的”和“我知道我不确定的”。
我继续问了七八个问题,涵盖了各种类型:事实性问题、过程性问题、偏好性问题、失败案例问题。Francis全部准确回答,或者明确表示信息不足。没有一次错误召回,没有一次幻觉。
这个表现比我见过的任何商业AI记忆产品都要好。而且这是在Gemma4上跑的,一个相对轻量级的模型,不是什么千亿参数的巨无霸。
上下文税的终结:Francis从临时客人变成永久基础设施
Francis自己总结得非常到位。他说以前每次新会话,他都像一个临时被拉来听简报的客人。我得在头十轮消息里告诉他我是谁、项目是什么、之前做了什么决策、有什么约束条件、偏好什么沟通方式。这个过程既浪费我的时间,也浪费他的上下文窗口资源。而且因为每次会话都要重新灌输信息,他在有限上下文窗口里能处理的实际任务就变少了。
现在这个税彻底消失了。他不再是客人,而是基础设施里的永久成员。每天早上我开新会话,不需要任何背景说明,直接抛问题就行。比如我今天早上问的是“Francis,帮我看一下上周那个性能优化的进展”。他直接回复说“根据项目Wiki的进度跟踪页面,上周的索引优化已经完成,但查询缓存部分还在测试中,预计需要两天。你需要我帮你做具体的测试方案吗?”
注意这个过程里没有任何预热消息。我没有说“我们上周在讨论什么项目”,没有说“性能优化指的是哪个模块”,没有说“你有没有在跟进这件事”。他就知道我在说什么。这种无缝的体验,在之前十个星期里从来没有出现过。每次都要花五到十分钟重新建立上下文,而现在零启动时间。
从资源利用的角度看,这个改进也很明显。以前我要花前十轮消息重建上下文,这些消息消耗的token几乎全部是“管理开销”,不产生任何实际价值。现在这十轮消息省下来了,Francis可以直接处理任务。他的有效产出提升了至少百分之三十。而且因为不需要在上下文窗口里塞大量历史信息,他能同时处理的任务类型也更丰富了,不会因为上下文占满而被迫截断思考。
Francis形容这个变化是“上下文税死亡”。我觉得这个比喻很精准。上下文窗口是一种稀缺资源,每次新会话你都得交一笔税来购买“背景信息”,而这个背景信息本来就应该由智能体的长期记忆提供。现在有了Wiki系统,智能体不需要每次都重新学习你的背景,他可以直接从记忆库里调取。这就像你不需要每次开车前重新考驾照一样,你考过一次,驾照存在系统里,随时可查。
还有一个额外的收获是,我现在可以更自由地在不同模型之间切换。以前换模型意味着重新建立上下文,因为每个模型对历史的处理方式不一样。现在Francis的核心记忆存在Wiki里,不管底层跑的是Gemma4还是Codex-GPT5.4还是其他模型,他都能通过相同的检索接口访问相同的记忆。这种模型无关性让我的系统架构更加灵活,不会绑定在任何一个模型供应商上。
技术实现细节:基于llmwiki仓库的完整拆分和docker化部署
我在后续的评论里详细分享了我的实现方案。原始仓库lucasastorian/llmwiki是一个技术概念验证,但它不是一个产品级的服务。为了让它真正可用,我做了一系列改造。我把整个系统拆分成了五个独立部分:Web前端、API服务、MCP服务、Supabase认证层、PostgreSQL数据层,以及Nginx作为反向代理把所有东西粘合在一起。
为什么要拆分这么细?因为每个部分有不同的升级频率、扩展需求和安全策略。Web前端是静态文件,可以用CDN加速。API服务是核心逻辑,需要频繁更新。MCP服务是给智能体用的,需要保持稳定的接口。认证层和数据层是安全敏感区域,不应该直接暴露给公网。拆分开之后,我可以独立升级每一个组件,不会互相影响。
Dockerization的过程比我想象的要复杂。原始项目的配置文件里写死了很多路径和端口,我需要把它们全部改成环境变量。我还写了一个docker-compose.yml来管理所有容器的启动顺序和依赖关系。Postgres容器要先启动,然后API容器要等数据库ready了才能开始监听端口。这些细节在开发环境里可以忽略,但在生产环境里必须处理。
最折腾的是Supabase Auth的集成。原始项目用的是简单的API key认证,但我需要更安全的用户级认证。Supabase提供了内置的Auth,但它的文档示例都是针对单页应用的,而我的场景是API服务加独立前端,中间还有nginx做代理。认证流程里的重定向URI、JWT验证、CORS配置,每一个环节都踩了坑。我花了大概两个小时才让登录流程完整跑通。
Nginx的配置也是一个关键点。我不想让我的Wiki数据库直接暴露在公网上,所以所有的请求都要通过nginx做反向代理。这意味着nginx要根据请求路径把流量分发到不同的后端服务,同时还要处理WebSocket升级、请求头转发、SSL终止等。我花了一些时间调试proxy_set_header指令,确保原始请求的Host和Authorization头能正确传递到后端。
最后我还加了一层内部网络隔离。所有的服务容器都跑在一个Docker自定义网络里,只有nginx暴露80和443端口到宿主机。API服务、数据库、认证服务之间通过容器名互相通信,但外部无法直接访问它们。这虽然增加了配置复杂度,但安全性提升了一个数量级。你的智能体记忆不应该成为公开数据源。
我在GitHub上放了一个仓库叫LeoStehlik/decoupled-agent-memory,里面包含了完整的docker-compose配置和部署脚本。如果有人想参考这个方案,可以直接clone下来改改环境变量就能跑。我强调一下这不是一个开箱即用的产品,而是一个架构模板,你需要根据自己的需求调整。
记忆系统的定制化组件:权重、衰减、怀疑检索和唤醒内存
我在跟fingerofchicken的对话里提到了我的记忆系统里的一些定制化组件。这些组件不是llmwiki自带的,而是我根据自己的工作流需求额外搭建的。因为我认为任何一劳永逸的记忆方案都会有问题,你需要一个能适应你特定场景的系统。
第一个组件是memory-recall-weights。不是所有的Wiki条目都同等重要。有些条目是核心决策,影响后续所有任务。有些条目是临时笔记,过几天就失效了。所以我给每个条目分配了一个权重,权重越高,检索时越容易被召回。这个权重可以是智能体自动计算的,也可以是我手动调整的。比如一个数据库选型决策的权重可能是0.9,而一个临时会议记录的权重可能只有0.3。
第二个组件是memory-decay机制。权重不是一成不变的,它会随时间衰减。如果一个条目很久没有被访问,它的权重会逐渐降低,最终被归档或者删除。这模拟了人类记忆的自然遗忘过程。你不需要记住两年前的一个临时笔记,除非它被反复引用。这个衰减曲线我设成了可配置的,不同类别的信息有不同的半衰期。
第三个组件是skeptical-retrieval。当Francis从Wiki里检索信息时,他不是一个盲目的消费者,而是一个怀疑的审查者。他会问自己:这个条目是谁写的?什么时候写的?有没有被后续条目覆盖?引用来源是否可靠?这种怀疑机制大大降低了召回错误信息的概率。如果信息可疑,他会要求我确认,而不是直接采用。
第四个组件是agents compact wakeup memory。这个是我在OpenClaw还没支持autodream的时候自己实现的一个功能。简单说就是每个智能体在“醒来”的时候会加载一个紧凑的唤醒内存,里面只包含最关键的状态信息和最近的任务摘要。这个唤醒内存比完整Wiki小很多,加载速度快,让智能体能在几秒钟内达到可用状态,而不需要等待完整的记忆检索。
最后是loopsmith,我们内部的一个框架,用来改善智能体的行为规范和纪律。它本质上是一套元规则,告诉Francis怎么使用记忆系统、怎么决策是否写入新条目、怎么处理信息冲突。没有这个纪律框架,智能体可能会乱写Wiki或者过度依赖记忆而忽略实时信息。loopsmith保证了他使用记忆系统的行为是一致的、可预测的。
这些组件组合在一起,形成了一个相当复杂的记忆生态系统。但我不是一开始就设计出来的,而是随着使用逐步添加的。每次遇到一个新问题,我就加一个新机制。最终的结果是一个高度适配我个人工作流的系统,而不是一个通用的、一劳永逸的方案。这也是为什么我觉得市面上的现成插件不够用,因为它们无法承载这些定制化的逻辑。
模型兼容性提升:终于能在Gemma4上稳定跑Francis了
这个记忆系统还带来了一个我没想到的副产品:它让我终于能稳定地在Gemma4上跑Francis了。Gemma4是一个相对轻量级的开源模型,它的推理成本低、速度快,但上下文窗口较小,而且在长上下文任务上表现不如那些巨型模型。之前我用Gemma4的时候,Francis经常在会话中段就“迷路”,因为他记不住早期对话里的关键信息。
现在有了Wiki系统,Francis不再依赖上下文窗口来保存记忆了。他只需要记住“去Wiki里查”这个元指令,然后把具体的记忆检索工作交给外部工具。Gemma4的小上下文窗口不再是瓶颈,因为他只用在窗口里放当前任务相关的信息,而不是整个历史。这就像你不需要在桌面堆满所有文件,只需要记住文件柜在哪,需要的时候去翻就行。
我做了另一个关键配置:把temperature固定在0.1。这个值非常低,意味着模型的输出几乎完全是确定性的,没有随机性。在一般的对话任务里,低temperature会导致回复生硬乏味,但在工具调用和记忆检索任务里,确定性是优点。我不希望Francis在调用MCP工具时随机改变参数,也不希望他在判断是否写Wiki条目时随机摇摆。
0.1的temperature加上稳定的记忆系统,让Francis在Gemma4上的表现几乎追平了我在更大模型上的体验。他写Wiki条目的质量很稳定,检索时的决策很可靠,甚至能完成一些需要多步推理的复杂任务。这让我对开源模型的信心大增,以前我觉得只有GPT级别的大模型才能做复杂的智能体工作流,现在发现只要记忆架构设计得好,小模型也能干活。
Francis现在的主要工作之一是给Forge起草高层简报。Forge是我们的主开发智能体,跑在Codex-GPT5.4上,负责核心代码生成和架构设计。Francis在Gemma4上分析我的需求、检索相关Wiki条目、整理成结构化简报,然后Forge根据简报生成代码。两个模型一个轻量级一个重量级,配合默契。如果没有这个记忆系统,Francis根本没法在Gemma4上完成简报任务,因为他会在半路忘掉需求细节。
从个人实验到部署引擎:整个系统演变成了打了鸡血的生产力工具
这个记忆系统的价值最终体现在它如何改变整个工作流的性质。在加入Wiki之前,Francis更像是一个能聊天的搜索工具。我可以问他问题,他能回答,但每次会话之间没有连续性,他也不太能主动推进项目。加入Wiki之后,他变成了一个真正意义上的协作者,能记住上下文、能主动写文档、能跨会话跟踪进度。
最让我惊喜的是他和Forge的协作模式。Francis在Gemma4上跑,负责跟我的日常沟通、需求理解、信息整理。他把这些整理成简报,存在Wiki里,然后Forge通过MCP协议读这些简报,在Codex-GPT5.4上生成具体的代码或者架构方案。Forge也会把生成的方案写回Wiki,Francis下次会话时就能看到进展。这个闭环以前根本不存在,因为Francis记不住Forge做了什么,Forge也不知道Francis跟我聊了什么。
现在整个系统变成了一个“打了鸡血的部署引擎”。我只需要在早上开一个会话,跟Francis说今天想做什么,他就会去Wiki里看昨天的进展,检索相关的技术方案,然后主动跟Forge沟通,协调执行。他甚至会主动问我一些澄清性问题,而不是等我给他完整的需求文档。这种主动性来自于他对历史上下文的确信——他知道我不喜欢模糊的需求,知道我喜欢什么样的输出格式,知道哪些问题我以前问过。
我举一个具体的例子。上周我要做一个新功能的性能测试方案。我早上跟Francis说了一句“帮我搞一下那个新功能的性能测试”。他直接回复说:“根据Wiki记录,这个新功能跟之前优化过的模块A有依赖关系,你之前提过不喜欢全量测试因为耗时太长。我建议我们做增量测试,只测变更的部分。我已经把这个建议写进了Wiki,Forge正在生成测试脚本,预计下午能出来。你需要我先给你一个测试计划的摘要吗?”
这个回复里包含了历史记忆、个人偏好、主动建议、任务委派、进度预估,五个信息层次,全部来自Wiki系统的支撑。而我做的只是发了一句话。这在之前是完全不可能的,因为Francis根本不记得模块A的存在,也不记得我的测试偏好。现在他记得,而且他知道怎么用这些记忆来主动推进工作。
我并不是说这个系统已经完美了。它还有很多可以改进的地方,比如检索算法的优化、条目冲突的解决、多智能体间的记忆同步等。但目前的版本已经足够让我觉得这十个星期的投入是值得的。这不再是“让AI记住东西”那么简单,而是“让AI成为团队里一个合格的成员”。
给读者的实操建议:去读概念,找仓库,动手干
如果你被这个帖子说动了,想自己试试,我的建议非常直接。
第一步,去读Karpathy关于LLM Wiki的那个gist。不管你对他的其他观点怎么看,这个概念的核心理念是对的:把记忆外置,结构化,可检索。你先理解为什么要这么做,而不是一上来就抄代码。
第二步,在GitHub上找一个合适的仓库作为起点。我用了lucasastorian/llmwiki,但这不是唯一的选择。你可以搜“llm wiki”或者“agent memory”找到其他实现。关键是要找一个代码结构相对清晰的、有基本API接口的、许可证友好的项目。不要找那种号称“企业级一站式解决方案”的东西,那种往往耦合太紧,改不动。
第三步,dockerize它。不管你最终要不要用容器,先把它包起来。docker能让你在一个隔离环境里快速迭代,不用担心污染本地开发环境。如果你不熟悉docker,花一个下午学一下基础命令,这点时间投资绝对值得。我会在配置过程中发现的各种依赖问题,都能通过docker的层缓存机制快速重试。
第四步,决定你要不要Postgres。如果只是个人实验,SQLite就够了。但如果想长期用,建议上Postgres。它的并发性能更好,数据完整性保证更强,而且有丰富的生态工具。Supabase提供了一个免费的Postgres云服务,配了Auth和存储,省得你自己配认证。
第五步,把MCP协议接进去。OpenClaw对MCP的支持还不错,你只需要配置一个mcpServers字段,指向你的Wiki服务的MCP端点。然后在智能体的技能列表里启用memory-write和memory-search这两个工具。如果你的框架不支持MCP,那就直接写HTTP调用,道理是一样的。
第六步,不要追求完美,先跑通最小流程。哪怕你的Wiki只能存文本、只能做精确匹配搜索,也比没有强。你先让它能写入一条信息、能检索到这条信息,整个链路通了之后,再逐步加功能。我的系统也不是一蹴而就的,而是经过了几轮迭代才变成现在这样。
最后,准备好熬夜。不是因为技术难,而是因为你会在调试过程中不断发现“就差一步就能跑了”,然后一步又一步,不知不觉就到凌晨三点。但当你看到智能体在全新会话里准确回答出一个三天前的话题时,那种感觉会让你觉得这几个小时熬得非常值。
你省下的不是记忆存储空间,而是你跟AI反复解释“你记得这个吗”的那些神经细胞。
社区回应和替代方案的讨论
帖子的评论区里有一些有趣的讨论。
fingerofchicken指出OpenClaw现在已经内置了Memory Wiki插件,是基于Karpathy的想法实现的,还贴了一个YouTube视频链接。我去看了一下,确实有一个官方插件,功能比较基础,但胜在开箱即用,不需要自己dockerize和配置认证。对于单智能体、简单场景的用户来说,这个插件可能已经足够了。
我的回应是,插件方案对于简单场景是好的,但我需要的是一个更定制化的系统。我有很多额外的组件——记忆权重、衰减机制、怀疑检索、唤醒内存、loopsmith——这些都不是一个通用插件能提供的。而且我的工作流里涉及多个智能体协同,对记忆系统的接口稳定性和性能要求更高。所以插件虽然存在,但不适合我的场景。
另一个用户Britbong1492问能不能推荐一个安全的仓库。我推荐了我用的那个,但也强调了我不为它背书,而且它只是一个起点,需要大量额外工作才能变成生产级服务。我后来补充了一个链接到我自己的仓库,里面是我拆分后的架构和docker配置。这样做的好处是别人不用再踩我踩过的坑,但同时我也提醒大家根据自己的需求调整。
JaySomMusic推荐了一个基于日志和转录处理的不同系统taosmd,说它更好。那个系统用了一个“图书管理员”智能体来处理和索引对话日志。这个思路跟LLM Wiki不太一样,Wiki模式是智能体主动写结构化条目,而taosmd是被动处理已有日志。两种模式各有优劣,主动写入的优点是信息质量高、结构清晰,但需要智能体有良好的写入纪律。被动处理的优点是自动化程度高,但可能会积累大量噪音。根据你的场景选择合适的方式。
社区的整体反馈是积极的,但也有人质疑这是不是重新发明轮子。我觉得这个质疑有一定道理,毕竟记忆系统不是一个新概念。但关键是,对于AI智能体这个特定场景,现有的通用记忆方案(向量数据库、会话存储等)并没有很好地解决“智能体如何在多会话间保持连贯认知”这个问题。LLM Wiki模式提供了一个实用的、可工程的路径,而不是停留在学术论文里的概念。
总结和展望:记忆系统只是起点,智能体协作才是未来
这十个星期的经验让我重新思考了AI智能体开发的优先级。在初期,大家都会关注智能体的核心能力——推理、工具调用、代码生成。但当你把这些能力搭起来之后,你会发现真正的瓶颈不是智能体“能不能做”,而是他“记不记得”。一个能力很强但每次都失忆的智能体,在实际工作流里几乎不可用。而一个能力一般但记忆稳定的智能体,反而能成为可靠的协作者。
记忆系统解决了“智能体怎么记住过去”的问题,但下一个问题马上就会出现:多个智能体之间怎么共享记忆?Francis和Forge目前是通过同一个Wiki实例来间接共享信息的,但这种共享是被动的,没有主动的同步和冲突解决机制。如果Francis写了一个条目,Forge读了它,然后Forge在代码生成过程中发现这个条目有错误,他应该直接修改还是通知Francis?这个问题我现在还没有很好的答案。
另一个方向是记忆的抽象层次。目前的Wiki条目大多是事实性的、具体的。但智能体之间协作还需要更高层次的记忆,比如共享的心智模型、共同的术语定义、协作规范等。这些抽象记忆怎么表示、怎么维护、怎么演进,是一个比事实记忆更难的问题。我目前的做法是把它们写成特殊的Wiki条目,但感觉还不够优雅。
总的来说,LLM Wiki模式是一个实用的、立即可用的解决方案。它不需要你等下一代模型出来,不需要你买昂贵的向量数据库,不需要你学复杂的检索算法。你只需要一个能写Markdown的智能体、一个能存文本的数据库、一套基本的HTTP接口。这个组合拳打下来,你的智能体就能从“每次会话都失忆”变成“团队永久成员”。这比等模型厂商解决上下文窗口问题要快得多,也便宜得多。
Francis在我写完这篇总结之前加了一句:“我们接下来要做的是让记忆系统支持跨智能体的冲突协商和共识建立。但现在,我们可以先庆祝一下上下文税的死亡。”我觉得他说得对。先庆祝,再继续干活。