一、为什么我会把 AI 编程代理拆成 9 个仓库
AI 编程代理这几年特别火,但真正用下来你会发现,单靠一个大模型对话窗口根本撑不起复杂的项目开发。模型记不住你之前定下的技术约束,看不到整个项目的依赖关系,甚至连续对话超过几轮之后就开始丢上下文。这些问题的根源并不在于模型本身蠢,而是我们缺少一套能帮 AI 补齐短板的工具链。
我最早也是自己写一些零散的脚本,把代码库的关键信息塞给 AI,或者用一套固定的提示词模板来维持上下文。时间一长,这些零碎的东西越来越多,维护起来反而比写业务代码还累。于是我把手头的代码整理成了九个独立的开源仓库,全部走 MIT 协议,任何团队和个人都可以直接拿去改、拿去用。
这套工具链解决的核心问题有三个:第一,让 AI 在项目的长期开发过程中有持续记忆,不因为对话轮次的增加而忘记早前约定;第二,给 AI 一张清晰的代码地图,让它能够快速定位关键文件、理解模块之间的依赖关系,而不是盲目读整个仓库;第三,把所有和 AI 交互产生的 token 消耗记录成可量化的账本,避免月底看着账单一脸懵。
整个设计思路是模块化、轻量化、可替换。每个仓库都只做一件事,组件之间通过简单的配置文件和标准输入输出协议对接,你不用全部采纳,挑自己缺的那块来用即可。下面我会逐个拆开讲,包括每个模块的技术选型、核心实现逻辑和部署过程中的实际经验。
二、先聊记忆模块:到底该怎么给 AI 建立长期记忆
很多人在和 AI 编程代理协作的时候都有过这种体验:明明上一轮刚和它确认了数据库表结构命名规则,几轮之后它又生成了一批违反规则的新代码。这不是 AI 在跟你对着干,而是它根本没有一个超越单次对话的存储机制。普通的上下文窗口,几十页代码一填充,早就把那些“约定俗成”的规则挤出去了。
我专门给这套工具链写了一个记忆服务仓库,本质是一个带版本管理能力的键值存储服务,数据层用的是文件系统加索引的轻量方案,没有引入重量级数据库。每条记忆都有三个核心字段:命名空间、关键词和内容正文。命名空间决定了这条记忆归属于哪个项目,关键词用于后续的模糊召回,内容正文则可以是任意长度的文本,例如编码规范、架构决策、API 使用约定等。
记忆写入的时机非常关键,我建议在每次对话刚开始的时候,把当前项目相关的记忆快照自动注入到系统提示词中,同时在代码提交之前,把新出现的约定再固化回记忆库。这个过程我写成了一组 Git 钩子脚本,不需要你手动触发。提交代码时,钩子会扫描 diff 中新增的注释和文档片段,提取包含关键决策性语言的句子,再通过我一个简单的解析器判断是否需要列入记忆。
实际用下来有几个很值得注意的经验。记忆的粒度太细会导致召回时上下文膨胀,反而干扰模型的判断,所以每条记忆尽量控制在 100 字以内;粒度太粗又抹平了细节,无法拦截具体的错误。最稳妥的做法是分层存:一层是项目级的不变量,比如“禁止使用全局变量”,一层是模块级的局部约束,比如“用户服务模块必须走统一的鉴权入口”。召回的优先级也是先项目层后模块层,靠这个顺序来避免冲突。
记忆仓库本身没有任何和具体大模型绑定的代码,完全是通用的 HTTP 接口。你完全可以把它接入到任何支持自定义上下文的 AI 工具里,甚至不用于 AI 编程,拿来管理日常的开发知识笔记也可以。这算是这个模块最让我满意的地方,它没有把记忆和某个特定模型强耦合,随时可以替换上游模型,不会影响已经积累的记忆数据。
三、代码地图:让 AI 在几秒钟内看懂项目结构
让 AI 真正理解一个大型代码仓库,是比记忆更硬核的难题。如果直接把整个仓库源码塞进上下文,token 消耗瞬间爆表,而且大部分代码对当前任务来说是噪声。我们需要一张结构化的代码地图,只传递那些能让 AI 快速建立全局认知的信息,例如目录树、依赖关系、关键函数的入口点。
代码地图仓库的输入是一个本地 Git 仓库路径,输出会产生三样东西。第一份是一棵精简目录树,默认只包含源文件目录和核心配置目录,忽略了构建产物及依赖缓存等目录;第二份是一个符号索引文件,列出了所有导出类、顶层函数以及它们的文件定位;第三份是模块依赖关系图,这个图不是用来看的,而是用于回答 AI 关于“改动这个文件会影响到哪个模块”这类问题的。
生成代码地图的核心技术点是静态分析。为了同时支持不同的编程语言,我不能为每种语言都写一套复杂的编译器前端,所以我用了通用正则加语言特定插件的混合方案。每种语言插件负责提取该语言特有的语法结构,通用层则负责将提取到的符号汇总成统一的数据格式。目前已经支持最常见的几种后端语言,对于前端的类型标记语言也有不错的覆盖率,但还不完美,遇到极端的动态语法特性时可能会漏掉部分符号。
代码地图工具输出的格式是 JSON 加 Markdown 混合,其中完整地图用 JSON 记录,为了给机器去读取,而给 AI 提示词中直接插入的则是 Markdown 摘要版。摘要版控制了长度,默认只保留目录树前四级和依赖度最高的顶层模块,这样既能让 AI 有个全局感,又不会撑爆上下文。
这里有一个我在实践中踩过的坑。第一版我试图把依赖关系做得越细越好,每个函数级别的调用关系都精确画出来,结果引入的存储和数据查询开销非常大,生成一次地图要三十多秒,这在日常协作中是难以接受的。后来我把依赖图降级到了模块级,把“函数谁调用谁”这种关系交给 AI 自己根据代码内容推理。实测下来准确率没有明显下降,但生成时间降到了三秒以内,这才是能塞进日常开发流程的速度。
四、token 记账模块:把每一分成本算得清清楚楚
使用 AI 编程代理的隐性成本常常被低估。很多人以为只是按次调用付费,实际上上下文反复填充、重试调用、历史记录维护都会产生额外 token 消耗。如果项目团队按月结算,这些开销会被平摊到每个人头上,但具体消耗在哪里、哪些任务最烧钱,往往没有量化数据。为了搞清楚这个问题,我写了一个专用的 token 记账模块。
这个模块的工作方式类似网络代理。所有和 AI 服务的请求都会经过它的转发层,转发层会记录请求中的输入 token 数、输出 token 数、模型名称、请求发起时间以及所关联的项目和任务标签。记录存入一个本地 SQLite 数据库,并提供一组只读查询接口。
为什么选 SQLite 而不是文本日志?文本日志虽然简单,但是查询和聚合统计特别不方便。SQLite 单文件、零部署、支持 SQL 查询,非常适合这种本地工具场景。严格照 SQL 去查询各类任务的平均成本就可以直接做到,例如需要按任务分组统计时,一条标准 SQL 语句就能解决。
设计记账模块时我特别关注了一个隐私问题:记账和请求内容审计是两回事。我没有在日志里记录完整的请求和响应的原文,只记录了 token 计数和任务元信息。这样即使团队内部共用一台开发机,每个人的代码内容也不会被额外留存,只有成本和消耗的统计维度被保留下来。
也许有人好奇,既然官方控制台已经能看到用量,为什么还要多此一举做本地记账?官方后台的粒度通常只到账号级别,或者应用级别,它很难回答“昨天一下午调试哪个模块花费最高”这种具体问题。而且官方的数据存在一定延迟,没法实时感知当前会话是否出现异常消耗。本地记账则完全可控,我还在模块里做了一个预警规则:单次请求消耗超过项目平均消耗三倍以上时,会在终端直接打出一条告警提示,辅助定位那些因为上下文爆炸导致的高昂请求。
五、工具链里的其他六件套
除了记忆、代码地图和 token 记账这三个核心模块,这套工具链还有六个配套仓库,它们相辅相成,弥补了主模块以外的一些细节问题。
第四个仓库是任务拆分引擎。AI 编程时经常面对一个模糊的指令,例如“把这些接口都加上权限校验”,这种指令的 token 成本极高,因为模型需要反复猜测范围。我写了一个本地脚本,通过读取代码地图里的符号索引,把这类模糊指令自动扩展成包含具体文件列表、修改类型和影响范围的子任务清单,再交给主对话流程去执行。拆分后的任务让 AI 的重试次数明显下降,也让我更容易验证每个子步骤是否完成。
第五个仓库是变更集差异分析器。它不只对比代码的前后差异,还会花一部分精力分析这个差异是否和记忆库中的规则冲突。例如你自己定义了“所有数据模型必须带软删字段”,AI 在某一次修改中新增了一个没有软删字段的表结构,差异分析器就会在生成代码但还没提交的环节直接拦截并提醒你。
第六个仓库是上下文组装器。它负责对代码地图、记忆、任务清单做最终的优先级编排,并将其优化为一个适合当前模型的提示词结构。不同的模型对上下文格式的敏感度不同,有些模型适合用 XML 标签分隔不同板块,有些更适合用 Markdown 标题,这个组装器内部定义了一套描述不同模型的配置文件,你可以按自己的偏好调整。
第七个仓库是本地运行沙箱。很多 AI 生成的代码如果不实际跑一遍,你很难发现其中隐藏的错误。沙箱基于容器,在每次完成一轮修改后自动在隔离环境里构建和运行测试,并且把失败日志反馈给下一轮生成过程。这个闭环极大提高了 AI 生成代码的可用率。
第八个仓库是指令模板库。我把日常开发中高频碰到的几十类任务,比如“重构某个函数”、“补充单元测试”、“修复某类静态检查告警”,都整理成了带占位符的模板。模板库和记账模块联动,通过记录每次使用模板后的 token 成本和修改成功率,来筛选出最有效的模板形态,这个模块相当于一套持续进化的提示词优化系统。
第九个仓库是核心命令行入口,负责把前面八个仓库统一封装成一套流畅的命令行工具。你不需要记住每个仓库的单独配置方法,只需在系统初始化时指定好各模块的配置路径,就能直接在终端通过统一的命令来调用。这个入口同时集成了彩色输出和交互式确认,适合那些不习惯直接改 JSON 配置的开发者。
六、从零部署这套工具链的具体流程
如果你已经看过上面这些模块的介绍,可能想知道从零开始跑起来到底要多久。以我自己的项目经验来说,在一台干净的 Linux 开发机上,从克隆代码到跑通第一个完整的记忆注入流程,大约需要四十分钟,前提是你对命令行和 Git 的基本操作比较熟悉。
第一步是环境准备。这套工具链的主体部分用的是脚本语言实现,运行时依赖单个常用运行时环境,以及一个轻量级本地数据库客户端。建议使用当前主流的稳定版本 LTS 作为运行时,数据库客户端则直接使用系统包管理器安装的预编译版本,避免自己手工编译耗时间。我试验过在其它系统上运行,只要没有涉及特有的系统调用,基本都能正常工作,但官方最推荐的环境还是 Linux,日常开发最好也在这个环境里跑。
第二步是仓库拉取。九个仓库每个都要克隆到本地目录,建议放在同一个工作区文件夹下面,这样便于统一管理环境变量和配置路径。仓库之间没有隐式的路径约定,而是通过一个总的配置文件明确指向各自的存放位置,所以你也可以把它们放到不同目录,只需在配置文件里如实填写绝对路径就行。
第三步是初始化配置。拷贝一份配置模板,然后打开文件修改三个必备参数:项目名称、代码仓库路径以及依赖的模型接口配置。模型接口配置里需要填你的请求端点、密钥或者本地模型的监听地址。如果你只用兼容通用接口的模型服务,可以直接沿用默认的端点和请求格式,只需替换密钥即可。
第四步是启动依赖服务。先把记忆服务和记账服务启动起来,因为它们是其他模块的前置依赖。启动成功后你会看到终端输出一个本地监听地址,代表着服务已经正常运行。此时可以用自带的健康检查命令验证一下接口状态,如果返回正常,就可以进行下一步了。
第五步是生成第一份代码地图。切换到代码地图仓库,在命令行中传入你的项目路径,运行生成命令。第一次生成时因为要扫描整个仓库,耗时可能会长一些,之后再次运行则因为增量缓存的存在,速度会快很多。生成完成后,先手动打开那份 Markdown 摘要,看一下是否涵盖了项目中最重要的目录和模块。如果没有,检查一下你的源码目录是否被误排除了。
第六步是验证记忆注入。在命令行工具中输入一条测试指令,告诉 AI“把项目根目录下所有工具函数统一调整到命名空间下”。执行后观察系统提示词是否带着生成好的代码地图及记忆内容。如果你在调试日志里看到了注入的内容,说明整条链路已经打通了。
第七步是接入记账服务。把配置里的请求代理地址改成记账模块的监听地址,然后随便发起一次对话,再打开记账数据库的表,就能看到一条实时写入的 token 消耗记录。到这里,整套工具链的部署就完成了。
以上步骤听上去不少,但实际执行中每一步的反馈都很直接,不太需要反复试错。如果你只是暂时需要一个模块,可以不必全部启动这些服务,它们共用一套彼此独立的设计,能单独使用而不互相牵连。
七、真实使用中的场景复盘:旧项目抢救与新生项目约束
我一直觉得,工具链的价值不体现在演示视频里,而是在真实项目的复杂场景里更让人印象深刻。这里分享两个近期真实项目的使用复盘,希望能帮助你理解这些模块之间是怎么协作的。
第一个场景是我接手一个维护了两年的遗留项目,代码量大,文档少,核心开发人员已经离职。我做的第一件事不是去看代码,而是先对代码库跑地图生成命令,并让助手按照已有代码梳理出关键的模块依赖关系。这个过程需要先扫描并识别大量的数据表映射和外部服务调用,地图工具本身只需要基础配置和几轮分析就能完成。
有了代码地图之后,我让 AI 基于地图索引标识出三个最有价值的重要文件,再由开发人员按记忆库的要求补充了这些文件的设计意图和演变历史。记忆模块负责存储这些文档化信息,并从那以后,每次让 AI 改动相关模块时,这些背景知识都会自动注入。从那以后几周的维护性开发,AI 生成的代码没有再出现过对旧逻辑的误判,项目的上下文连续性得到了很大的改善。
第二个场景是新项目启动初期,我需要在三天内搭出一个具备基础功能的演示版本。这种情况下,token 消耗往往会因为反复尝试和调试而失控。我把记账模块的告警阈值调低了一档,让每次超过平均消耗的请求都能被及时发现。
这个过程中我印象很深的是,任务拆分引擎和本地沙箱组合带来的效率提升。过去直接让 AI“实现用户登录模块”,经常会得到乱糟糟的第一版代码。现在让它先按子任务拆分,比如先定义数据模型、再做会话接口、最后写中间件鉴权,每步完成都跑一次测试。三步走下来,每步的重试次数都控制在一次以内。记账模块的数据也证实,这套流程的产出效果更稳定,平均成本远低于一步到位的方案。
在沙箱里跑测试的时候,第一次跑出一个数据竞争导致的偶发失败,当时模型以为修好了,但沙箱反复跑了三次才让它真正承认修复不完整。这个过程虽然在纯对话模式下会让人烦躁,但有了沙箱的自动化反馈,我就完全不需要守着等结果,只需要在几轮之后回来看日志就好。
八、常见问题与排查经验速查
部署和使用这套工具链的过程中,肯定会遇到一些问题,下面的清单是我自己踩过或帮别人排查过的高频问题,可以当速查表用。
代码地图扫描结果不完整
表现是生成的目录结构里少了实际存在的源码目录,或者符号索引数量明显偏少。绝大多数原因在于默认的排除规则过于激进,把源码目录误判成了构建产物或者依赖目录。解决方法是打开扫描配置文件,查看排除列表,再把误判的目录移除。另一个常见原因是符号提取插件不支持该项目用到的某些动态语法特性,导致部分函数声明没有被识别,这种只能暂时把相关文件手动补充进代码地图的额外说明区。
记忆模块召回的内容和当前任务不匹配
举一个例子:你在改前端搜索组件,记忆模块却返回了一些后端接口的优化约定。排查的第一步是检查你的记忆条目里的关键词设置,关键词过于宽泛是召回不精准的重要原因。我建议把关键词设计成“模块名加领域动词”的组合,比如“搜索组件防抖策略”。第二步是检查上下文组装器的配置,看它在注入的时候是否按照命名空间做了过滤。命名空间配错会导致跨项目泄漏,在我早期使用的时候也遇到过,后来通过全局搜索这条记忆到底属于哪个项目,发现是复制配置时把项目名带错了。
记账数据出现明显的重复计费
如果你发现在代理日志里,同一次对话消耗被记录了两次,大概率是你把请求同时指向了记账代理和上游服务的官方通知钩子。记账模块本身不依赖任何外部通知,只依赖自己转发层记录的请求数据。检查一下配置文件,看是不是无意中同时开启了两个上报渠道。另外在调试时如果多次手动重启服务,也可能会把重试请求重复记入库中。我给记账表加了一个唯一索引来应对这种情况,但如果你拉取的版本比较旧,可以自己加上这个约束。
本地沙箱构建超时
这个问题通常发生在沙箱默认资源上限设置得比较小,而项目的核心服务依赖较重的情况下。你可以分两步排查:先单独在本地跑一次构建命令,确认不是构建脚本本身的问题;如果本地构建能通过,再将沙箱的超时时间调大一档,并适当增加内存限制。如果是涉及到需要访问外部依赖源的项目,注意沙箱是否能访问到预期地址,网络策略错误也会导致卡在依赖获取阶段。
记忆和代码地图信息冲突时以谁为准
我的建议很明确:代码永远是最新的事实来源。代码地图是从实际代码仓库实时生成的,所以一旦发现记忆库里的描述和代码现状不匹配,优先以真实代码为准,同时启动一次记忆更新流程,让 AI 重新分析当前代码,把过时的记忆改成新约定。不能反过来让代码迁就记忆,否则你会得到一个被旧规则束缚而无法修改的仓库。
不同语言项目的地图生成速度差异很大
不少人反馈大型动态语言项目生成地图特别慢,而静态编译语言项目则会快很多。静态分析对弱类型语言的识别能力有限,需要加载更多启发式规则,这就会明显增加扫描耗时。如果你的项目非常庞大,可以先只针对核心模块的小范围目录进行地图生成,把生成范围缩到当前任务真正涉及的区域里,速度会快很多。
九、我把自己锁死在“小步快跑”模式之后的体会
这套工具链的核心不是某一个仓库,而是它形成的一整套开发节奏。我是那种不希望 AI 一次给我生成五百行代码的人,因为那样出错了很难定位,像是一个巨大的黑盒。现在我会把一个大功能拆成很多个小步骤,让人工提供思路的引导,让工具把这些思路迅速转成可验证的代码片段。
有了记忆和代码地图,AI 不再需要重新摸索项目背景,可以更快地进入特定情境里进行工作。有了 token 记账,每一笔花销都有清晰的来龙去脉,让我能判断某个方案是否执行起来成本过高,从而及时更换路径。有了本地沙箱,每次修改后能立刻看到反馈,比起反复阅读代码来推测是否正确,这种即时验证的方式要高效得多。
如果要用一句话来总结我个人对这套项目的感受,我最大的体会是“让 AI 开发进入可观测、可回溯、可控制的状态,才让它真正成为生产工具”。如果只给出一个建议,我想说的是:不要一次性部署全部九个仓库,你可以先从代码地图加记账模块开始,跑顺了再引入记忆模块,逐步搭建自己的 AI 编程代理工作流。这九个仓库全部开源在 MIT 协议下,希望这些代码思路能给你带来一些灵感和帮助。