为什么需要 MemoryLLM 原生没有记忆大语言模型本质上是类似y f(x)的函数其中x是用户输入模型参数A、B、C在训练结束后就固定了不会因为输入的改变而改变因此原生 LLM 没有任何记忆能力我们之所以觉得大模型有记忆是因为采取了上下文注入的方式把历史对话S1、S2……直到最新的输入Xn拼成一个很长的序列丢给 LLMLLM 凭借注意力机制看到历史记录从而看似有记忆。上下文窗口的局限性即使采取了上下文注入的方式存在两个问题问题说明存储空间有限对话轮次越多输入序列越长资源负载越重最终可能导致 LLM 无法执行注意力扩散上下文过长时LM 无法把注意力正确放在关键内容上导致幻觉或答非所问因此需要限制上下文窗口Context Window目前业界主流采用200K tokens作为窗口大小——这个数值是通过大量实验得出的平衡点一方面支持足够的上下文另一方面避免注意力涣散朴素方案Sliding Window原理当窗口填满时丢弃旧内容移入新内容缺陷以前的内容大概率不如新内容重要但很容易举出反例比如用户在第一轮对话中做了自我介绍、设置了个性化偏好如请用中文回答一旦被滑动窗口划走这些关键信息全部丢失。主流方案一基于数据库类 RAG对话记录本质是一串文本与公司文件库没有本质区别。天然适合用传统 RAG检索增强生成的方法处理建立数据库 →存储切分后的文本块→ 检索 → 加载回上下文。存储流程切块Chunking如果历史消息很长如几千字可以按段落或按字数切分添加元信息提取 topic、用户偏好等语言信息一并嵌入到 chunk 中插入数据库使用 Elasticsearch 等数据库支持关键字搜索BM25和向量搜索Vector Embedding甚至混合搜索检索流程检索时主要有两种套路方案 A止取不经过 LLM将用户 query 直接 embedding 成向量在数据库中进行比对检索关键词搜索 BM25 评分优点速度快不需要额外消耗 token缺点无法理解语义对复杂查询的召回效果有限方案 B经过 LLMReAct 模式由 LLM 分析用户 query生成更合适的搜索方案确定关键词等从数据库检索到一堆文档后让 LLM 做 reasoning 判断内容是否足够如果不够调整优化 query重新检索refine优点语义理解能力强检索更精准缺点消耗更多 token 和时间最终处理无论哪种方案检索得到的 chunk 都被插入到上下文 Context Window 中再附上 query一起交给 LLM 处理。主流方案二基于 Markdown蒸馏压缩这是Claude Code使用的方法被很多人归为业界标准。但核心痛点是写代码该方案有天然的优势需要具体问题具体分析。三层记忆结构第一层Memory长期记忆特点跨 session 永远生效永久加载到上下文窗口。典型内容用户编号Profile用户偏好User Preference如生成内容时尽可能少辅助信息多用代码回答全局约束Constraints如删文件时必须提示我第二层Topics专题记忆特点按 topic 划分每个 topic 是一个独立文件。典型场景用户让 agent 写数据库接入代码会涉及 topicdatabase_deployment从中提取结构化信息type例如 MongoDBversion例如 8.0constraints约束条件更新机制当内容发生变化时如 version 从 8.0 升级到 8.1在 topic 文件中记录Historical信息便于回溯和查找 bug。这样 LM 就能意识到旧记忆可能已过时。加载机制只有当当前对话涉及某个 topic 时才会把对应 topic 内容加载到上下文窗口中。第三层Transcript兜底层原生的原始对话记录保存在 message 文档中。作用万一前两层都命中不到相应信息可以从原信息中回溯查找。注从性能上看Transcript 的查找效率不如第一种 RAG 方法。但若能在前两层命中关键内容效果往往更好。结构化维护方法Markdown 本质上是纯文本文件手动维护更新非常痛苦如需要读取文件、定位行、删除内容。标准做法加载时将 Markdown 结构化为 JSON / Dict 数据结构更新时让 LLM 进行 distill蒸馏压缩按预定义的 key 生成结构化 Dict逐项更新 Dict 内容落盘时将 Dict 重新渲染回 Markdown 格式输出这样做既规范又稳定避免 key 偏移的问题。冰与火Key 定义的 Trade-off在 distill 过程中最核心的不稳定点在于key 是预定义的还是让 LLM 自由生成。最冰端Predefined Keys把固定的 key如profile、user_preference、constraints等 20 个 key写入 system prompt让 distill agent 按这 20 个 key 归纳总结优点非常稳固即使 LLM 生成了同义词如生成了overview而不是profile可以通过 merge 代码将其映射回正确 key再丢回给 LLM 让它生成一模一样的 key缺点不够灵活可能无法覆盖新场景最火端LLM 自定义 Keys所有 key 都由 LLM 生成优点更动态可以适应新场景缺点不可控。例如第一轮 distill 生成了overview和focus第二轮可能生成profile和concentration需要多轮次判断overview与profile是否应该 merge新 key 是 append 还是 update业界中庸之道取长补短在中间状态平衡预定义足够广泛的 key让 LLM 不需要自造词也保留让 LLM生成新 key 的能力既保证稳定性又保持灵活性如何让 LM 知道存在哪些 Topics需要解决一个问题LM 怎么知道该加载哪个 topic方法一主动搜索给 agent 一个 agent 去遍历所有 markdown 文件列出有哪些 topic 可用。方法二轻量化写入 Memory在 Memory 文件中维护一个轻量化的 key如known_topics只写简短简介因为 Memory 是永远加载的不能太长。LM 看到这个列表就知道有哪些 topic 可以加载避免每次都做遍历操作。两种方法对比方法优点缺点主动搜索全面多一次 LLM 调用 多一次遍历额外 token 消耗和时间开销写入 Memory减少调用开销需要维护且 Memory 会变长总结Memory 是 Agent 设计中的重中之重。好的 memory 设计几乎在很大程度上决定了 Agent 到底好不好用。对比维度数据库方案IAGMarkdown 方案Distill核心原理把历史当文件检索召回把历史蒸馏压缩成结构化信息优点检索精准支持混合搜索结构化程度高可回溯Claude Code 在用缺点原生数据检索慢distill 过程不稳定key 定义有 trade-off适用场景需要精确匹配、关键词搜索写代码、写文档等有明确 topic 的场景