推广 热搜: 采购方式  甲带  滤芯  气动隔膜泵  减速机  减速机型号  带式称重给煤机  履带  无级变速机  链式给煤机 

谷歌白皮书:上下文工程:会话和记忆

   日期:2026-01-05 08:57:07     来源:网络整理    作者:本站编辑    评论:0    
谷歌白皮书:上下文工程:会话和记忆

从预测性 AI 到自主代理

人工智能正在发生变革。多年来,重点一直放在那些擅长被动、离散任务的模型上:回答问题、翻译文本或根据提示生成图像。这种范式虽然强大,但每一步都需要持续的人工指导。我们现在正见证范式的转变,从仅仅预测或创建内容的 AI,转向一类能够自主解决问题和执行任务的新型软件。

这个新前沿围绕着 AI 代理(AI Agents)构建。代理不仅仅是静态工作流中的 AI 模型;它是一个完整的应用程序,能够制定计划并采取行动以实现目标。它结合了语言模型(LM)的推理能力与采取行动的实践能力,使其能够处理模型本身无法独自完成的复杂、多步骤任务。关键能力在于代理可以独立工作,自行找出实现目标所需的后续步骤,而无需人类在每一步进行指导。

本文档是五部分系列文章的第三篇,作介绍了上下文工程(Context Engineering)、会话(Sessions)和记忆(Memory)在构建智能 LLM 代理中的关键作用。

作者: Kimberly Milam 和 Antonio Gulli

Google

2025年11月

目录

  • 简介 - 6
  • 上下文工程 - 7
  • 会话 (Sessions) - 12
  • 框架和模型之间的差异 - 13
  • 多智能体系统的会话 - 15
  • 跨多个智能体框架的互操作性 - 19
  • 会话的生产环境考量 - 20
  • 管理长上下文对话:权衡与优化 - 22
  • 记忆 (Memory) - 27
  • 记忆的类型 - 34
  • 信息类型 - 35
  • 组织模式 - 35
  • 存储架构 - 36
  • 创建机制 - 37
  • 记忆范围 - 38
  • 多模态记忆 - 39
  • 记忆生成:提取与整合 - 41
  • 深度剖析:记忆提取 - 44
  • 深度剖析:记忆整合 - 47
  • 记忆溯源 - 49
  • 在记忆管理期间考虑记忆血统 - 50
  • 在推理期间考虑记忆血统 - 52
  • 触发记忆生成 - 52
  • 记忆即工具 (Memory-as-a-Tool) - 53
  • 后台与阻塞操作 - 56
  • 记忆检索 - 56
  • 检索时机 - 58
  • 带记忆的推理 - 61
  • 系统指令中的记忆 - 61
  • 对话历史中的记忆 - 63
  • 程序性记忆 - 64
  • 测试与评估 - 65
  • 记忆的生产环境考量 - 67
  • 隐私与安全风险 - 69
  • 结论 - 70
  • 尾注 - 71

有状态和个性化的 AI 始于上下文工程。

简介

本白皮书探讨了会话 (Sessions) 和 记忆 (Memory) 在构建有状态、智能的 LLM(大型语言模型)代理中的关键作用,旨在通过这些概念增强开发者的能力,从而创造出更强大、更具个性化且持久的 AI 体验。为了使 LLM 能够记忆、学习并个性化交互,开发者必须在其上下文窗口内动态地组装和管理信息——这一过程被称为上下文工程 (Context Engineering)

本白皮书总结的核心概念如下:

  • 上下文工程 (Context Engineering)
    在 LLM 的上下文窗口内动态组装和管理信息的过程,以实现有状态的智能代理。
  • 会话 (Sessions)
    承载与代理进行的完整对话的容器,保存着对话的时间顺序历史和代理的工作记忆。
  • 记忆 (Memory)
    长期持久化的机制,用于跨多个会话捕获和整合关键信息,为 LLM 代理提供连续且个性化的体验。

上下文工程 (Context Engineering)

LLM 本质上是无状态的。除了训练数据之外,它们的推理和感知仅限于在单次 API 调用的“上下文窗口”中提供的信息。这带来了一个根本性问题,因为 AI 代理必须配备操作指令(明确可采取的行动)、用于推理的证据和事实数据,以及定义当前任务的即时对话信息。为了构建能够记忆、学习和个性化交互的有状态智能代理,开发者必须为对话的每一轮构建这种上下文。这种为 LLM 动态组装和管理信息的过程被称为上下文工程

上下文工程代表了传统提示工程 (Prompt Engineering) 的进化。提示工程专注于制作最佳的、通常是静态的系统指令。相反,上下文工程处理整个负载 (payload),根据用户、对话历史和外部数据动态构建具有状态感知的提示。它涉及策略性地选择、总结和注入不同类型的信息,以最大化相关性并最小化噪音。外部系统——如 RAG 数据库、会话存储和记忆管理器——管理着大部分此类上下文。代理框架必须编排这些系统,以检索并将上下文组装成最终的提示。

可以将上下文工程想象成代理的“备料”(mise en place)——就像厨师在烹饪前收集和准备所有食材的关键步骤。如果你只给厨师食谱(提示),他们可能会用手头已有的随机食材做出一顿还可以的饭菜。但是,如果你首先确保他们拥有所有正确的高质量食材、专用工具,并且清楚了解呈现风格,他们就能可靠地制作出色的、定制化的结果。上下文工程的目标是确保模型拥有完成任务所需的最相关信息,不多也不少。

上下文工程管理着包含各种组件的复杂负载的组装:

1. 指导推理的上下文 (Context to guide reasoning)

定义代理的基本推理模式和可用动作,指导其行为:

  • 系统指令 (System Instructions)
    定义代理角色、能力和约束的高级指令。
  • 工具定义 (Tool Definitions)
    代理可用于与外部世界交互的 API 或函数的模式 (Schemas)。
  • 少样本示例 (Few-Shot Examples)
    通过上下文学习 (in-context learning) 指导模型推理过程的精选示例。

2. 证据与事实数据 (Evidential & Factual Data)

代理进行推理的实质性数据,包括预先存在的知识和为特定任务动态检索的信息;它是代理响应的“证据”:

  • 长期记忆 (Long-Term Memory)
    跨多个会话收集的关于用户或主题的持久化知识。
  • 外部知识 (External Knowledge)
    从数据库或文档中检索的信息,通常使用检索增强生成 (RAG)1
  • 工具输出 (Tool Outputs)
    工具返回的数据或结果。
  • 子代理输出 (Sub-Agent Outputs)
    被委派特定子任务的专用代理返回的结论或结果。
  • 工件 (Artifacts)
    与用户或会话相关的非文本数据(例如,文件、图像)。

3. 即时对话信息 (Immediate conversational information)

将代理置于当前交互中,定义即时任务:

  • 对话历史 (Conversation History)
    当前交互的逐轮记录。
  • 状态/草稿板 (State / Scratchpad)
    代理用于即时推理过程的临时、进行中信息或计算。
  • 用户的提示 (User's Prompt)
    需要解决的即时查询。

上下文的动态构建至关重要。例如,记忆不是静态的;随着用户与代理交互或新数据的摄入,必须选择性地检索和更新记忆。此外,有效的推理通常依赖于上下文学习2(LLM 从提示中的演示学习如何执行任务的过程)。当代理使用与当前任务相关的少样本示例,而不是依赖硬编码的示例时,上下文学习会更有效。同样,RAG 工具也会根据用户的即时查询检索外部知识。

构建上下文感知代理最严峻的挑战之一是管理不断增长的对话历史。理论上,具有大上下文窗口的模型可以处理大量记录;实际上,随着上下文的增长,成本和延迟也会增加。此外,模型可能会遭受“上下文腐烂” (context rot) 的困扰,即随着上下文的增长,它们关注关键信息的能力会减弱。上下文工程通过采用策略动态地改变历史记录——例如摘要、选择性修剪或其他压缩技术——来直接解决这个问题,以在管理总 Token 数的同时保留重要信息,最终带来更稳健和个性化的 AI 体验。

这种实践表现为代理在每一轮对话的操作循环中的一个连续周期:

图 1. 代理的上下文管理流程
  1. 获取上下文 (Fetch Context)
    代理首先检索上下文——例如用户记忆、RAG 文档和最近的对话事件。对于动态上下文检索,代理将使用用户查询和其他元数据来确定要检索的信息。
  2. 准备上下文 (Prepare Context)
    代理框架动态构建用于 LLM 调用的完整提示。虽然单个 API 调用可能是异步的,但准备上下文是一个阻塞的、“热路径” (hot-path) 过程。在上下文准备好之前,代理无法继续。
  3. 调用 LLM 和工具 (Invoke LLM and Tools)
    代理迭代调用 LLM 和任何必要的工具,直到生成最终的用户响应。工具和模型的输出被追加到上下文中。
  4. 上传上下文 (Upload Context)
    该轮次中收集的新信息被上传到持久存储。这通常是一个“后台”过程,允许代理完成执行,而记忆整合或其他后处理则异步进行。

在这个生命周期的核心是两个基本组件:会话记忆。会话管理单个对话的逐轮状态。相比之下,记忆提供了长期持久性的机制,跨多个会话捕获和整合关键信息。

你可以把会话想象成你为特定项目使用的工作台或书桌。当你工作时,桌上摆满了所有必要的工具、笔记和参考资料。一切都触手可及,但也都是临时的,特定于手头的任务。一旦项目完成,你不会把整个乱糟糟的桌子塞进仓库。相反,你开始创建记忆的过程,这就像一个有组织的文件柜。你会审查桌上的材料,丢弃草稿和冗余笔记,只将最关键、定稿的文件归档到标记好的文件夹中。这确保了文件柜对于所有未来的项目来说都是一个干净、可靠且高效的事实来源,而不会被工作台的短暂混乱所干扰。这个类比直接反映了有效代理的运作方式:会话作为单个对话的临时工作台,而代理的记忆则是精心组织的文件柜,使其能够在未来的交互中回忆起关键信息。

基于这个上下文工程的高级概述,我们现在可以探索两个核心组件:会话和记忆,首先从会话开始。

会话 (Sessions)

上下文工程的一个基础元素是会话,它封装了单个连续对话的即时对话历史和工作记忆。每个会话都是一个独立的记录,绑定到特定用户。会话允许代理保持上下文,并在单个对话的范围内提供连贯的响应。一个用户可以有多个会话,但每个会话都作为一个特定交互的独特、断开连接的日志来运作。每个会话包含两个关键组件:按时间顺序排列的历史 (事件) 和 代理的工作记忆 (状态)

事件 (Events) 是对话的构建块。常见的事件类型包括:用户输入(来自用户的消息,如文本、音频、图像等)、代理响应(代理对用户的回复)、工具调用(代理使用外部工具或 API 的决定)或工具输出(从工具调用返回的数据,代理使用它来继续推理)。

除了聊天记录,会话通常还包括一个状态 (State)——一个结构化的“工作记忆”或草稿板。这保存了与当前对话相关的临时结构化数据,例如购物车里有什么物品。随着对话的进行,代理会向会话追加额外的事件。此外,它可能会根据代理中的逻辑改变状态。

事件的结构类似于传递给 Gemini API 的 Content 对象列表,其中每个具有角色 (role) 和部分 (parts) 的项目代表对话中的一轮——或一个事件。

contents = [
 {
   "role": "user",
   "parts": [ {"text": "What is the capital of France?"}]
 }, {
   "role": "model",
   "parts": [ {"text": "The capital of France is Paris."}]
 }
]

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=contents
)
代码片段 1: 调用 Gemini 的多轮对话示例

