- 短期记忆,即线程范围的记忆,通过在会话中维护消息历史来跟踪正在进行的对话。LangGraph 将短期记忆作为智能体状态的一部分进行管理。状态通过检查点持久化到数据库,以便随时恢复线程。短期记忆在图被调用或某个步骤完成时更新,状态在每个步骤开始时被读取。
- 长期记忆跨会话存储特定用户或应用级别的数据,并在对话线程_之间_共享。它可以在_任何时候_和_任何线程_中被回忆。记忆的作用域可以是任意自定义命名空间,而不仅限于单个线程 ID。LangGraph 提供了存储(参考文档)以便保存和回忆长期记忆。

短期记忆
短期记忆让你的应用程序能够在单个线程或对话中记住之前的交互。一个线程将会话中的多次交互组织在一起,类似于电子邮件将消息分组到单个对话中的方式。 LangGraph 将短期记忆作为智能体状态的一部分进行管理,通过线程范围的检查点持久化。该状态通常可以包括对话历史以及其他有状态的数据,例如上传的文件、检索到的文档或生成的工件。通过将这些存储在图的状态中,机器人可以访问给定对话的完整上下文,同时保持不同线程之间的隔离。管理短期记忆
对话历史是最常见的短期记忆形式,而长时间的对话对当今的 LLM 构成了挑战。完整的历史记录可能无法放入 LLM 的上下文窗口,从而导致不可恢复的错误。即使你的 LLM 支持完整的上下文长度,大多数 LLM 在长上下文中的表现仍然不佳。它们会被陈旧或偏离主题的内容”分散注意力”,同时还会面临响应时间变慢和成本增加的问题。 聊天模型通过消息接受上下文,这些消息包括开发者提供的指令(系统消息)和用户输入(人类消息)。在聊天应用中,消息在人类输入和模型响应之间交替出现,形成一个随时间不断增长的消息列表。由于上下文窗口有限,且富含 token 的消息列表成本较高,许多应用可以从使用手动删除或遗忘过期信息的技术中受益。
长期记忆
LangGraph 中的长期记忆允许系统跨不同对话或会话保留信息。与线程范围的短期记忆不同,长期记忆保存在自定义”命名空间”中。 长期记忆是一个复杂的挑战,没有放之四海而皆准的解决方案。然而,以下问题提供了一个框架,帮助你了解不同的技术:- 记忆的类型是什么?人类使用记忆来记住事实(语义记忆)、经历(情节记忆)和规则(程序记忆)。AI 智能体可以以同样的方式使用记忆。例如,AI 智能体可以使用记忆来记住关于用户的特定事实以完成任务。
- 何时更新记忆?记忆可以作为智能体应用逻辑的一部分进行更新(例如,“在热路径中”)。在这种情况下,智能体通常在响应用户之前决定记住哪些事实。或者,记忆可以作为后台任务进行更新(在后台/异步运行并生成记忆的逻辑)。我们在下面的章节中解释这些方法之间的权衡。
语义记忆
语义记忆,无论是在人类还是 AI 智能体中,都涉及对特定事实和概念的保留。在人类中,它可以包括在学校学到的信息以及对概念及其关系的理解。对于 AI 智能体,语义记忆通常用于通过记住过去交互中的事实或概念来个性化应用程序。语义记忆不同于”语义搜索”,后者是一种使用”含义”(通常是嵌入)来查找相似内容的技术。语义记忆是心理学中的一个术语,指存储事实和知识,而语义搜索是一种基于含义而非精确匹配来检索信息的方法。
档案
语义记忆可以通过不同方式管理。例如,记忆可以是关于用户、组织或其他实体(包括智能体本身)的单一、持续更新的”档案”,其中包含范围明确且具体的信息。档案通常只是一个 JSON 文档,包含你选择用来表示你的领域的各种键值对。 在记忆档案时,你需要确保每次都在更新档案。因此,你需要传入之前的档案并要求模型生成新的档案(或某些JSON 补丁应用于旧档案)。随着档案变得越来越大,这可能会容易出错,可以考虑将档案拆分成多个文档或在生成文档时使用严格解码来确保记忆模式的有效性。
集合
或者,记忆可以是一个随时间持续更新和扩展的文档集合。每个单独的记忆可以具有更窄的范围,更容易生成,这意味着你随时间丢失信息的可能性更小。LLM 更容易为新信息生成_新_对象,而不是将新信息与现有档案进行调和。因此,文档集合往往会带来更高的下游召回率。 然而,这将部分复杂性转移到了记忆更新上。模型现在必须_删除_或_更新_列表中的现有项目,这可能很棘手。此外,某些模型可能默认过度插入,而其他模型可能默认过度更新。参见 Trustcall 包,了解一种管理此问题的方法,并考虑使用评估(例如,使用 LangSmith 等工具)来帮助调整行为。 使用文档集合还将复杂性转移到对列表进行记忆搜索上。Store 目前支持语义搜索和按内容过滤。
最后,使用记忆集合可能会使向模型提供全面上下文变得具有挑战性。虽然单个记忆可能遵循特定的模式,但这种结构可能无法捕捉记忆之间的完整上下文或关系。因此,在使用这些记忆生成响应时,模型可能缺乏在统一档案方法中更易获取的重要上下文信息。

