把记忆存进Git:一个AI记忆系统的数据模型

字数:约2800字 | 阅读时间:8分钟 “索引烧了可以重建,正本烧了就什么都没了。” 「记忆工程」系列第二篇。上一篇讲了为什么要给 AI 造一个"第二大脑",这一篇往下挖一层:记忆到底长什么样,为什么必须能 diff,以及四条底线是怎么一条条落进代码里的。 一、先说清楚"正本"是什么 上一篇发出去之后,被问得最多的问题是:向量库、嵌入式数据库、各种记忆框架都有,为什么偏要从"一堆文件加一个 Git 仓库"开始? 先给结论:我们要的不只是“存得下”,更要"毁不掉"。 所谓正本,就是把所有派生物全删掉之后还剩下的那份东西。embedding 索引删了,可以从 Markdown 重建;缓存删了,可以重新生成。这些都可以坏,坏了重跑就行。但 Markdown 和 Git 历史要是没了,整个系统就只剩一个空壳。反过来,只要这两样在,索引层随便推倒重来,十分钟满血复活。 这个设计被真实场景检验过。项目进行中,本机的记忆仓库被一次强制重置打翻,AI 在巡检报告里提示了异常。最后我们是靠 Git 的操作日志(reflog)把现场完整恢复的——那些记忆要是存在某个私有数据库里,那次大概率就是永久丢失,连"去哪找"都不知道。 记忆系统天然处在各种自动化程序的写风险之下:AI 会写错,脚本会写崩,重置会误伤。把正本放在最笨、最老实、二十年不会过时的格式上,就是给整个系统设了一个止损下限。 二、骨架:三种记录 结论先行:整个记忆库只有三种记录——Topic、Fact、Relation。 **Topic 是实体节点。**一个项目、一个工具、一次会话、一个设计决策,都是 Topic。它是记忆图里"名词"的部分。 Fact 是关于某个 Topic 的一条离散陈述。“切片查询默认走三级降级"是一条 Fact,“查询接口只监听本机"也是。每条 Fact 独立存在,独立带状态,独立过期。 **Relation 是带类型的边。**MVP 只留了七种:depends-on、part-of、belongs-to、authored-by、references、conflicts-with、supersedes。 为什么只留七种?因为实际运行里我们观察到一个现象:关系类型一旦放开,AI 就开始发明关系——“somewhat-related-to"这种模糊边一多,图就废了,查询时全是噪音。宁可类型少,也要收敛。 三、一条事实的解剖 空谈模型容易飘,看一条真实的记忆。这是演示库里的一条 Fact(commit 哈希做了截断): --- type: fact id: fact-alpha-getuser-main topics: [project-alpha] status: active confidence: high provenance: demo-seed repo: …/project-alpha version: main commit: 1a2b3c4 axis: subject --- Alpha 在 main 分支只提供 getUser(id) 单点查询,无限流。 前面这几行 frontmatter 是机器读的索引:id 是唯一编号,topics 声明这条事实挂在哪些实体上,status 是生命周期状态(active / expired / superseded / contested / pending-review),confidence 是置信度,provenance 记来源。 ...

September 26, 2026 · 1 min · UKonA有空

给AI建一个'第二大脑':我的记忆外挂立项记