生产级代理的执行环境通常是无状态的,这意味着请求完成后它不保留任何信息。因此,其对话历史必须保存到持久存储中以维持连续的用户体验。虽然内存存储适合开发,但生产应用程序应利用健壮的数据库来可靠地存储和管理会话。例如,您可以将对话历史存储在像 Agent Engine Sessions3 这样的托管解决方案中。

框架和模型之间的差异

虽然核心思想相似,但不同的代理框架以不同的方式实现会话、事件和状态。代理框架负责维护 LLM 的对话历史和状态,使用此上下文构建 LLM 请求,并解析和存储 LLM 响应。

代理框架充当代码与 LLM 之间的通用翻译器。虽然您(开发者)使用框架的一致内部数据结构来处理每个对话轮次,但框架处理将这些结构转换为 LLM 所需的精确格式的关键任务。这种抽象非常强大,因为它将您的代理逻辑与您使用的特定 LLM 解耦,防止供应商锁定。

图 2: 代理的上下文管理流程

最终,目标是生成一个 LLM 能理解的“请求”。对于 Google 的 Gemini 模型,这是一个 `List[Content]`。每个 Content 对象是一个简单的类似字典的结构,包含两个键:`role` 定义谁在说话("user" 或 "model"),`parts` 定义消息的实际内容(文本、图像、工具调用等)。

框架会自动处理将数据从其内部对象(例如,ADK Event)映射到进行 API 调用前 Content 对象中相应的 role 和 parts。本质上,框架为开发者提供了一个稳定的内部 API,同时在幕后管理不同 LLM 复杂多变的外部 API。

  • ADK
     使用显式的 Session 对象,其中包含 Event 对象列表和单独的 State 对象。Session 就像一个文件柜,一个文件夹用于对话历史(事件),另一个用于工作记忆(状态)。
  • LangGraph
     没有正式的“会话”对象。相反,状态 (State) 就是会话。这个包罗万象的状态对象保存了对话历史(作为 Message 对象列表)和所有其他工作数据。与传统会话的仅追加日志不同,LangGraph 的状态是可变的。它可以被转换,像历史压缩这样的策略可以改变记录。这对管理长对话和 Token 限制很有用。

多智能体系统的会话

在多智能体系统中,多个代理协同工作。每个代理专注于一个较小的专门任务。为了使这些代理有效协作,它们必须共享信息。系统架构定义了它们用于共享信息的通信模式。这种架构的核心组件是系统如何处理会话历史——所有交互的持久日志。

图 3: 不同的多智能体架构模式30

在探索管理此历史记录的架构模式之前,至关重要的是将其与发送给 LLM 的上下文区分开来。将会话历史视为整个对话的永久、未删节的文字记录。另一方面,上下文是为单轮对话发送给 LLM 的精心制作的信息负载。代理可以通过仅从历史记录中选择相关的摘录,或添加特殊的格式(如引导性前言)来引导模型的响应来构建此上下文。本节重点介绍在代理之间传递什么信息,而不一定是发送给 LLM 的上下文。

代理框架使用两种主要方法处理多智能体系统的会话历史:共享统一历史 (Shared, Unified History),其中所有代理都为一个日志做贡献;或 独立个体历史 (Separate, Individual Histories),其中每个代理维护自己的视角。这两种模式的选择取决于任务的性质和代理之间期望的协作风格。

对于共享统一历史模型,系统中的所有代理都从同一个单一对话历史中读取并写入所有事件。每个代理的消息、工具调用和观察结果都按时间顺序追加到一个中央日志中。这种方法最适合需要单一事实来源的紧密耦合协作任务,例如多步骤问题解决过程,其中一个代理的输出是下一个代理的直接输入。即使有共享历史,子代理也可能在将日志传递给 LLM 之前对其进行处理。例如,它可以筛选相关的事件子集,或添加标签以标识哪个代理生成了每个事件。

如果您使用 ADK 的 LLM 驱动委托来移交给子代理,子代理的所有中间事件都将写入与根代理相同的会话:

from google.adk.agents import LlmAgent

# 子代理可以访问 Session 并向其写入事件。
sub_agent_1 = LlmAgent(...)

# 可选地,子代理可以将最终响应文本(或结构化输出)保存到指定的状态键。
sub_agent_2 = LlmAgent(
    output_key="..."
)

# 父代理
root_agent = LlmAgent(
    sub_agents=[sub_agent_1, sub_agent_2]
)
代码片段 2: 跨多个代理框架的 A2A 通信

独立个体历史模型中,每个代理维护自己的私有对话历史,对其他代理就像黑盒一样。所有内部过程——如中间想法、工具使用和推理步骤——都保存在代理的私有日志中,对其他人不可见。通信仅通过显式消息发生,代理共享其最终输出,而不是其过程。

这种交互通常通过实现 Agent-as-a-tool(代理即工具) 或使用 Agent-to-Agent (A2A) 协议来实现。使用 Agent-as-a-Tool,一个代理像调用标准工具一样调用另一个代理,传递输入并接收最终的、自包含的输出。使用 Agent-to-Agent (A2A) 协议,代理使用结构化协议进行直接消息传递。

跨多个智能体框架的互操作性

图 4: 使用不同框架的多个代理之间的 A2A 通信

框架使用内部数据表示为多智能体系统引入了一个关键的架构权衡:将代理与 LLM 解耦的抽象,同时也将其与使用其他代理框架的代理隔离了。这种隔离在持久层被固化。会话的存储模型通常将数据库模式直接耦合到框架的内部对象,创建了一个刚性的、相对不可移植的对话记录。因此,使用 LangGraph 构建的代理无法原生解释由基于 ADK 的代理持久化的不同 Session 和 Event 对象,使得无缝的任务移交变得不可能。

协调这些隔离代理之间协作的一种新兴架构模式是 Agent-to-Agent (A2A) 通信。虽然这种模式允许代理交换消息,但它未能解决共享丰富上下文状态的核心问题。每个代理的对话历史都编码在其框架的内部模式中。因此,任何包含会话事件的 A2A 消息都需要翻译层才有用。

一个更健壮的互操作性架构模式涉及将共享知识抽象为一个与框架无关的数据层,例如记忆 (Memory)。与保存原始的、特定于框架的对象(如 Events 和 Messages)的会话存储不同,记忆层旨在保存经过处理的、规范的信息。关键信息——如摘要、提取的实体和事实——从对话中提取出来,通常存储为字符串或字典。记忆层的数据结构不耦合到任何单一框架的内部数据表示,这使其能够充当通用的公共数据层。这种模式允许异构代理通过共享公共认知资源来实现真正的协作智能,而无需自定义翻译器。

会话的生产环境考量

当将代理迁移到生产环境时,其会话管理系统必须从简单的日志演变为健壮的企业级服务。关键考量因素分为三个关键领域:安全与隐私、数据完整性和性能。像 Agent Engine Sessions 这样的托管会话存储专门设计用于解决这些生产需求。

安全与隐私

保护会话中包含的敏感信息是一项不可协商的要求。严格隔离是最关键的安全原则。会话由单个用户拥有,系统必须强制执行严格隔离,以确保一个用户永远无法访问另一个用户的会话数据(即通过 ACL)。对会话存储的每个请求都必须针对会话所有者进行身份验证和授权。

处理个人身份信息 (PII) 的最佳实践是在将会话数据写入存储之前对其进行编校 (Redact)。这是一项基本的安全措施,可以大幅降低潜在数据泄露的风险和“爆炸半径”。通过使用 Model Armor 等工具确保敏感数据永远不会被持久化,您可以简化对 GDPR 和 CCPA 等隐私法规的遵守,并建立用户信任。

数据完整性与生命周期管理

生产系统需要明确的规则来规定会话数据如何随时间存储和维护。会话不应永远存在。您可以实施生存时间 (TTL) 策略来自动删除不活跃的会话,以管理存储成本并减少数据管理开销。这需要明确的数据保留策略,定义会话在归档或永久删除之前应保留多长时间。

此外,系统必须保证操作按确定性顺序追加到会话历史中。维持正确的事件时间顺序对于对话日志的完整性至关重要。

性能与可扩展性

会话数据处于每个用户交互的“热路径”上,使其性能成为首要关注点。读取和写入会话历史必须极快,以确保响应迅速的用户体验。代理运行时通常是无状态的,因此在每一轮开始时都会从中央数据库检索整个会话历史,从而产生网络传输延迟。

为了减轻延迟,减少传输的数据大小至关重要。一个关键的优化是在将会话历史发送给代理之前对其进行过滤或压缩。例如,您可以删除当前对话状态不再需要的旧的、不相关的函数调用输出。下一节将详细介绍几种压缩历史记录的策略,以有效管理长上下文对话。

管理长上下文对话:权衡与优化