情节记忆
情节记忆,无论是在人类还是 AI 智能体中,都涉及回忆过去的事件或行动。CoALA 论文对此有很好的阐述:事实可以写入语义记忆,而经历可以写入情节记忆。对于 AI 智能体,情节记忆通常用于帮助智能体记住如何完成任务。 在实践中,情节记忆通常通过少样本示例提示来实现,智能体从过去的序列中学习以正确执行任务。有时候”展示”比”描述”更容易,LLM 能够很好地从示例中学习。少样本学习让你可以通过使用输入-输出示例更新提示词来”编程”你的 LLM,以说明预期行为。虽然可以使用各种最佳实践来生成少样本示例,但挑战通常在于根据用户输入选择最相关的示例。 请注意,记忆存储只是将数据存储为少样本示例的一种方式。如果你希望更多地参与开发,或将少样本示例与你的评估框架更紧密地关联,你也可以使用 LangSmith 数据集来存储数据,并实现自己的检索逻辑以根据用户输入选择最相关的示例。 参见这篇博客文章,展示了少样本提示如何提高工具调用性能;以及这篇博客文章,使用少样本示例将 LLM 与人类偏好对齐。程序记忆
程序记忆,无论是在人类还是 AI 智能体中,都涉及记住执行任务所用的规则。在人类中,程序记忆就像是执行任务的内化知识,例如通过基本运动技能和平衡感来骑自行车。而情节记忆则涉及回忆具体经历,例如第一次不用辅助轮成功骑自行车,或在风景秀丽的路线上难忘的骑行经历。对于 AI 智能体,程序记忆是模型权重、智能体代码和智能体提示词的组合,它们共同决定了智能体的功能。 在实践中,智能体修改其模型权重或重写代码的情况相当少见。然而,智能体修改自身提示词的情况更为常见。 优化智能体指令的一种有效方法是通过”反思”或元提示。这涉及使用当前指令(例如系统提示词)以及最近的对话或明确的用户反馈来提示智能体。然后,智能体根据此输入优化自己的指令。这种方法对于难以事先明确指定指令的任务特别有用,因为它允许智能体从其交互中学习和适应。 例如,我们构建了一个推文生成器,利用外部反馈和提示词重写来为 Twitter 生成高质量的论文摘要。在这种情况下,特定的摘要提示词难以事先明确指定,但用户批评生成的推文并提供如何改进摘要过程的反馈则相对容易。 以下伪代码展示了如何使用 LangGraph 记忆存储来实现此功能,使用存储来保存提示词,update_instructions 节点获取当前提示词(以及从 state["messages"] 中捕获的与用户对话的反馈),更新提示词,并将新提示词保存回存储。然后,call_model 从存储中获取更新后的提示词并使用它来生成响应。

写入记忆
智能体写入记忆主要有两种方法:“在热路径中”和”在后台”。
在热路径中
在运行时创建记忆既有优点也有挑战。从积极的方面来看,这种方法允许实时更新,使新记忆在后续交互中立即可用。它还提高了透明度,因为用户可以在记忆被创建和存储时收到通知。 然而,这种方法也带来了挑战。如果智能体需要一个新工具来决定将什么提交到记忆,可能会增加复杂性。此外,思考将什么保存到记忆的过程可能会影响智能体的响应延迟。最后,智能体必须在创建记忆和其他职责之间进行多任务处理,这可能影响所创建记忆的数量和质量。 例如,ChatGPT 使用 save_memories 工具将记忆以内容字符串的形式进行插入或更新,对每条用户消息决定是否以及如何使用此工具。参见我们的 memory-agent 模板作为参考实现。在后台
将记忆创建作为独立的后台任务提供了几个优势。它消除了主应用程序中的延迟,将应用程序逻辑与记忆管理分离,并允许智能体更专注地完成任务。这种方法还提供了在记忆创建时机上的灵活性,以避免冗余工作。 然而,这种方法也有其自身的挑战。确定写入记忆的频率变得至关重要,因为不频繁的更新可能使其他线程缺少新的上下文。决定何时触发记忆形成也很重要。常见的策略包括在设定的时间段后进行调度(如果发生新事件则重新调度)、使用 cron 计划,或允许用户或应用程序逻辑手动触发。 参见我们的 memory-service 模板作为参考实现。记忆存储
LangGraph 将长期记忆作为 JSON 文档存储在存储中。每个记忆都在自定义namespace(类似于文件夹)和独特的 key(类似于文件名)下组织。命名空间通常包含用户或组织 ID 或其他标签,使信息更易于组织。这种结构实现了记忆的层次化组织。然后通过内容过滤器支持跨命名空间搜索。
连接这些文档 到 Claude、VSCode 等,通过 MCP 获取实时答案。

