前言
在基于大模型智慧能力的应用越来越普遍的今天,如何设计、开发与维护好应用里面与AI对接的核心模块——智能体,成为了AI程序开发者需要深入研究的课题。如何在llm模型non-deterministic的本质上构建起deterministic的应用,需要在深刻理解大模型的能力与局限的同时,引入软件工程和系统运维的最佳实践。
google在2025年11月发布了5本Agent白皮书,旨在分享他们在构建生产级AI智能体的经验,感兴趣的读者可以在这篇公众号文章找到链接:https://mp.weixin.qq.com/s/lKyX_1cFATjZazpLyQg6uA
今天,我们来读一下其中的Context Engineering一书,记录下谷歌是如何将智能体的上下文用工程化的思路进行管理的,原文链接:
Context Engineering: Sessions & Memory
上下文工程是什么
由于大语言模型无状态的本质,撇除其本身的训练参数外,它的知识和对外界的认识都被局限在每一次api调用的上下文中。基于这一事实,如何更科学有效地在有限的上下文长度中,赋予大模型回答问题所需的全部上下文,包括会话历史,外部数据,知识等,便是上下文工程要解决的问题。
上下文工程主要负责将以下元素合理地组合到输给大模型的payload:
- 引导模型如何推理的上下文
- 系统提示词(人设,能力,边界等)
- 工具定义
- few-shot示例
- 真实、准确的数据(用于避免幻觉)
- 长期记忆(跨session的用户会话)
- 外部知识
- 工具调用结果
- 子智能体的输出结果
- 图片、档案等文件
- 会话中间信息
- 当前会话历史
- 状态/手写板(当前工作模型输出的中间结果)
- 用户提示词
如何科学地将这些元素塞进每一次输入給大模型的上下文,是搭建稳定可靠的智能体的关键。同时,为了有效对抗上下文过长导致模型注意力下降的问题,上下文工程还涉及到动态调整当前的会话历史,比如说选择性地压缩、清理先前的对话,仅保留关键的信息来腾出上下文空间给新的输入。
下面是一种循环性优化上下文的智能体框架:
基本流程:相关信息提取(从rag,网络,会话历史)→ 准备上下文→ 输入LLM和工具调用 → 更新上下文/会话,整个流程的同时,异步地持久化到记忆存储。
基于这个上下文工程的总览,我们可以深入探讨其中两个核心部分:会话和记忆
会话
会话包括当前用户与大模型对话的全部内容,包括用户问题、模型回答、工具调用、计划等,大模型的api每次都需要把整段对话作为输入,比如说:
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
)
多智能体系统会话
实践上,单一智能体无法有效解决现实世界的复杂问题,此时,通过多个智能体互相协作,每个负责专门、小范围的任务,最后再进行汇总,可以显著提高回答的质量,同时得益于并发运行,降低延迟。而如何高效地在不同智能体中共享信息,如何共享当前会话的内容,就成了关键。
基本上,可以分为两种范式:集中记录和独立记录。
集中记录将所有智能体的思考、输出、工具调用都写入同一个会话历史中,这种范式适合多个智能体,或者子智能体模式下,共同紧密协作解决某个明确任务的适合。在这种模式下,我们需要通过过滤,打标签等方法来筛选输入给各个智能体的上下文。
独立记录模式下,每个智能体独自管理自己的会话历史,通过Agent-as-a-Tool(把其他Agent当作可调用的工具)或者Agent-to-Agent(A2A)协议进行通信
生产环境会话管理
当我们把智能体部署到生产环境时,其会话管理则需要严肃考虑三个方面:
- 安全与隐私:需要做如数据脱敏,严格RBAC等
- 数据一致性:会话的写入需要遵循deterministic的顺序(seriallizable?)
- 性能:会话历史是访问热点,需要满足低延迟来保证用户体验
会话压缩策略
为了成本和大模型注意力的考虑,智能体应用需要持续的对会话历史进行压缩截断,简单的策略是保持最近N论对话,或者N个token,而更加复杂有效的,则需要用到大模型来对先前的对话进行总结:递归地对过往会话进行总结,这个过程一般是异步的,以免影响到用户体验。
记忆
记忆是从每个会话或者其他数据源中提炼出来的有意义的信息,它为智能体解锁了以下能力:
- 个性化——透过记忆,智能体能够跨会话记住用户的对话、偏好等
- 上下文窗口管理——会话历史压缩成记忆可以有效降低上下文
- 数据挖掘——大数据下用户对某个智能体的记忆能够揭示智能体的使用情况
- 自我提升与自适应——智能体可以通过过往的交互来建立对自己解决方案的持续认识,构建解决问题有效路径的笔记本
在智能体应用中集成记忆功能,需要多个模块的支持:
实现上,知识的读取可以分为两种:Memory-as-a-tool和静态检索,前者把记忆封装成一个tool供大模型选择性的调用,后者像rag一样基于用户的问题去检索,每次都会嵌入上下文。
记忆的表示与存储
那么记忆应该怎么表示呢?google提出,记忆可以分成两类,用内容和元数据表示:
- 陈述性记忆——陈述现实世界中的事实,人物和事件
- 流程性记忆——描述如何实现某个目的的流程和技巧
对于这些记忆,大致有三种组织模式:
- collections——若干段记忆组成一个集合供智能体读取,每个记忆描述独立的事件、观测
- 结构化用户画像——将记忆处理成一个结构化的用户卡片,描述姓名、年龄、偏好等基本信息
- 滚动摘要——一个不断又智能体更新滚动的记忆大文档
如何储存?一般也有三种模式:
- 向量数据库
- 知识图谱
- 混合模式——用向量来充实知识图谱节点的信息,使得系统可以同时进行语义检索和关系检索
创建机制
记忆是如何创建的呢?有两种方式:
- 用户声明让大模型记住某些知识——“记住我12月15号生日”
- 大模型从对话中提取出来记忆——“我下周二有个同学聚会,帮我…”
创建的记忆如何存放?一般分为内部存储和外部存储,其中内部就是在智能体框架中管理,而外部存储如Mem0, Zep则提供API接口供框架调用,这种方式支持更复杂的记忆相关管理,如语义检索,动态总结等,同时这些复杂的操作转移外部系统,不会影响智能体框架本身的运行,下面是一个高层次的创建流程图:
记忆提取与记忆固化
记忆提取决定了会话中哪些信息是“重要”的,需要智能体记住。记忆管理器按照一系列提示词指引从会话中提取出结构化的信息,如用户基本信息,商业信息等,一些记忆管理的库还会支持few-shots来教会大模型应该如何提炼记忆。
记忆固化可以说是记忆管理生命周期最重要的一环:它负责动态地将会话历史转变成对用户的深入理解,主要来说,它负责解决记忆信息的这些问题:
- 记忆重复——会话中可能重复提及某些信息,需要去重
- 冲突信息——用户的信息可能随着会话进行有更新,如果没有固化并由大模型来理解,可能会提取出相互矛盾的事实
- 信息演化——同样的,信息可能会有更新的情况:“用户有一个女朋友”→“用户有一个家庭”
- 记忆相关性衰退——不管从存储限制考虑,还是现实世界的情况出发,记忆都不会永远一直有效,需要有策略性的对它们进行遗忘
具体来说,记忆固化大致上是一个LLM工作流:
- 记忆管理器从新的会话中提取记忆
- 新的记忆与存储中的记忆进行对比
- 进行更新操作,如失效、删除、创建、更新等,最后持久化到存储中
记忆溯源
为了确保在长期使用中智能体记忆的可信度,我们的记忆需要是可溯源的,智能体在有必要的时候,需要追溯某段知识是来源于会话的哪些内容:有些时候,某段记忆可能来源与多段对话的总结,有些时候,一段对话可以延伸出多段记忆:
何时触发记忆生成
智能体框架需要决定何时从会话中生成新的记忆:基本上就是频率和成本的权衡,一般有这些触发时机:
- 会话完成——在会话结束后进行记忆提起
- 轮次总结——每多少轮对话进行
- 主动触发——用户明确要求智能体记住的时候
- 自行决定——假如我们把记忆封装成工具,则可以在提示词中指示llm在遇到“重要”信息时,调用该工具来创建记忆(何为“重要”需要开发者准确定义)
记忆检索
基本上跟rag一样,可以用混合的方式来根据三个维度进行检索:
- 语义相似度
- 时效性
- 重要性(可能需要模型自己评分?)
什么时候提供记忆给LLM?可以像RAG一样每次对用户的问题做语义检索,自动嵌入,也可以封装成工具让大模型自己决定是否需要调用,此时,工具的描述需要提示大模型有什么记忆可以读取:
def load_memory(query: str, tool_context: ToolContext):
"""Retrieves memories for the user.
The following types of information may be stored for the user:
* User preferences, like the user's favorite foods.
...
"""
# Retrieve memories using similarity search.
response = tool_context.search_memory(query)
return response.memories
如何在提示词引入记忆
如果记忆是全局性的背景知识,如用户画像,则建议在系统提示词中引入,这通常会给引入的记忆很高的优先级,我们需要小心避免模型过度重视这些记忆,在不合适的时候也尝试在对话中引用这些记忆。
如果记忆是取决于当前场景需要的,则建议通过封装工具调用或者直接在用户提问前的提示词中进行嵌入,文中提到,假如构造的记忆message使用user角色的话,则记得要使用第一人称(我记得“{memory}”),避免模型产生混乱。
流程性记忆
这份白皮书主要介绍如何管理陈述性记忆,并未太多提及如何管理让智能体更好执行任务的流程性记忆,不过文中提到,它们都遵循同样的流程,虽然方法不一样:
- 提取——需要专门的提示词和工程方法从会话中,包括工具调用和用户反馈,提取出有效的方法论,形成playbook
- 固化——需要动态地评估playbook的执行效果,同旧的进行比较,并进行步骤更新
- 检索——playbook需要不同的数据结构进行检索
测试与评估
我们在上一期Agent Quality系统性地介绍了智能体的质量管理体系,同样地,我们可以遵循一样的工程思维对记忆模块进行质量管理。对于智能体记忆能力的评估,可以分为两类:
- 记忆生成的质量
- 准确率:在所有智能体生成的记忆中,有多少是相关而准确的
- 召回率:对于对话中所有相关的事实与信息,有多少被智能体提取到
- f1-score:前二者的平衡分数
- 记忆召回的能力
- Recall@K:当某段记忆被需要用来回答问题的时候,它是否出现在被召回的前k段记忆中
- 延迟:召回是智能体响应的关键路径之一,需要维持低延迟来满足用户体验
高层次地衡量,我们同样可以用端到端任务成功率来衡量质量:用大模型来比较模型引用记忆后的回答与某个标准答案,是否最终成功完成用户的提问。
总结
在这份白皮书中,google重点介绍了智能体应用中上下文工程的两大部分,会话与记忆。会话管理了用户当前对话的上下文,其目的在于通过滚动总结等技术手段,使得用户不断增加的会话历史可以塞进模型有效的上下文中。记忆则是用户个性化体验和跨会话持久化能力的核心,通过不断从会话中提取、固化、更新记忆,智能体能够超越大模型上下文以外一概不知的局限,变得如真人一样不断的记住外部世界发生的事件,并在后续的会话中引用它们。
comments powered by Disqus