在简单的架构中,会话是用户与代理之间对话的不可变日志。然而,随着对话规模的扩大,对话的 Token 使用量也会增加。现代 LLM 可以处理长上下文,但存在局限性,特别是对于对延迟敏感的应用程序10

  1. 上下文窗口限制
    每个 LLM 都有它可以一次处理的最大文本量(上下文窗口)。如果对话历史超过此限制,API 调用将失败。
  2. API 成本 ($)
    大多数 LLM 提供商根据您发送和接收的 Token 数量收费。较短的历史记录意味着每轮的 Token 更少,成本更低。
  3. 延迟 (速度)
    向模型发送更多文本需要更长的处理时间,导致用户响应时间变慢。压缩使代理感觉快速且反应灵敏。
  4. 质量
    随着 Token 数量的增加,由于上下文中的额外噪音和自回归错误,性能可能会变差。

管理与代理的长对话可以比作一个精明的旅行者为长途旅行打包行李。行李箱代表代理有限的上下文窗口,衣服和物品是对话中的信息片段。如果你只是试图把所有东西都塞进去,行李箱会变得太重且杂乱无章,很难快速找到你需要的东西——就像过载的上下文窗口会增加处理成本并减慢响应时间一样。另一方面,如果你打包得太少,你就有可能落下护照或大衣等必需品,危及整个行程——就像代理可能会丢失关键上下文,导致不相关或错误的答案。旅行者和代理都在类似的限制下运作:成功不取决于你能携带多少,而取决于只携带你需要的东西。

压缩策略缩减长对话历史,浓缩对话以适应模型的上下文窗口,降低 API 成本和延迟。随着对话变长,每一轮发送给模型的历史记录可能会变得太大。压缩策略通过智能地修剪历史记录,同时尝试保留最重要的上下文来解决这个问题。

那么,你如何知道要在不丢失有价值信息的情况下从会话中扔掉什么内容呢?策略范围从简单的截断到复杂的压缩:

  • 保留最后 N 轮 (Keep the last N turns)
    这是最简单的策略。代理只保留最近的 N 轮对话(“滑动窗口”),并丢弃所有更旧的内容。
  • 基于 Token 的截断 (Token-Based Truncation)
    在将历史记录发送给模型之前,代理计算消息中的 Token,从最近的开始向后计算。它包括尽可能多的消息,而不超过预定义的 Token 限制(例如 4000 个 Token)。所有更旧的内容都被简单地切断。
  • 递归摘要 (Recursive Summarization)
    对话的旧部分被 AI 生成的摘要所取代。随着对话的增长,代理定期使用另一个 LLM 调用来总结最旧的消息。此摘要随后用作历史记录的浓缩形式,通常作为前缀添加到最近的逐字消息之前。

例如,您可以使用 ADK 的内置插件通过保留最后 N 轮来限制发送给模型的上下文。这不会修改存储在会话存储中的历史事件:

from google.adk.apps import App
from google.adk.plugins.context_filter_plugin import ContextFilterPlugin

app = App(
    name='hello_world_app',
    root_agent=agent,
    plugins=[
        # 保留最后 10 轮和最近的用户查询。
        ContextFilterPlugin(num_invocations_to_keep=10),
    ],
)
代码片段 3: 使用 ADK 进行会话截断,仅使用最后 N 轮

鉴于复杂的压缩策略旨在降低成本和延迟,至关重要的是在后台异步执行昂贵的操作(如递归摘要)并持久化结果。“在后台”确保客户端无需等待,“持久化”确保昂贵的计算不会过度重复。通常,代理的记忆管理器负责生成和持久化这些递归摘要。代理还必须记录哪些事件包含在压缩摘要中;这可以防止原始的、更冗长的事件被不必要地发送给 LLM。

此外,代理必须决定何时需要压缩。触发机制通常分为几类:

  • 基于计数的触发器
    (即 Token 大小或轮次阈值):一旦对话超过某个预定义阈值,就会对对话进行压缩。这种方法对于管理上下文长度通常“足够好”。
  • 基于时间的触发器
    压缩不是由对话的大小触发,而是由缺乏活动触发。如果用户在一段时间内(例如 15 或 30 分钟)停止交互,系统可以在后台运行压缩作业。
  • 基于事件的触发器
    (即语义/任务完成):当代理检测到特定任务、子目标或对话主题已结束时,决定触发压缩。

例如,您可以使用 ADK 的 EventsCompactionConfig 在配置的轮数后触发基于 LLM 的摘要:

from google.adk.apps import App
from google.adk.apps.app import EventsCompactionConfig

app = App(
    name='hello_world_app',
    root_agent=agent,
    events_compaction_config=EventsCompactionConfig(
        compaction_interval=5,
        overlap_size=1,
    ),
)
代码片段 4: 使用 ADK 的摘要进行会话压缩

记忆生成是从冗长且嘈杂的数据源中提取持久知识的广泛能力。在本节中,我们介绍了从对话历史中提取信息的一个主要示例:会话压缩。压缩提炼了整个对话的逐字记录,提取关键事实和摘要,同时丢弃对话填充词。

在压缩的基础上,下一节将更广泛地探讨记忆的生成和管理。我们将讨论创建、存储和检索记忆以构建代理长期知识的各种方式。

记忆 (Memory)

记忆和会话有着深刻的共生关系:会话是生成记忆的主要数据源,而记忆是管理会话大小的关键策略。记忆是从对话或数据源中提取的有意义信息的快照。它是一种浓缩的表示,保留了重要的上下文,使其对未来的交互有用。通常,记忆跨会话持久化,以提供连续和个性化的体验。

作为一个专门的、解耦的服务,“记忆管理器”为多智能体互操作性提供了基础。记忆管理器经常使用与框架无关的数据结构,如简单的字符串和字典。这允许建立在不同框架上的代理连接到单个记忆存储,从而能够创建任何连接的代理都可以利用的共享知识库。

注意:某些框架也可能将会话或逐字对话称为“短期记忆”。在本白皮书中,记忆被定义为提取的信息,而不是逐轮对话的原始对话。

存储和检索记忆对于构建复杂且智能的代理至关重要。健壮的记忆系统通过解锁几个关键能力,将基本的聊天机器人转变为真正的智能代理:

  • 个性化
    最常见的用例是记住用户偏好、事实和过去的互动,以定制未来的响应。例如,记住用户最喜欢的运动队或他们首选的飞机座位,可以创造更贴心和个性化的体验。
  • 上下文窗口管理
    随着对话变长,完整的历史记录可能会超过 LLM 的上下文窗口。记忆系统可以通过创建摘要或提取关键事实来压缩此历史记录,保留上下文而无需在每一轮中发送数千个 Token。这降低了成本和延迟。
  • 数据挖掘和洞察
    通过分析许多用户的存储记忆(以聚合的、保护隐私的方式),您可以从噪音中提取洞察。例如,零售聊天机器人可能会发现许多用户都在询问特定产品的退货政策,从而标记潜在问题。
  • 代理自我改进和适应
    代理通过创建关于自身表现的程序性记忆——记录哪些策略、工具或推理路径导致了成功的结果——来从以前的运行中学习。这使代理能够构建有效解决方案的剧本,使其能够随着时间的推移适应和改进其问题解决能力。

在 AI 系统中创建、存储和利用记忆是一个协作过程。栈中的每个组件——从最终用户到开发者的代码——都有独特的作用。

  1. 用户
    提供记忆的原始源数据。在某些系统中,用户可以直接提供记忆(即通过表单)。
  2. 代理(开发者逻辑)
    配置如何决定记住什么和何时记住,编排对记忆管理器的调用。在简单的架构中,开发者可以实现逻辑,使得记忆*总是*被检索并且*总是*被触发生成。在更高级的架构中,开发者可以实现“记忆即工具”,其中代理(通过 LLM)决定何时应检索或生成记忆。
  3. 代理框架(例如 ADK, LangGraph)
    提供记忆交互的结构和工具。框架充当管道。它定义了开发者的逻辑如何访问对话历史并与记忆管理器交互,但它本身不管理长期存储。它还定义了如何将检索到的记忆填充到上下文窗口中。
  4. 会话存储(即 Agent Engine Sessions, Spanner, Redis)
    存储会话的逐轮对话。原始对话将被摄入记忆管理器以生成记忆。
  5. 记忆管理器(例如 Agent Engine Memory Bank, MemO, Zep)
    处理记忆的存储、检索和压缩。存储和检索记忆的机制取决于使用的提供商。这是专门的服务或组件,它获取代理识别的潜在记忆并处理其整个生命周期。
    • 提取
      从源数据中提炼关键信息。
    • 整合
      整理记忆以合并重复的实体。
    • 存储
      将记忆持久化到持久数据库。
    • 检索
      获取相关记忆以为新交互提供上下文。
图 5: 会话、记忆和外部知识之间的信息流

职责的划分确保开发者可以专注于代理的独特逻辑,而无需构建用于记忆持久化和管理的复杂底层基础设施。重要的是要认识到,记忆管理器是一个活跃的系统,而不仅仅是一个被动的向量数据库。虽然它使用相似性搜索进行检索,但其核心价值在于能够随着时间的推移智能地提取、整合和整理记忆。像 Agent Engine Memory Bank 这样的托管记忆服务处理记忆生成和存储的整个生命周期,让您可以专注于代理的核心逻辑。

这种检索能力也是为什么记忆经常被与另一个关键架构模式进行比较:检索增强生成 (RAG)。然而,它们建立在不同的架构原则之上,因为 RAG 处理静态的外部数据,而记忆整理动态的、用户特定的上下文。它们履行两个独特且互补的角色:RAG 使代理成为事实专家,而记忆使其成为用户专家。下表细分了它们的高级差异:

特性
RAG 引擎
记忆管理器
主要目标
将外部事实知识注入上下文。
创建个性化和有状态的体验。代理记住事实,随时间适应用户,并维持长期运行的上下文。
数据源
静态的、预索引的外部知识库(例如 PDF、Wiki、文档、API)。
用户与代理之间的对话。
隔离级别
通常共享。知识库通常是所有用户可访问的全局只读资源,以确保一致的事实答案。
高度隔离。记忆几乎总是按用户划分范围,以防止数据泄露。
信息类型
静态、事实性和权威性。通常包含特定领域的数据、产品详情或技术文档。
动态且(通常)特定于用户。记忆源自对话,因此存在固有的不确定性水平。
写入模式
批量处理。通过离线管理操作触发。
基于事件的处理。以某种节奏触发(即每轮或会话结束时)或记忆即工具(代理决定生成记忆)。
读取模式
RAG 数据几乎总是“作为工具”检索。当代理决定用户查询需要外部信息时检索。
两种常见模式:
1. 记忆即工具:当用户查询需要关于用户(或其他身份)的额外信息时检索。
2. 静态检索:在每轮开始时始终检索记忆。
表 1: RAG 引擎和记忆管理器的比较