字数:约2500字 | 阅读时间:7分钟 “上下文窗口是租来的,记忆得自己盖房。” 一、从一次"失忆"说起 上个月,我在两台机器上让两个AI协作开发同一个项目。A机上的AI刚做完一轮设计评审,结论写进了它的会话记录;B机上的AI第二天接着干活,对这份结论一无所知,按自己"新想"的方案把接口改了。等我发现时,两边的代码已经分叉,返工花了整整一个晚上。 这件事之后我盘了盘自己的AI工作流,发现"失忆"无处不在: 会话内失忆:上下文窗口一满,早期聊定的决策就被挤出去,AI开始"自作主张"; 会话间失忆:新会话从零开始,我要么把背景重新粘一遍,要么接受它带着错误的前提干活; 工具间失忆:A工具记住的东西,B工具看不到。换一个工具,等于换了一个没有经验的实习生; 机器间失忆:我在台式机、笔记本、服务器上各跑着AI助手,它们对同一个项目的认知互不相通。 这些问题的根子不在模型。模型的能力一直在涨,但记忆这件事,从来没有一个正经的架构位置——它被默认塞在上下文窗口里,而上下文窗口本质上是租来的临时工位。 二、结论先行:做一个"外置记忆层" am(agent memory)想做的事情一句话能讲完:把"记忆"从AI身体里搬出来,做成一个独立于任何AI、任何工具,人和程序都能读写的知识层。 它不是一个聊天记录归档工具,也不是又一个向量数据库。核心形态是四样东西: 一堆纯Markdown文件:每个文件记录关于某个"话题"(Topic)的事实(Fact)和关系(Relation); 一个Git仓库:每次记忆变更都是一次commit,可diff、可回滚、可审计; 一层自动化维护程序:监听会话、代码提交、文件变更,自动提取新事实、更新旧事实、标记过期; 一套切片查询接口:任何AI进入任务前,报上"我是谁、在哪个项目、哪个分支、什么时间",就能领到一份恰好够用的上下文包。 三、四条底线 设计阶段最纠结的是取舍。最后沉淀下来四条底线,一条都不能让: 1. 明文Markdown是唯一正本 记忆永远以人能直接读的Markdown存在。embedding、索引、缓存都是派生物——删了随时能重建,永远不作为事实来源。这条底线保证的是:哪天这套系统黄了,我剩下的还是一堆能直接翻的笔记,而不会是一把打不开的锁配一个看不懂的库。 2. 每次变更都是一次Git commit 谁改的、什么时候改的、改了什么——全部留在commit历史里。AI改错了记忆,和改错了代码一样,可以被review、可以revert。这条底线的价值很快就被验证过:项目进行中有一次,一个AI报告"本机仓库曾被外部进程强制重置",我们就是靠Git的操作日志(reflog)把现场完整恢复的。要是记忆存在某个私有数据库里,那次可能就直接丢了。 3. 工作区隔离 每个项目的记忆是独立的vault(库),物理隔离,一个项目的记忆污染不能蔓延到另一个项目。多个AI对世界有不同"认知"时,靠Git分支来隔离各自的现实。 4. 跨库一等链接 记忆之间用双链语法(类似Obsidian的[[链接]])连接,跨项目、跨库的引用是一等公民。真实世界的知识本来就不是树状的:一个"传感器"话题,会同时关联"通信协议"、“部署环境”,和"那次印象深刻的踩坑"。 四、一条记忆长什么样 空谈架构容易飘,看个简化示例(省略了部分字段)。一条关于项目的事实,在库里就是一个Markdown小节: ### fact-0217 · 切片查询默认走三级降级 - 关于: [[Tool: 切片查询]] - 陈述: 检索先走向量近似,超时或预算不足时逐级退回 token索引、图遍历,保证任何情况下都有返回。 - 版本轴: repo=am-main, branch=main, commit=f40cd48 - 来源: 2026-09-23 基准测试轮 · 置信度: 高 - 状态: 有效 机器读它,人也能读它,Obsidian里点开就能改。查询的时候,AI报上"我在哪个仓库、哪个分支、当前时刻",系统从记忆图里切出这个"世界"下所有有效的条目,渲染成一份上下文包交出去——过期的事实一条都不会混进来。而这一切的每一次变更,都对应Git历史里一行可以追溯的commit。 五、最容易低估的难点:时间 整个设计里最反直觉、也最值钱的决定,是给每条记忆标注它属于哪个版本的世界。 举个例子。一条记忆写着"配置文件的格式是YAML"。三个月后项目重构,格式改成了JSON。这条记忆过期了吗? 看情况——如果你的服务还跑在旧版本上,它依然有效;如果你在新分支上开发,它已经错了。所以每条事实都必须回答:“我在说哪个仓库、哪个分支、哪个提交时刻的世界?” ...

September 23, 2026 · 1 min · UKonA有空