一份构建者指南,涵盖四次训练运行、24个评估决策,以及隔离测试结果与实际系统性能之间出人意料的差距。
AI translation, not an official translation. Refer to the original for technical details.
Adapted from @Av1dlive# 如何使用 Kimi K3 构建智能体记忆工厂(构建者指南) 我将向你展示我实际测试了什么、哪些失败了,以及哪些内容留下了价值。 4次训练运行。24个评估决策。一个我没有预料到的结果…… 我的模型在12个隔离测试中全部通过,然后在实际运行的系统中只通过了12个中的5个。 提示词、纠正过程,以及为什么简单规则几乎打败了它。 TLDR;如果你不想阅读这2690个字——关于我如何使用一个 AI 模型找到最接近 AI 智能体记忆的解决方案并创建记忆策略模型——你可以直接前往 GitHub 仓库,那里有所有实验结果。https://github.com/codejunkie99/continual-memory-policy-model ## 引言 我的记忆模型在12个验证案例中通过了12个。然后我将它连接到实际系统,它只答对了5个。 测试和实际运行的系统对它的要求是不同的。 我希望 Claude Code 和 Codex 能够共享有用的项目知识,而无需重新训练任何一个智能体。 这促使我建立了一个独立的记忆服务,由一个小模型来决定如何处理这些笔记。 本项目中所有代码均由 Kimi K3 编写。 以下是其背后的选择、失败的运行过程,以及你可以尝试的配置。结果涵盖 v1 至 v4 版本。 这是实验性软件,而非生产级记忆服务。 # 开始之前的六个术语 - 记忆(memory):关于项目保存的笔记,而非计算机的内存(RAM)。 - 策略(policy):选择如何处理这些笔记的流程。 - 权重(weights):模型内部影响其输出的学习数字。 - 微调(fine-tuning):针对特定任务的额外训练。 - LoRA:低秩适配。它在保持原始模型不变的情况下训练小型附加模块。 - MCP:模型上下文协议。它允许智能体调用另一个程序提供的工具。 其他术语在出现时会加以解释。完整词汇表见文末。 # 我如何与 Kimi K3 合作 Kimi K3 编写了代码。我指定了我想要的内容,并随着构建进展不断修改需求。 因为在我看来,它是目前最好的开源模型。 我为保存的事实和模型训练分别指定了独立的调度方案。 我选择了 LFM2.5-VL-3B,询问了关于 MLX Studio 的问题,后来又请求集成 Claude Code 和 Codex。 实现内容逐渐扩展,涵盖了 SQLite 存储、操作检查、训练导出、适配器评估以及 MCP 工具。 编码工作流运行了这些检查。我没有亲自编写这些函数,也没有手动输入每一条测试命令。 ## 我们检查了什么 第一份训练报告显示保存了一个适配器。它尚未被批准投入使用;实际运行的系统仍需测试。 随后我询问了记忆是否真正有帮助,以及私密内容是否可能泄露。v4 报告记录了36个通过的测试,以及一个包含24个步骤的评估流程。 这些检查告诉我们运行了什么、通过了什么。它们并不能证明生产环境下的安全性。 训练脚本不是唯一的检查项;运行中的服务同样重要。 # 1. 将事实存储在模型之外 假设一个项目更改了其部署命令。智能体在下一个任务中应该使用新命令,而不需要先进行一次训练运行。 该命令应当存储在数据库中。模型的职责是选择如何管理该记录。 1. SQLite 数据库存储笔记及其修订版本。 1. 策略选择一个记忆操作。 1. 普通代码检查并执行该操作。 操作类型包括 WRITE、UPDATE、DELETE、LINK、COMPACT 和 NOOP,分别用于添加、修改、停用、关联、合并或保持笔记不变。 模型不编写数据库命令。执行更新时,由外部代码提供目标记录和替换内容。 ## 从基线出发 我首先构建了一套基于规则的策略。它让我能在训练生效之前对记忆存储进行测试,也为后续的学习模型提供了一个具体的超越目标。 如果存储的命令有误,我希望能检查该记录并加以纠正,而不是去猜测是哪次训练引入了这个错误。 NOOP 存在也是出于同样的考虑。有些消息不值得留下永久笔记。如果把所有内容都保存下来,下一个智能体将不得不面对更多需要整理的材料。 # 2. 我为何选择 LFM 我最初考虑的是 Qwen,后来选择了 Liquid AI 的 LFM2.5-VL-3B。选择它的原因是我能让本地训练流程顺利运行。 Liquid 提供了一个 8 位的 MLX 检查点,以紧凑格式存储模型参数。mlx-vlm 训练器支持该检查点。 ## MLX Studio 并非训练器 我的 Mac 配备了 48 GB 统一内存。我们审查过的 Leap 方案需要 NVIDIA CUDA 硬件。 我们审查的 MLX Studio 版本没有微调界面,因此我使用了独立的 mlx-vlm Python 训练器。 下载大小为 3.74 GB。修复数据集加载器的兼容性问题后,完成一个训练步骤的峰值内存占用为 5.693 GB。 ## 未作比较的内容 LFM 还具备处理图像的能力。我在此次任务中未使用该功能,因此无法将其列为该模型更适合此任务的理由。 最终的选择取决于四项实际检验: - 可用的检查点。 - 训练器支持。 - 本地更新成功完成。 - 服务可验证的有效输出格式。 我未曾在相同数据上对较小的纯文本模型进行比较。 我也未比较推理时间、能耗或不同模型系列之间的任务成功率。 对于六个操作标签而言,较小的纯文本模型或许已经足够。我没有进行必要的对比实验来得出相反的结论。 ## 下一步的比较方向 如果重新选择,我会给规则系统、较小的纯文本模型和 LFM 提供相同的示例与测试,然后比较结果和运行成本。让一个模型成功完成本地训练,并不能告诉我它是否是最佳选择。 ## LoRA 的作用 LoRA 添加了一组可训练的数值数组,称为矩阵,这些附加内容共同构成一个适配器。 用转向来类比有助于理解:发动机保持原位,而一个较小的调整改变了整个系统的行为方式。 Rank-8 配置训练了 12,230,656 个参数,占训练器所暴露参数总量的 0.392%。Rank 控制着附加内容的规模。 原始权重保持固定不变;适配器仅针对语言层,而非图像处理部分。 ## 训练答案格式 我向训练器提供了示例与预期答案的配对数据,这属于监督训练。这些训练轮次并非通过完成智能体任务所获得的奖励来学习。 我使用了仅针对补全部分的损失函数,即对答案而非输入提示进行评分。我需要的是一个有效的操作调用。 训练器将预测答案与提供的目标进行比较,并相应调整适配器。 ## 适配器的实用价值 适配器为我提供了一个独立文件,可在不改动基础模型的情况下进行版本管理与对比。 我使用了8阶(rank 8),但没有测试这是否是最优设置。我也没有将这条路线与训练全部权重的方案进行比较。 # 3. 第一个版本不断输出 write ## 四次尝试一览 ## v1:每次给出相同的答案 第一个适配器完成了51个训练步骤。随后在每个诊断用例上都输出了 WRITE,得分为 0/9。 训练已经结束,但策略仍然无法完成任务。 这个结果并未解释全部问题所在。为了下一次尝试,我对各操作的样本进行了均衡处理,并确保训练过程对答案进行评分。 ## v2 和 v3:针对错误进行改进 在 v2 中,我将96个样本均衡分布在六种操作上:每种16个。经过192个训练步骤后,得分为 7/9。两处错误都将 LINK 与 COMPACT 混淆了。 这两个操作的职责不同:链接用于连接独立的笔记,而压缩则是将它们合并。下一轮训练需要更多关于这一区别的样本。 在 v3 中,我使用了回放(replay)方式:利用精选样本进行进一步训练。该集合包含112个样本,其中 LINK 有32个,其余每种操作各16个。 最终得分达到了 9/9。 ## 一个真实示例,包括其中的错误 此输入出现在已保存的回放数据中,以及索引为5的诊断用例中。它是合成数据,并非用户的私人对话。 训练目标以如下参数命名了 memory_action: 记录的 v2 输出为: 经过回放训练后,v3 返回: ## 这个示例的隐患 可以看到修正之处:v3 返回了 LINK,而 v2 返回的是 COMPACT。 对于这个操作选择示例而言,空载荷是有意为之的。但仅凭这个答案本身,无法告知数据库需要更改哪些记录。 不过请注意输入内容。它包含的是一个用例编号,而非笔记的实际内容。模型可能只是学会了这个捷径。 这个相同的输入也存在于训练数据中。修正后的答案体现的是在已知用例上的进步,而非理解陌生笔记的能力。 ## 随后我将 v3 接入了系统 在冻结 v3 之后,它通过了一个独立的12用例验证集。未经修改的基础模型只通过了其中一个。 随后我将其连接到运行时——即执行内存操作的程序。得分下降至 5/12。 只有50%的响应符合所需的输出结构。 有两件事发生了变化。 - 运行时提供的是记录计数和重复状态,而非合成用例标识符。 - 它还要求提供完整的工具调用,而不仅仅是一个操作词。 ## v4:针对我们实际使用的接口进行训练 我一直在测试一个与服务所用接口不同的接口。 如果程序无法读取完整的答案,那么一个正确的操作名称也毫无意义。 训练样本需要同时匹配正在运行的服务的输入格式和输出检查要求。 在 v4 中,我使用运行时的输入特征生成了288个样本,每种操作48个。答案采用了其精确的输出格式。 训练运行了288个步骤,峰值内存占用报告为7.213 GB。 各版本之间同时发生了多项变化,因此无法将改进归因于某一个修复。若要做到这一点,需要每次只改变一个因素进行对比。 # 4. 基于规则的系统几乎与模型持平 在同一段经过人工编写的24步序列上,v4 系统正确完成了全部24个操作,而基于规则的系统完成了23个。 两者均获得了0.77的效用值——这是该项目对内存结果的评分指标,并非开发者生产力的衡量标准。 多对了一个操作,效用分数持平。 ## 部分输入已经包含了答案 甚至有些输入直接注明了所请求的操作:例如 requested_op: UPDATE。 模型看到的特征有限。更大的智能体仍然需要识别对话中的有用信息,并找到相关记录。 ## 那么为什么还要费心训练模型呢? 对于这个版本,我会从规则入手。规则可以避免训练工作、模型运行时间以及额外的故障场景。 ## 什么会改变我的想法 我感兴趣的是,后续的使用是否能让策略学到一些我原本需要持续编写规则才能处理的内容。 一条笔记的价值可能取决于其存在的时长、被修正的历史、检索历史,以及后续任务的结果。 举例来说,未来的策略或许能学会:何时反复修正意味着应该替换一条笔记,或者何时两条相关笔记应当保持独立。 这才是真正的研究问题。v4 尚未给出答案。 输入本身也需要改进。计数和操作提示并不能告诉模型一段对话的含义。 更丰富的信号需要精心设计,在适用的情况下还需征得同意,并经过隐私审查。 ## 我会采用的测试标准 如果学习到的策略在新任务上的帮助足以抵消其成本和延迟,我才会保留它。 规则也会接受相同的任务测试。如果有用的结果保持一致,我就保留规则。 无论哪种方式,隐私检查都会保留在普通代码中。我不希望由训练出来的策略来决定某项隐私限制今天是否适用。 ## 测试时不要泄露答案 一个有效的对比测试应尽可能去除明确的操作提示。否则,模型可能只是在重复输入中已有的答案。 我还会在训练与评估之间区分项目和时间段。 该测试应在报告任务结果的同时,报告每次决策的成本。如果准确率的小幅提升会带来显著延迟,那可能得不偿失。 # 5. 配合 Claude Code 或 Codex 试用 本地 MCP 服务器为 Claude Code 和 Codex 提供了相同的记忆工具。两个客户端的模型均无需微调。 以下是两个智能体共享一条修正内容的示例: 1. Claude Code 在执行部署任务前调用 memory_search。 1. 你确认已保存的命令已过时。 1. 它通过 memory_observe 提交修正。策略选择一个动作,代码对其进行验证。 1. 后续的 Codex 会话从同一数据库和项目范围中检索到已修正的命令。 1. 确认任务结果后,智能体携带检索标识符调用 memory_feedback。 该标识符将反馈与之前的搜索关联起来。仅检索一条笔记并不意味着它起到了作用。 这让你有具体的内容可供审查:旧命令、替换命令,以及后续任务的结果。你不必凭空猜测"更好的记忆"究竟意味着什么。 ## 无需下载模型即可开始 你需要 git、Python 3.11 或更新版本,以及你打算使用的 Claude Code 或 Codex CLI。以下命令适用于 macOS 或 Linux shell。 使用你的项目目录。 从基于规则的策略开始。你不需要模型权重或 GPU。首先验证服务能够保存一条笔记并再次找到它。 固定的版本与本文匹配。演示成功后会打印 demo complete,并写入 runtime/demo-output/demo.json。 将其生成的数据与下方使用的空 memory.db 分开存放。 ## 连接 Claude Code 或 Codex 在同一终端中,注册其中一个客户端,或同时注册两者: 假后端是非模型测试配置,而非经过训练的适配器。 注册信息会保留在客户端配置中。末尾的集成指南说明了应使用哪个作用域。 ## 验证保存与检索是否正常 打开一个全新的代理会话,若有提示则批准服务器。要求其调用: 检查实际工具返回的结果。 - 第一个结果应在全新存储上报告 ok: true 和 WRITE。 - 搜索应返回标记及检索标识符。 该标记应在重启后依然存在。这是你的第一项检查,而非编码质量更优的证据。 本文中,服务器级别的操作序列已在干净环境中重新运行。 客户端命令语法已单独验证,两个客户端均未注册新服务器。 ## 为代理设定操作规则 将"先搜索再工作"、"仅持久化已修正内容"以及"结果反馈"指令写入 Codex 的 AGENTS.md 或 Claude Code 的 CLAUDE.md。 切勿将召回的文本视为指令,也不得存储机密信息。 1. 若搜索结果为空,请检查数据库路径和作用域。作用域标签用于组织记录,并非安全边界。 1. 若某次观察返回 NOOP,这可能仅仅意味着没有值得保存的内容。 1. 当上述步骤正常运行后,下方链接的独立 MLX 流程将介绍如何使用经过训练的适配器。上述命令用于测试基线,并不复现训练运行。 ## 将私有产物置于 git 之外 # 6. 仍待测试的内容 数据库可以即时变更,模型不会在每次对话后重新训练。 我将两个调度分开,以便操作员可以审查示例、测试候选版本,并保留之前的适配器。 此处存在一个缺口:适配器可以被直接加载,绕过注册表审批。该审批步骤并不能保护系统的所有入口路径。 拟议的下一项实验将对比无记忆、基于规则的记忆和学习型记忆在新任务上的表现。 衡量指标包括:任务成功率、陈旧记忆错误率以及额外耗时。 ## 究竟是哪条记录起了作用? 任务成功并不能告诉我是哪条记忆发挥了作用。v4 的结果来自生成的监督示例,而非基于真实任务反馈训练的策略。 若代理检索了三条记录后任务成功,这并不能说明是哪条记录起了作用。其中一条可能无关紧要,另一条可能是错误的。 要从这些结果中进行训练,我需要在特定的记忆决策与其后续影响之间建立更清晰的关联。 当前的归因路径将反馈与创建记录的事件绑定,无法追踪此后的每一次修订。 当一条有用的记录在被使用之前已经过多次更新时,这一点尤为重要。 ## 下一轮运行 将示例、适配器版本和评估条件一并保存。 在相同的未经改动的任务上测试候选版本,然后将部署作为独立决策处理。 我现在可以测试这一学习闭环。但我仍需证明,基于后续结果进行训练能够产生一个值得使用的策略。 在此之前,规则是模型的竞争对手。 代码、报告及配置指南均在末尾附有链接。请先从规则入手,再尝试经过训练的适配器。 # 参考:v4 训练设置 这些是已记录的设置,并非经过验证的最优值。下方链接的运行时报告包含训练详情。 # 参考:证据所能说明的内容 # 完整术语表 以此作为参考。 ## 系统及其记忆 ## 训练小型模型 ## 结果与智能体连接 # 代码、报告与配置 - 代码库:实现、测试与快速入门。(https://github.com/codejunkie99/continual-memory-policy-model) - 本地训练报告:Mac 配置、LoRA 设置与早期训练运行。(https://github.com/codejunkie99/continual-memory-policy-model/blob/main/outputs/MLX_FINETUNE_REPORT.md) - 运行时验证报告:v3 运行时故障、修订后的 v4 训练运行与本地验证检查。(https://github.com/codejunkie99/continual-memory-policy-model/blob/main/outputs/LIVE_VALIDATION_REPORT.md) - 规则对比 v4:记录的操作得分与等效效用结果。(https://github.com/codejunkie99/continual-memory-policy-model/blob/main/outputs/live-v4-active/live-evaluation.json) - Claude Code 与 Codex 配置:安装、客户端注册与 MLX 适配器说明。(https://github.com/codejunkie99/continual-memory-policy-model/blob/main/docs/AGENT_INTEGRATION.md) - 代码库图表:系统、数据存储与学习工作流的可编辑图表。(https://github.com/codejunkie99/continual-memory-policy-model/tree/main/docs/diagrams)