理解这种差异的一个有用的方法是将 RAG 视为代理的研究图书管理员,将记忆管理器视为其私人助理

研究图书管理员 (RAG) 在一个巨大的公共图书馆工作,里面装满了百科全书、教科书和官方文件。当代理需要一个既定的事实——如产品的技术规格或历史日期——它会咨询图书管理员。图书管理员从这个静态、共享和权威的知识库中检索信息,以提供一致的、事实性的答案。图书管理员是世界事实的专家,但他们不知道关于提问用户的任何个人信息。

相比之下,私人助理 (Memory) 跟随代理并携带一本私人笔记本,记录与特定用户每次互动的细节。这本笔记本是动态且高度隔离的,包含个人偏好、过去的对话和不断变化的目标。当代理需要回忆用户最喜欢的运动队或上周项目讨论的背景时,它会求助于助理。助理的专长不在于全球事实,而在于它所服务的用户本身。

最终,一个真正智能的代理两者都需要。RAG 为其提供世界的专家知识,而记忆为其提供对用户的专家理解。

下一节通过检查记忆的核心组件来解构记忆的概念:它存储的信息类型、其组织模式、其存储和创建机制、其范围的战略定义,以及它对多模态与文本数据的处理。

记忆的类型

代理的记忆可以根据信息的存储方式和捕获方式进行分类。这些不同类型的记忆协同工作,以创建对用户及其需求的丰富、上下文理解。在所有类型的记忆中,规则都是:记忆是描述性的,而不是预测性的。

“记忆”是由记忆管理器返回并由代理用作上下文的原子信息片段。虽然确切的模式可能有所不同,但单个记忆通常由两个主要部分组成:内容和元数据。

  • 内容
    从源数据(即会话的原始对话)中提取的记忆实质。至关重要的是,内容设计为与框架无关,使用任何代理都可以轻松摄取的简单数据结构。内容可以是结构化或非结构化数据。
    • 结构化记忆
      包括通常存储在通用格式(如字典或 JSON)中的信息。其模式通常由开发者定义,而不是由特定框架定义。例如,`{"seat_preference": "Window"}`。
    • 非结构化记忆
      是捕捉较长交互、事件或主题本质的自然语言描述。例如,“用户偏好靠窗座位”。
  • 元数据
    提供有关记忆的上下文,通常存储为简单的字符串。这可以包括记忆的唯一标识符、记忆“所有者”的标识符以及描述记忆内容或数据源的标签。

信息类型

除了基本结构外,记忆还可以根据它们所代表的知识的基本类型进行分类。这种区分对于理解代理如何使用记忆至关重要,它将记忆分为源自认知科学11的两个主要功能类别:陈述性记忆 ("知道什么") 和 程序性记忆 ("知道如何")

  • 陈述性记忆 (Declarative memory)
    代理关于事实、数字和事件的知识。它是代理可以明确陈述或“宣告”的所有信息。如果记忆是对“什么”问题的回答,它就是陈述性的。这一类包括一般世界知识(语义)和特定用户事实(实体/情景)。
  • 程序性记忆 (Procedural memory)
    代理关于技能和工作流程的知识。它通过隐含地演示如何正确执行任务来指导代理的行动。如果记忆有助于回答“如何”问题——例如预订旅行的正确工具调用顺序——它就是程序性的。

组织模式

一旦创建了记忆,下一个问题是如何组织它。记忆管理器通常采用以下模式之一或多种来组织记忆:集合 (Collections)12、结构化用户档案 (Structured User Profile) 或“滚动摘要” (Rolling Summary)。这些模式定义了单个记忆如何相互关联以及与用户的关系。

  • 集合模式13
     将内容组织成单个用户的多个独立的自然语言记忆。每个记忆都是一个独特的事件、摘要或观察,尽管对于单个高级主题,集合中可能有多个记忆。集合允许存储和搜索与特定目标或主题相关的更大、更少结构化的信息池。
  • 结构化用户档案模式
    将记忆组织为关于用户的一组核心事实,就像一张不断更新新的、稳定信息的联系人卡片。它专为快速查找基本事实信息(如姓名、偏好和账户详细信息)而设计。
  • 与结构化用户档案不同,“滚动”摘要模式将所有信息整合到一个单一的、不断发展的记忆中,该记忆代表整个用户-代理关系的自然语言摘要。管理器不是创建新的单独记忆,而是不断更新这一个主文档。此模式经常用于压缩长会话,在管理总 Token 数的同时保留重要信息。

存储架构

此外,存储架构是一个关键决策,决定了代理检索记忆的速度和智能程度。架构的选择定义了代理是否擅长查找概念上相似的想法、理解结构关系,或者两者兼而有之。

记忆通常存储在向量数据库和/或知识图谱中。向量数据库有助于查找与查询概念上相似的记忆。知识图谱将记忆存储为实体及其关系的网络。

  • 向量数据库
    是最常见的方法,支持基于语义相似性而不是精确关键字的检索。记忆被转换为嵌入向量,数据库找到与用户查询最接近的概念匹配。这擅长检索上下文和含义是关键的非结构化自然语言记忆(即“原子事实”14)。
  • 知识图谱
    用于将记忆存储为实体(节点)及其关系(边)的网络。检索涉及遍历此图以查找直接和间接连接,允许代理推理不同事实是如何链接的。它是结构化、关系查询和理解数据中复杂连接(即“知识三元组”15)的理想选择。

您还可以通过使用向量嵌入丰富知识图谱的结构化实体,将两种方法结合成混合方法。这使系统能够同时执行关系和语义搜索。这提供了图的结构化推理和向量数据库的细微概念搜索,提供了两全其美的方案。

创建机制

我们还可以根据记忆的创建方式(包括信息的派生方式)对记忆进行分类。显式记忆是在用户直接命令代理记住某事时创建的(例如,“记住我的周年纪念日是 10 月 26 日”)。另一方面,隐式记忆是当代理在没有直接命令的情况下从对话中推断和提取信息时创建的(例如,“我的周年纪念日是下周。你能帮我为我的伴侣找一份礼物吗?”)。

记忆还可以根据记忆提取逻辑是位于代理框架内部还是外部来区分。内部记忆是指直接内置于代理框架中的记忆管理。它方便入门,但通常缺乏高级功能。内部记忆可以使用外部存储,但生成记忆的机制在代理内部。

外部记忆涉及使用专门致力于记忆管理的独立服务(例如,Agent Engine Memory Bank, MemO, Zep)。代理框架调用此外部服务的 API 来存储、检索和处理记忆。这种方法提供了更复杂的功能,如语义搜索、实体提取和自动摘要,将记忆管理的复杂任务卸载到专门构建的工具上。

记忆范围

您还需要考虑记忆描述的是谁或什么。这对您使用什么实体(即用户、会话或应用程序)来聚合和检索记忆有影响。

  • 用户级范围 (User-Level scope)
     是最常见的实现,旨在为每个人创造连续、个性化的体验;例如,“用户偏好中间座位”。记忆绑定到特定用户 ID,并在其所有会话中持久存在,允许代理建立对其偏好和历史的长期理解。
  • 会话级范围 (Session-Level scope)
     专为长对话的压缩而设计;例如,“用户正在购买 2025 年 11 月 7 日至 2025 年 11 月 14 日之间往返纽约和巴黎的机票。他们偏好直飞和中间座位”。它创建了从单个会话中提取的见解的持久记录,允许代理用一组简明的关键事实替换冗长、占用大量 Token 的文字记录。至关重要的是,此记忆与原始会话日志不同;它只包含从对话中处理过的见解,而不是对话本身,且其上下文被隔离到该特定会话。
  • 应用程序级范围 (Application-level scope)
    (或全局上下文)是应用程序的所有用户都可访问的记忆;例如,“代号 XYZ 指的是项目……”。此范围用于提供共享上下文、广播系统范围的信息或建立常识基线。应用程序级记忆的一个常见用例是程序性记忆,它为代理提供“操作指南”说明;这些记忆通常旨在帮助所有用户的代理解理。至关重要的是,必须清除这些记忆中的所有敏感内容,以防止用户之间的数据泄露。

多模态记忆

“多模态记忆”是一个关键概念,描述了代理如何处理非文本信息,如图像、视频和音频。关键在于区分记忆所源自的数据(其来源)和记忆所存储的数据(其内容)。

  • 源自多模态源的记忆
    是最常见的实现。代理可以处理各种数据类型——文本、图像、音频——但它创建的记忆是源自该来源的文本见解。例如,代理可以处理用户的语音备忘录以创建记忆。它不存储音频文件本身;相反,它转录音频并创建文本记忆,如“用户对最近的运输延误表示沮丧”。
  • 具有多模态内容的记忆
    是一种更高级的方法,其中记忆本身包含非文本媒体。代理不仅描述内容;它直接存储内容。例如,用户可以上传一张图片并说“记住我们标志的这个设计”。代理创建一个直接包含图像文件的记忆,链接到用户的请求。

大多数当代记忆管理器专注于处理多模态源,同时生成文本内容。这是因为为特定记忆生成和检索非结构化二进制数据(如图像或音频)需要专门的模型、算法和基础设施。将所有输入转换为一种通用的、可搜索的格式:文本,要简单得多。

例如,您可以使用 Agent Engine Memory Bank 从多模态输入生成记忆。输出记忆将是从内容中提取的文本见解:

from google.genai import types

client = vertexai.Client(project=..., location=...)
response = client.agent_engines.memories.generate(
    name=agent_engine_name,
    direct_contents_source={
        "events": [
            {
                "content": types.Content(
                    role="user",
                    parts=[
                        types.Part.from_text(
                             "This is context about the multimodal input."
                        ),
                        types.Part.from_bytes(
                            data=CONTENT_AS_BYTES,
                            mime_type=MIME_TYPE
                        ),
                        types.Part.from_uri(
                            file_uri="file/path/to/content",
                            mime_type=MIME_TYPE
                        )
                    ]
                )
            }
        ]
    },
    scope={"user_id": user_id}
)
代码片段 5: Agent Engine Memory Bank 的多模态输入记忆生成 API 调用示例

下一节将检查记忆生成的机制,详述两个核心阶段:从源数据中提取新信息,以及随后将该信息与现有记忆库进行整合。

记忆生成:提取与整合

记忆生成自主地将原始对话数据转换为结构化的、有意义的见解。可以将其视为旨在提取和浓缩记忆的 LLM 驱动的 ETL(提取、转换、加载)管道。记忆生成的 ETL 管道将记忆管理器与 RAG 引擎和传统数据库区分开来。

记忆管理器不需要开发者手动指定数据库操作,而是使用 LLM 智能地决定何时添加、更新或合并记忆。这种自动化是记忆管理器的核心优势;它抽象了管理数据库内容、链接 LLM 调用和部署后台服务进行数据处理的复杂性。

图 6: 记忆生成的高级算法,从新数据源提取记忆并将其与现有记忆整合

虽然具体算法因平台而异(例如 Agent Engine Memory Bank, MemO, Zep),但记忆生成的高级过程通常遵循以下四个阶段:

  1. 摄入 (Ingestion)
    过程始于客户端向记忆管理器提供原始数据源,通常是对话历史。
  2. 提取与过滤 (Extraction & Filtering)
    记忆管理器使用 LLM 从源数据中提取有意义的内容。关键在于此 LLM 不会提取所有内容;它只捕获符合预定义主题定义的信息。如果摄入的数据不包含与这些主题匹配的信息,则不会创建记忆。
  3. 整合 (Consolidation)
    这是最复杂的阶段,记忆管理器处理冲突解决和去重。它执行“自我编辑”过程,使用 LLM 将新提取的信息与现有记忆进行比较。为了确保用户的知识库保持连贯、准确并根据新信息随时间演变,管理器可以决定:
    • 将新见解合并到现有记忆中。
    • 如果现有记忆现已无效,则将其删除。
    • 如果主题是全新的,则创建一个全新的记忆。
  4. 存储 (Storage)
    最后,新的或更新的记忆被持久化到持久存储层(如向量数据库或知识图谱),以便在未来的交互中检索。

像 Agent Engine Memory Bank 这样的托管记忆管理器完全自动化了此管道。它们提供了一个单一、连贯的系统,用于将对话噪音转化为结构化知识,允许开发者专注于代理逻辑,而不是自己构建和维护底层数据基础设施。例如,使用 Memory Bank 触发记忆生成只需要一个简单的 API 调用17

from google.cloud import vertexai

client = vertexai.Client(project=..., location=...)

client.agent_engines.memories.generate(
    name="projects/.../locations/...reasoningEngines/...",
    scope={"user_id": "123"},
    direct_contents_source={
        "events": [...]
    },
    config={
        # 在后台运行记忆生成。
        "wait_for_completion": False
    }
)
代码片段 6: 使用 Agent Engine Memory Bank 生成记忆

记忆生成的过程可以比作勤奋的园丁照料花园。提取就像接收新的种子和树苗(来自对话的新信息)。园丁不会把它们随便扔到地里。相反,他们通过拔除杂草(删除冗余或冲突的数据)、修剪过度生长的枝条以改善现有植物的健康(提炼和总结现有记忆),然后小心地将新树苗种植在最佳位置来执行整合。这种持续、深思熟虑的整理确保花园保持健康、有条理,并随着时间的推移继续繁荣,而不是变成杂草丛生、无法使用的混乱。这个异步过程在后台进行,确保花园随时准备好迎接下一次访问。

现在,让我们深入探讨记忆生成的两个关键步骤:提取和整合。

深度剖析:记忆提取

记忆提取的目标是回答一个基本问题:“这次对话中的哪些信息足够有意义,可以成为记忆?” 这不是简单的摘要;这是一个有针对性的、智能的过滤过程,旨在将信号(重要事实、偏好、目标)与噪音(寒暄、填充文本)分离。

“有意义”不是一个普遍的概念;它完全由代理的目的和用例定义。客户支持代理需要记住的内容(例如订单号、技术问题)与个人健康教练需要记住的内容(例如长期目标、情绪状态)根本不同。因此,自定义保留什么信息是创建真正有效代理的关键。

记忆管理器的 LLM 通过遵循一组精心构建的程序化护栏和指令来决定提取什么,这些指令通常嵌入在复杂的系统提示中。此提示通过向 LLM 提供一组主题定义来定义“有意义”的含义。使用模式和基于模板的提取,LLM 被赋予预定义的 JSON 模式或使用 LLM 功能(如结构化输出18)的模板;LLM 被指示使用对话中的相应信息构建 JSON。或者,使用自然语言主题定义,LLM 由主题的简单自然语言描述指导。

使用少样本提示 (few-shot prompting),通过示例“向” LLM 展示要提取什么信息。提示包括几个输入文本示例和应提取的理想、高保真记忆。LLM 从示例中学习所需的提取模式,使其对于难以用模式或简单定义描述的自定义或细微主题非常有效。

大多数记忆管理器开箱即用,通过查找常见主题,如用户偏好、关键事实或目标。许多平台还允许开发者定义自己的自定义主题,根据其特定领域定制提取过程。例如,您可以通过提供自己的主题定义和少样本示例来自定义 Agent Engine Memory Bank 认为有意义并持久化的信息19

from google.genai.types import Content, Part

memory_bank_config = {
    "customization_configs": [{
        "memory_topics": [
            { "managed_memory_topic": {"managed_topic_enum": "USER_PERSONAL_INFO" }},
            {
                "custom_memory_topic": {
                    "label": "business_feedback",
                    "description": """关于咖啡店体验的具体用户反馈。这包括对饮料、食物、糕点、氛围、员工友好度、服务速度、清洁度的意见,以及任何改进建议。"""
                }
            }
        ],
        "generate_memories_examples": {
            "conversationSource": {
                "events": [
                    {
                        "content": Content(
                            role="model",
                            parts=[Part(text="欢迎回到 The Daily Grind!我们很想听听您对这次光临的反馈。")])
                    },{
                        "content": Content(
                            role="user",
                            parts=[Part(text= "嘿。今天的滴滤咖啡有点温,这让人很扫兴。还有,音乐太大声了,我几乎听不见朋友说话。")])
                    }
                ]
            },
            "generatedMemories": [
                {"fact": "用户报告滴滤咖啡是温的。"},
                {"fact": "用户觉得店里的音乐太大声了。"}
            ]
        }
    }]
}
代码片段 7: 自定义 Agent Engine Memory Bank 认为有意义并持久化的信息

虽然记忆提取本身不是“摘要”,但算法可能会结合摘要来提炼信息。为了提高效率,许多记忆管理器将对话的滚动摘要直接纳入记忆提取提示中20。这个浓缩的历史记录提供了从最近的互动中提取关键信息所需的必要上下文。它消除了在每一轮中重复处理完整、冗长对话以保持上下文的需要。

一旦从数据源中提取了信息,就必须通过整合更新现有的记忆库以反映新信息。

深度剖析:记忆整合

从冗长的对话中提取记忆后,整合应将新信息集成到一个连贯、准确且不断发展的知识库中。这可以说是记忆生命周期中最复杂的阶段,将简单的两件事实集合转变为对用户的精心策划的理解。没有整合,代理的记忆很快就会变成一个嘈杂、矛盾且不可靠的日志,记录着曾经说过的每一条信息。这种“自我策展”通常由 LLM 管理,是使记忆管理器超越简单数据库的关键。

整合解决了源自对话数据的基本问题,包括:

  • 信息重复
    用户可能会在不同的对话中以多种方式提及相同的事实(例如,“我需要去纽约的航班”和后来的“我计划去纽约旅行”)。简单的提取过程会创建两个冗余的记忆。
  • 冲突信息
    用户的状态随时间变化。没有整合,代理的记忆将包含矛盾的事实。
  • 信息演变
    一个简单的事实可以变得更加细微。关于“用户对市场营销感兴趣”的初始记忆可能会演变为“用户正在领导一个专注于 Q4 客户获取的市场营销项目”。
  • 记忆相关性衰减
    并非所有记忆都永远有用。代理必须进行遗忘——主动修剪旧的、陈旧的或低置信度的记忆,以保持知识库的相关性和效率。遗忘可以通过指示 LLM 在整合期间服从更新的信息或通过生存时间 (TTL) 自动删除来发生。

整合过程是一个 LLM 驱动的工作流,它将新提取的见解与用户的现有记忆进行比较。首先,工作流尝试检索与新提取的记忆相似的现有记忆。这些现有记忆是整合的候选者。如果现有记忆被新信息反驳,它可能会被删除。如果它被增强,它可能会被更新。

其次,向 LLM 展示现有记忆和新信息。其核心任务是将它们放在一起分析,并确定应执行什么操作。主要操作包括:

  • UPDATE (更新)
    用新信息或更正后的信息修改现有记忆。
  • CREATE (创建)
    如果新见解完全是新颖的且与现有记忆无关,则创建一个新的。
  • DELETE / INVALIDATE (删除/无效)
    如果新信息使旧记忆完全不相关或不正确,则删除或使其无效。

最后,记忆管理器将 LLM 的决定转换为更新记忆存储的事务。

记忆溯源 (Memory Provenance)

机器学习的经典公理“垃圾进,垃圾出”对 LLM 来说更为关键,因为结果往往是“垃圾进,自信的垃圾出”。为了使代理做出可靠的决策并使记忆管理器有效地整合记忆,它们必须能够批判性地评估其自身记忆的质量。这种可信度直接源自记忆的溯源 (Provenance)——对其起源和历史的详细记录。

图 7: 数据源和记忆之间的信息流。单个记忆可以源自多个数据源,单个数据源可能促成多个记忆。

记忆整合的过程——将来自多个来源的信息合并成单一的、不断发展的记忆——产生了跟踪其血统 (lineage) 的需求。如上图所示,单个记忆可能是多个数据源的混合,而单个源可能被分割成多个记忆。

为了评估可信度,代理必须跟踪每个来源的关键细节,例如其起源(来源类型)和年龄(“新鲜度”)。这些细节至关重要,原因有二:它们决定了每个来源在记忆整合期间的权重,并告知代理在推理期间应在多大程度上依赖该记忆。

来源类型是确定信任的最重要因素之一。数据源主要分为三类:

  • 引导数据 (Bootstrapped Data)
    从内部系统(如 CRM)预加载的信息。这种高信任度数据可用于初始化用户的记忆以解决冷启动问题,即向代理从未互动过的用户提供个性化体验的挑战。
  • 用户输入
    这包括明确提供的数据(例如,通过表单,这是高信任度的)或从对话中隐式提取的信息(通常不太可信)。
  • 工具输出
    从外部工具调用返回的数据。通常不鼓励从工具输出生成记忆,因为这些记忆往往是脆弱和陈旧的,使这种来源类型更适合短期缓存。

在记忆管理期间考虑记忆血统

这种动态、多源的记忆方法在管理记忆时带来了两个主要的操作挑战:冲突解决和删除派生数据。

记忆整合不可避免地会导致冲突,即一个数据源与另一个数据源冲突。记忆的溯源允许记忆管理器为其信息源建立信任层级。当来自不同来源的记忆相互矛盾时,代理必须在冲突解决策略中使用此层级。常见策略包括优先考虑最受信任的来源、支持最近的信息,或在多个数据点中寻找确证。

管理记忆时的另一个挑战发生在删除记忆时。一个记忆可以源自多个数据源。当用户撤销对一个数据源的访问权限时,源自该源的数据也应被删除。删除该源“接触”过的每一个记忆可能过于激进。一种更精确但计算成本更高的方法是仅使用剩余的有效源从头开始重新生成受影响的记忆。

除了静态的溯源细节外,对记忆的信心必须演变。信心通过确证增加,例如当多个受信任的来源提供一致的信息时。然而,高效的记忆系统还必须通过记忆修剪 (memory pruning) 来主动整理其现有知识——这是一个识别并“遗忘”不再有用的记忆的过程。这种修剪可以由几个因素触发:

  • 基于时间的衰减
    记忆的重要性会随时间降低。两年前关于一次会议的记忆可能不如上周的记忆相关。
  • 低置信度
    从弱推断创建且从未被其他来源确证的记忆可能会被修剪。
  • 不相关
    随着代理获得对用户更复杂的理解,它可能会确定一些旧的、琐碎的记忆不再与用户的当前目标相关。

通过结合反应性整合管道和主动修剪,记忆管理器确保代理的知识库不仅仅是一个不断增长的记录,而是一个经过策划、准确且相关的对用户的理解。

在推理期间考虑记忆血统

除了在整理语料库内容时考虑记忆的血统外,记忆的可信度也应在推理时被考虑。代理对记忆的信心不应是静态的;它必须根据新信息和时间的推移而演变。信心通过确证增加。相反,信心随时间降低(或衰减),因为旧记忆变得陈旧,并且当引入矛盾信息时也会下降。最终,系统可以通过归档或删除低置信度的记忆来“遗忘”。这种动态置信度分数在推理时至关重要。记忆及其置信度分数(如果有)不是直接展示给用户,而是被注入到提示中,使 LLM 能够评估信息可靠性并做出更细微的决策。

整个信任框架服务于代理的内部推理过程。记忆及其置信度分数通常不直接向用户显示。相反,它们被注入到系统提示中,允许 LLM 权衡证据,考虑其信息的可靠性,并最终做出更细微和值得信赖的决策。

触发记忆生成

虽然一旦触发生成,记忆管理器就会自动化记忆提取和整合,但代理仍必须决定何时应尝试生成记忆。这是一个关键的架构选择,平衡数据新鲜度与计算成本和延迟。此决定通常由代理的逻辑管理,该逻辑可以采用几种触发策略。记忆生成可以基于各种事件启动:

  • 会话完成
    在多轮会话结束时触发生成。
  • 轮次节奏
    在特定轮数后运行该过程(例如,每 5 轮)。
  • 实时
    在每一轮之后生成记忆。
  • 显式命令
    根据直接的用户命令激活该过程(例如,“记住这个”)。

触发器的选择涉及成本和保真度之间的直接权衡。频繁生成(例如,实时)确保记忆高度详细和新鲜,捕获对话的每一个细微差别。然而,这会产生最高的 LLM 和数据库成本,并且如果处理不当可能会引入延迟。不频繁生成(例如,会话完成时)更具成本效益,但有创建低保真记忆的风险,因为 LLM 必须一次性总结更大块的对话。您还需要小心,确保记忆管理器不会多次处理相同的事件,因为这会引入不必要的成本。

记忆即工具 (Memory-as-a-Tool)

一种更复杂的方法是允许代理自己决定何时创建记忆。在这种模式中,记忆生成作为一个工具(即 `create_memory`)暴露出来;工具定义应定义哪些类型的信息应被认为是有意义的。然后,代理可以分析对话,并在识别出有意义的持久化信息时自主决定调用此工具。这将识别“有意义信息”的责任从外部记忆管理器转移到了代理(也就是作为开发者的你)身上。

例如,您可以使用 ADK 通过将记忆生成代码打包成一个工具21来实现这一点,代理决定何时调用它。您可以将会话发送到 Memory Bank,Memory Bank 将从对话历史中提取并整合记忆:

from google.adk.agents import LlmAgent
from google.adk.memory import VertexAiMemoryBankService
from google.adk.runners import Runner
from google.adk.tools import ToolContext

def generate_memories(tool_context: ToolContext):
    """触发记忆生成以记住会话。"""

    # 选项 1: 使用 ADK 记忆服务从完整的对话历史中提取记忆。
    tool_context._invocation_context.memory_service.add_session_to_memory(session)

    # 选项 2: 从上一轮对话中提取记忆。
    client.agent_engines.memories.generate(
        name="projects/.../locations/...reasoningEngines/...",
        direct_contents_source={
            "events": [
                {"content": tool_context._invocation_context.user_content}
            ]
        },
        scope={
            "user_id": tool_context._invocation_context.user_id,
            "app_name": tool_context._invocation_context.app_name
        },
        # 在后台生成记忆
        config={"wait_for_completion": False}
    )
    return {"status": "success"}

agent = LlmAgent(
    tools=[generate_memories]
)

runner = Runner(
    agent=agent,
    app_name=APP_NAME,
    session_service=session_service,
    memory_service=VertexAiMemoryBankService(...)
)
代码片段 8: 使用自定义工具触发记忆生成的 ADK 代理

另一种方法是利用内部记忆,代理主动决定从对话中记住什么。在此工作流中,代理负责提取关键信息。可选地,这些提取的记忆随后被发送到 Agent Engine Memory Bank 以与用户的现有记忆整合22

def extract_memories(query: str, tool_context: ToolContext):
    """触发记忆生成以记住信息。

    Args:
        query: 应关于用户持久保存的有意义信息。
    """

    client.agent_engines.memories.generate(
        name="projects/.../locations/...reasoningEngines/...",

        # 有意义的信息已从对话中提取,所以我们只想将其与同一用户的现有记忆整合。
        direct_memories_source={
            "direct_memories": [{"fact": query}]
        },
        scope={
            "user_id": tool_context._invocation_context.user_id,
            "app_name": tool_context._invocation_context.app_name
        },
        config={"wait_for_completion": False}
    )
    return {"status": "success"}

agent = LlmAgent(
    tools=[extract_memories]
)
代码片段 9: 使用自定义工具从对话中提取记忆并触发整合的 ADK 代理

后台与阻塞操作

记忆生成是一个昂贵的操作,需要 LLM 调用和数据库写入。对于生产中的代理,记忆生成几乎应始终作为后台进程异步处理23

在代理向用户发送响应后,记忆生成管道可以并行运行,而不会阻塞用户体验。这种解耦对于保持代理感觉快速和响应灵敏至关重要。阻塞(或同步)方法,即用户必须等待记忆写入后才能收到响应,会导致不可接受的缓慢和令人沮丧的用户体验。这要求记忆生成发生在与代理核心运行时架构上分离的服务中。

记忆检索

有了记忆生成机制,您的重点可以转移到检索这一关键任务上。智能检索策略对于代理的性能至关重要,包括关于应检索哪些记忆以及何时检索的决定。

检索记忆的策略很大程度上取决于记忆的组织方式。对于结构化用户档案,检索通常是针对完整档案或特定属性的直接查找。然而,对于记忆集合,检索是一个复杂得多的搜索问题。目标是从大量非结构化或半结构化数据中发现最相关、概念上相关的信息。本节讨论的策略旨在解决记忆集合的这一复杂检索挑战。

记忆检索为当前对话搜索最相关的记忆。有效的检索策略至关重要;提供不相关的记忆可能会混淆模型并降低其响应质量,而找到完美的上下文片段可能会导致非常智能的交互。核心挑战是在严格的延迟预算内平衡记忆的“有用性”。

高级记忆系统超越了简单的搜索,并在多个维度上对潜在记忆进行评分,以找到最佳匹配:

  • 相关性 (语义相似性)
    此记忆与当前对话在概念上的相关程度如何?
  • 近时性 (基于时间)
    此记忆是多久前创建的?
  • 重要性 (显著性)
    此记忆总体上有多关键?与相关性不同,记忆的“重要性”可以在生成时定义。

仅依赖基于向量的相关性是一个常见的陷阱。相似性分数可能会浮现出概念上相似但陈旧或琐碎的记忆。最有效的策略是混合方法,结合所有三个维度的分数。

对于准确性至关重要的应用程序,可以使用查询重写、重排序 (reranking) 或专用检索器等方法来细化检索。然而,这些技术计算成本高且增加了显著的延迟,使其不适合大多数实时应用程序。对于这些复杂算法是必要的且记忆不会很快变陈旧的场景,缓存层可以是有效的缓解措施。缓存允许临时存储检索查询的昂贵结果,绕过后续相同请求的高延迟成本。

  • 使用查询重写,可以使用 LLM 来改进搜索查询本身。这可能涉及将用户的模糊输入重写为更精确的查询,或者将单个查询扩展为多个相关查询以捕获主题的不同方面。虽然这显着提高了初始搜索结果的质量,但它在流程开始时增加了额外 LLM 调用的延迟。
  • 使用重排序,初始检索使用相似性搜索获取广泛的候选记忆集(例如,前 50 个结果)。然后,LLM 可以重新评估并重新排序这个较小的集合,以产生更准确的最终列表24
  • 最后,您可以使用微调来训练专用的检索器。但这需要访问标记数据,并可能显着增加成本。

最终,最好的检索方法始于更好的记忆生成。确保记忆语料库高质量且没有不相关信息,是保证任何检索到的记忆集都有帮助的最有效方法。

检索时机

检索的最后一个架构决策是何时检索记忆。一种方法是主动检索,即在每一轮开始时自动加载记忆。这确保上下文始终可用,但会为不需要记忆访问的轮次引入不必要的延迟。由于记忆在单轮中保持静态,可以有效地缓存它们以减轻这种性能成本。

例如,您可以使用 ADK 的内置 `PreloadMemoryTool` 或自定义回调来实现主动检索25

# 选项 1: 使用内置的 PreloadMemoryTool,每轮使用相似性搜索检索记忆。
agent = LlmAgent(
    tools=[adk.tools.preload_memory_tool.PreloadMemoryTool()]
)

# 选项 2: 使用自定义回调来更好地控制记忆的检索方式。
def retrieve_memories_callback(callback_context, llm_request):
    # ... (省略代码细节,见原文) ...
    # 将格式化的记忆追加到系统指令
    llm_request.config.system_instruction += "\nHere is information that you have about the user:\n"
    llm_request.config.system_instruction += "\n".join(memories)

agent = LlmAgent(
    before_model_callback=retrieve_memories_callback,
)
代码片段 10: 使用 ADK 在每轮开始时检索记忆

或者,您可以使用反应式检索 ("Memory-as-a-Tool"),其中代理获得一个查询其记忆的工具,自己决定何时检索上下文。这更高效、更健壮,但需要额外的 LLM 调用,增加了延迟和成本;但是,仅在必要时检索记忆,因此延迟成本发生的频率较低。此外,代理可能不知道是否存在要检索的相关信息。但这可以通过让代理了解可用记忆的类型(例如,在使用自定义工具时的工具描述中)来缓解,从而允许就何时查询做出更明智的决定。

# 选项 1: 使用内置的 LoadMemory。
agent = LlmAgent(
    tools=[adk.tools.load_memory_tool.LoadMemoryTool()],
)

# 选项 2: 使用自定义工具,您可以在其中描述可能可用的信息类型。
def load_memory(query: str, tool_context: ToolContext):
    """为用户检索记忆。
    可能存储了以下类型的用户信息:
    * 用户偏好,如用户最喜欢的食物。
    ...
    """
    response = tool_context.search_memory(query)
    return response.memories

agent = LlmAgent(
    tools=[load_memory],
)
代码片段 11: 配置 ADK 代理决定何时检索记忆

带记忆的推理

一旦检索到相关记忆,最后一步是将它们策略性地放入模型的上下文窗口中。这是一个关键过程;记忆的放置会显着影响 LLM 的推理,影响运营成本,并最终决定最终答案的质量。

记忆主要通过追加到系统指令或注入到对话历史中来呈现。在实践中,混合策略通常是最有效的。对应该始终存在的稳定、全局记忆(如用户档案)使用系统提示。否则,对仅与对话即时上下文相关的短暂、情景记忆使用对话注入或记忆即工具。这平衡了对持久上下文的需求与即时信息检索的灵活性。

系统指令中的记忆

使用记忆进行推理的一个简单选项是将记忆追加到系统指令中。此方法通过将检索到的记忆与前言一起直接追加到系统提示中,将它们框架化为整个交互的基础上下文,从而保持对话历史的整洁。例如,您可以使用 Jinja 动态地将记忆添加到您的系统指令中:

from jinja2 import Template

template = Template("""
{{ system_instructions }}

Here is some information about the user:
{% for retrieved_memory in data %}
* {{ retrieved_memory.memory.fact }}
{% endfor %}

""")

template.render(
    system_instructions=system_instructions,
    prompt=...
)
代码片段 12: 使用检索到的记忆构建系统指令

在系统指令中包含记忆赋予记忆高权威性,干净地将上下文与对话分离,并且是稳定、“全局”信息(如用户档案)的理想选择。然而,存在过度影响的风险,即代理可能会试图将每个主题都与核心指令中的记忆联系起来,即使这并不恰当。

这种架构模式引入了几个约束。首先,它要求代理框架支持在每次 LLM 调用之前动态构建系统提示;这种功能并不总是现成支持的。此外,鉴于系统提示必须在 LLM 决定调用记忆检索工具之前最终确定,该模式与“记忆即工具”不兼容。最后,它很难处理非文本记忆。大多数 LLM 只接受文本作为系统指令,这使得直接将图像或音频等多模态内容嵌入提示中变得具有挑战性。

对话历史中的记忆

在这种方法中,检索到的记忆直接注入到逐轮对话中。记忆可以放置在完整对话历史之前,或者紧接在最新的用户查询之前。

然而,这种方法可能会很嘈杂,增加 Token 成本,如果检索到的记忆不相关,可能会混淆模型。其主要风险是对话注入,即模型可能会错误地将记忆视为对话中实际说过的内容。您还需要更加小心您注入到对话历史中的记忆的视角;例如,如果您使用“user”角色和用户级记忆,记忆应以第一人称视角书写。

通过工具调用检索记忆是将记忆注入对话历史的一种特殊情况。记忆将作为工具输出的一部分直接包含在对话中。

def load_memory(query: str, tool_context: ToolContext):
    """将记忆加载到对话历史中..."""
    response = tool_context.search_memory(query)
    return response.memories

agent = LlmAgent(
    tools=[load_memory],
)
代码片段 13: 将记忆作为工具检索,直接插入对话中

程序性记忆

本白皮书主要关注陈述性记忆,这一重点反映了当前的商业记忆格局。大多数记忆管理平台也是为这种陈述性方法构建的,擅长提取、存储和检索“什么”——事实、历史和用户数据。

然而,这些系统并非设计用于管理程序性记忆,即改进代理工作流程和推理的机制。存储“如何做”不是一个信息检索问题;它是一个推理增强问题。管理这种“知道如何”需要一个完全独立和专门的算法生命周期,尽管具有类似的高级结构26

  1. 提取
    程序性提取需要专门的提示,旨在从成功的交互中提炼出可重用的策略或“剧本”,而不仅仅是捕获事实或有意义的信息。
  2. 整合
    虽然陈述性整合合并相关事实(“什么”),但程序性整合整理工作流本身(“如何”)。这是一个主动的逻辑管理过程,专注于将新的成功方法与现有的“最佳实践”集成,修补已知计划中的缺陷步骤,并修剪过时或无效的程序。
  3. 检索
    目标不是检索数据来回答问题,而是检索指导代理如何执行复杂任务的计划。因此,程序性记忆可能具有与陈述性记忆不同的数据模式。

代理“自我进化”其逻辑的能力自然会引来与一种常见的适应方法的比较:微调——通常通过人类反馈的强化学习 (RLHF)27。虽然这两个过程都旨在改善代理行为,但它们的机制和应用根本不同。微调是一个相对缓慢的离线训练过程,会改变模型权重。程序性记忆通过将正确的“剧本”动态注入提示中,通过上下文学习指导代理而无需任何微调,从而提供快速的在线适应。

测试与评估

现在您有了一个启用记忆的代理,您应该通过全面的质量和评估测试来验证其行为。评估代理的记忆是一个多层次的过程。评估需要验证代理记住了正确的事情(质量),它可以在需要时找到那些记忆(检索),并且使用那些记忆实际上有助于它完成目标(任务成功)。虽然学术界专注于可重现的基准,但行业评估集中在记忆如何直接影响生产代理的性能和可用性。

  • 记忆生成质量指标
    评估记忆本身的内容,回答问题:“代理是否记住了正确的事情?” 这通常是通过将代理生成的记忆与手动创建的理想记忆“黄金集”进行比较来衡量的。
    • 精确度 (Precision)
      在代理创建的所有记忆中,有多少百分比是准确且相关的?高精确度可以防止“过度急切”的记忆系统用不相关的噪音污染知识库。
    • 召回率 (Recall)
      在它应该从源中记住的所有相关事实中,它捕获了多少百分比?高召回率确保代理不会错过关键信息。
    • F1-分数
      精确度和召回率的调和平均数,提供单一、平衡的质量度量。
  • 记忆检索性能指标
    评估代理在正确时间找到正确记忆的能力。
    • Recall@K
      当需要记忆时,是否在前 'K' 个检索结果中找到了正确的记忆?这是检索系统准确性的主要衡量标准。
    • 延迟
      检索处于代理响应的“热路径”上。整个检索过程必须在严格的延迟预算内执行(例如,低于 200ms),以避免降低用户体验。
  • 端到端任务成功指标
    是终极测试,回答问题:“记忆实际上有助于代理更好地完成工作吗?” 这通过使用其记忆评估代理在下游任务上的表现来衡量,通常使用 LLM “法官”将代理的最终输出与标准答案进行比较。法官确定代理的答案是否准确,有效地衡量了记忆系统对最终结果的贡献程度。

评估不是一次性事件;它是持续改进的引擎。上述指标提供了识别弱点并随时间系统地增强记忆系统所需的数据。这个迭代过程涉及建立基线、分析故障、调整系统(例如,优化提示、调整检索算法)并重新评估以衡量变更的影响。

虽然上述指标侧重于质量,但生产准备就绪程度也取决于性能。对于每个评估领域,测量底层算法的延迟及其在负载下扩展的能力至关重要。“在热路径上”检索记忆可能具有严格的亚秒级延迟预算。生成和整合虽然通常是异步的,但必须有足够的吞吐量来跟上用户需求。最终,一个成功的记忆系统必须是智能、高效且对现实世界使用具有鲁棒性的。

记忆的生产环境考量

除了性能之外,将启用记忆的代理从原型过渡到生产需要关注企业级架构问题。此举引入了对可扩展性、弹性和安全性的关键要求。生产级系统不仅要为智能而设计,还要为企业级鲁棒性而设计。

为了确保用户体验永远不会被计算昂贵的记忆生成过程所阻塞,健壮的架构必须将记忆处理与主应用程序逻辑解耦。虽然这是一种事件驱动模式,但它通常通过对专用记忆服务的直接、非阻塞 API 调用来实现,而不是通过自管理的消息队列。流程如下:

  1. 代理推送数据
    在相关事件(例如,会话结束)之后,代理应用程序对记忆管理器进行非阻塞 API 调用,“推送”原始源数据(如对话记录)进行处理。
  2. 记忆管理器在后台处理
    记忆管理器服务立即确认请求,并将生成任务放入其自己的内部托管队列中。然后,它全权负责异步的繁重工作:进行必要的 LLM 调用以提取、整合和格式化记忆。管理器可能会延迟处理事件,直到经过一段时间的不活动。
  3. 记忆被持久化
    服务将最终记忆——可能是新条目或对现有条目的更新——写入专用的、持久的数据库。对于托管记忆管理器,存储是内置的。
  4. 代理检索记忆
    当主代理应用程序需要为新的用户交互检索上下文时,它可以直接查询此记忆存储。

这种基于服务的非阻塞方法确保记忆管道中的故障或延迟不会直接影响面向用户的应用程序,使系统更具弹性。它还为选择在线(实时)生成(适用于对话新鲜度)和离线(批处理)处理(适用于从历史数据填充系统)提供了依据。

随着应用程序的增长,记忆系统必须处理高频事件而不发生故障。鉴于并发请求,系统必须防止多个事件试图修改同一记忆时的死锁或竞争条件。您可以使用事务数据库操作或乐观锁定来缓解竞争条件;然而,当多个请求试图修改相同的记忆时,这可能会引入排队或节流。健壮的消息队列对于缓冲大量事件并防止记忆生成服务不堪重负至关重要。

记忆服务还必须对瞬态错误具有弹性(故障处理)。如果 LLM 调用失败,系统应使用带有指数退避的重试机制,并将持续失败路由到死信队列进行分析。

对于全球应用程序,记忆管理器必须使用具有内置多区域复制功能的数据库,以确保低延迟和高可用性。客户端复制是不可行的,因为整合需要数据的单一、事务一致的视图以防止冲突。因此,记忆系统必须在内部处理复制,向开发者呈现单一的逻辑数据存储,同时确保底层知识库在全球范围内一致。

像 Agent Engine Memory Bank 这样的托管记忆系统应帮助您解决这些生产考量,以便您可以专注于核心代理逻辑。

隐私与安全风险

记忆源自并包含用户数据,因此需要严格的隐私和安全控制。一个有用的类比是将系统的记忆视为由专业档案管理员管理的安全公司档案,其工作是在保护公司的同时保存有价值的知识。

此档案的首要规则是数据隔离。就像档案管理员永远不会混合来自不同部门的机密文件一样,记忆必须严格在用户或租户级别进行隔离。服务于一个用户的代理绝不能访问另一个用户的记忆,这使用限制性访问控制列表 (ACL) 来强制执行。此外,用户必须对其数据拥有程序控制权,并有明确的选项选择退出记忆生成或请求从档案中删除其所有文件。

在归档任何文件之前,档案管理员会执行关键的安全步骤。首先,他们仔细检查每一页以编校 (redact) 敏感的个人信息 (PII),确保在不造成责任的情况下保存知识。其次,档案管理员受过训练,能够发现并丢弃伪造或故意误导的文件——这是防止记忆投毒 (memory poisoning)28 的保障措施。同样,系统必须在将信息提交到长期记忆之前对其进行验证和清理,以防止恶意用户通过提示注入破坏代理的持久知识。系统必须包括像 Model Armor 这样的保障措施,在将信息提交到长期记忆之前对其进行验证和清理29

此外,如果多个用户共享同一组记忆,如程序性记忆(教导代理如何做某事),则存在泄露风险。例如,如果一个用户的程序性记忆被用作另一个用户的示例——就像在全公司范围内共享备忘录一样——档案管理员必须首先执行严格的匿名化,以防止敏感信息跨用户边界泄露。

结论

本白皮书探讨了上下文工程的学科,重点关注其两个中心组件:会话和记忆。从简单的对话轮次到持久、可操作的情报的过程受此实践支配,该实践涉及将所有必要信息——包括对话历史、记忆和外部知识——动态组装到 LLM 的上下文窗口中。这整个过程依赖于两个不同但相互关联的系统之间的相互作用:即时会话和长期记忆。

会话支配着“现在”,充当单个对话的低延迟、按时间顺序排列的容器。其主要挑战是性能和安全性,需要低延迟访问和严格隔离。为了防止上下文窗口溢出和延迟,您必须使用令牌截断或递归摘要等提取技术来压缩会话历史或单个请求负载中的内容。此外,安全性至关重要,要求在持久化会话数据之前进行 PII 编校。

记忆是长期个性化的引擎,也是跨多个会话持久化的核心机制。它超越了 RAG(使代理成为事实专家),使代理成为用户专家。记忆是一个主动的、LLM 驱动的 ETL 管道——负责提取、整合和检索——它从对话历史中提炼出最重要的信息。通过提取,系统将最关键的信息提炼成关键记忆点。随后,整合整理并将此新信息与现有语料库集成,解决冲突,并删除冗余数据以确保连贯的知识库。为了保持敏捷的用户体验,记忆生成必须在代理响应后作为异步后台进程运行。通过跟踪溯源并采用针对记忆投毒等风险的保障措施,开发者可以构建真正与用户一起学习和成长的值得信赖的、自适应的助手。


尾注 (References)

  1. Google Cloud. (n.d.). Retrieval-Augmented Generation (RAG) [检索增强生成]. Retrieved from https://cloud.google.com/use-cases/retrieval-augmented-generation?hl=en
  2. Brown, T. et al. (2020). Language Models are Few-Shot Learners [语言模型是少样本学习者]. Retrieved from https://arxiv.org/abs/2301.00234 (注:链接指向相关概念论文)
  3. Google Cloud. (n.d.). Sessions Overview - Agent Engine [会话概览 - 代理引擎]. Retrieved from https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/sessions/overview
  4. LangChain. (n.d.). Message Passing Between Agents [代理间的消息传递]. Retrieved from https://langchain-ai.github.io/langgraph/concepts/multi_agent/#message-passing-between-agents
  5. Google. (n.d.). Multi-Agents - ADK Docs [多智能体 - ADK 文档]. Retrieved from https://google.github.io/adk-docs/agents/multi-agents/
  6. Google. (n.d.). Explicit Invocation (Agent as Tool) [显式调用(代理即工具)]. Retrieved from https://google.github.io/adk-docs/agents/multi-agents/#c-explicit-invocation-agenttool
  7. Agent2Agent. (n.d.). Message Concepts [消息概念]. Retrieved from https://agent2agent.info/docs/concepts/message/
  8. Google Developers. (n.d.). A2A: A New Era of Agent Interoperability [A2A:代理互操作性的新时代]. Retrieved from https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
  9. Google Cloud. (n.d.). Model Armor Overview [Model Armor 概览]. Retrieved from https://cloud.google.com/security-command-center/docs/model-armor-overview
  10. Google AI. (n.d.). Long Context Limitations [长上下文限制]. Retrieved from https://ai.google.dev/gemini-api/docs/long-context#long-context-limitations
  11. Hugging Face. (n.d.). Memory in LLM Agents [LLM 代理中的记忆]. Retrieved from https://huggingface.co/blog/Kseniase/memory
  12. LangChain. (n.d.). Semantic Memory - LangGraph [语义记忆]. Retrieved from https://langchain-ai.github.io/langgraph/concepts/memory/#semantic-memory
  13. LangChain. (n.d.). Semantic Memory - LangGraph [语义记忆]. Retrieved from https://langchain-ai.github.io/langgraph/concepts/memory/#semantic-memory
  14. Xu, Z. et al. (2024). Atomic Facts in Knowledge Graphs [知识图谱中的原子事实]. Retrieved from https://arxiv.org/pdf/2412.15266
  15. Xu, Z. et al. (2024). Knowledge Triples [知识三元组]. Retrieved from https://arxiv.org/pdf/2412.15266
  16. Google Cloud. (n.d.). Multimodal Prompts for Text Generation [用于文本生成的多模态提示]. Retrieved from https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#sample-requests-text-gen-multimodal-prompt
  17. Google Cloud. (n.d.). Generate Memories - Agent Engine [生成记忆]. Retrieved from https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/generate-memories
  18. Google Cloud. (n.d.). Control Generated Output [控制生成输出]. Retrieved from https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/control-generated-output
  19. Google Cloud. (n.d.). Memory Bank Configuration [记忆库配置]. Retrieved from https://cloud.google.com/agent-builder/agent-engine/memory-bank/set-up#memory-bank-config
  20. Shao, Y. et al. (2025). Rolling Summarization for Long Context [长上下文的滚动摘要]. Retrieved from https://arxiv.org/html/2504.19413v1
  21. Google. (n.d.). How Agents Use Tools - ADK Docs [代理如何使用工具]. Retrieved from https://google.github.io/adk-docs/tools/#how-agents-use-tools
  22. Google Cloud. (n.d.). Consolidate Pre-extracted Memories [整合预提取的记忆]. Retrieved from https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/generate-memories#consolidate-pre-extracted-memories
  23. Google Cloud. (n.d.). Background Memory Generation [后台记忆生成]. Retrieved from https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/generate-memories#background-memory-generation
  24. Wang, L. et al. (2025). Reranking for Memory Retrieval [记忆检索的重排序]. Retrieved from https://arxiv.org/pdf/2503.08026
  25. Google. (n.d.). Callbacks - ADK Docs [回调]. Retrieved from https://google.github.io/adk-docs/callbacks/
  26. Zhang, J. et al. (2025). Procedural Memory in Agents [代理中的程序性记忆]. Retrieved from https://arxiv.org/html/2508.06433v2
  27. Google Cloud. (n.d.). RLHF on Google Cloud [Google Cloud 上的 RLHF]. Retrieved from https://cloud.google.com/blog/products/ai-machine-learning/rlhf-on-google-cloud
  28. Liu, Y. et al. (2025). Memory Poisoning Attacks [记忆投毒攻击]. Retrieved from https://arxiv.org/pdf/2503.03704
  29. Google Cloud. (n.d.). Model Armor Overview [Model Armor 概览]. Retrieved from https://cloud.google.com/security-command-center/docs/model-armor-overview
  30. Google Cloud. (n.d.). Choose Design Pattern for Agentic AI System [为代理 AI 系统选择设计模式]. Retrieved from https://cloud.google.com/architecture/choose-design-pattern-agentic-ai-system
 
打赏
 
更多>同类资讯
0相关评论

推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  皖ICP备20008326号-18
Powered By DESTOON