区块链 区块链技术 比特币公众号手机端

AI Agent中的上下文工程与记忆工程

图像

在本文中,你将了解上下文工程和记忆工程如何解决 agentic AI 系统中的不同问题,以及这两个学科如何在检索到的记忆进入上下文窗口的交汇点相遇。

引言

图像

随着 AI agents 进入更长的工作流程和多会话用例,一种熟悉的模式浮现出来。约束在任务中途被丢弃,检索到的信息在不该出现的时候重新浮出水面,上一步骤的上下文渗入当前步骤。这些故障很难定位,因为没有单个组件明显有问题。

大多数情况下,问题出在两个被一起构建、混为一谈或被跳过的领域:上下文工程 和 记忆工程。它们相关但不同,以不同的方式失败,并且需要不同的系统才能正确处理。

本文涵盖了每个学科背后的核心决策以及它们的交互点:

  • 上下文工程涉及什么,以及决定 agent 在单次调用中能否良好推理的具体决策。
  • 记忆工程涉及什么,以及写入策略、存储、检索和维护分别如何影响长期可靠性。
  • 这两个学科如何在检索时共享边界,以及如何管理好这个边界。

分别地、综合地理解两者,是决定 agent 能否在实际工作负载中保持稳定表现的关键。

上下文工程与记忆工程概述

上下文工程 涵盖单次推理调用的设计:包含什么、压缩什么、把内容放在哪里、丢弃什么。范围内的所有内容都是临时的。当调用结束时,窗口被清空。

记忆工程 关注在单次与模型的交互之外存续的内容。它涵盖了负责写入、存储、检索、更新和管理信息的系统和策略,以便未来的交互能够利用这些信息。当一个 agent 从之前的会话中回忆信息、与另一个 agent 协调,或应用几天或几周前学到的用户偏好时,它依赖的就是记忆工程。

上下文工程决定模型在特定请求期间可获得哪些信息,而记忆工程决定哪些信息在多次请求之间持久化,以及这些信息如何随时间被维护、检索和信任。以下是一个概述:

维度 上下文工程 记忆工程
范围 单次推理调用 跨调用、会话、agents
数据存放位置 模型的活跃窗口内 外部存储:向量数据库、K/V、关系型
核心问题 包含什么以及如何组织 持久化什么、检索什么、信任什么
失败时机 窗口填满、位置错误、噪声淹没信号 检索遗漏、数据过时、投毒、没有写入策略
工程面 Prompt 结构、压缩、Token 预算 存储模式、检索策略、写入和更新策略
数据生命周期 一次 LLM 调用的时长 取决于记忆类型

上下文工程:组装最优上下文窗口

对于运行多步骤工作流的 agent,每次推理调用都会从多个来源组装一个上下文窗口:系统 prompt、任务描述、对话历史、工具输出、检索到的文档、子 agent 摘要。上下文工程是一组决策,决定每个组件贡献什么、以什么形式、在什么位置贡献。

选择性包含

并非所有可用的内容都应该进入上下文。一个返回数百行的数据库查询、一个返回五篇完整文章的网络搜索、一个记录冗长输出的代码执行器 所有这些都会使窗口膨胀,并在达到 Token 限制之前降低推理质量。决定什么逐字包含、什么压缩为关键事实、什么丢弃,是一个设计选择,而非默认行为。

结构放置

信息在窗口中的位置会影响模型使用它的可靠性。模型对长上下文开头和结尾的内容关注更强,而中间的材料获得的权重显著更低。这就是所谓的 "lost in the middle" 效应。

硬约束和任务关键指令应放在窗口顶部。与当前任务最相关的检索信息应放在上下文窗口末尾附近。

当前用户查询或任务通常应跟在检索信息之后,将相关上下文和当前目标尽可能靠近生成点放置。这种安排增加了模型在生成响应时有效使用检索信息的可能性。

图像

到达即压缩

工具输出应在调用返回后立即压缩,而不是等到窗口填满。一个包含 3,000 个 Token 的原始 API 响应,其中 agent 只需要 150 个,应该在进入下一步骤的上下文之前进行摘要。等到窗口满了再匆忙截断,是对一个可以在源头通过压缩预防的问题的被动管理。

对话历史管理

对话历史的增长速度超过任何其他上下文组件。对于长时间运行的 agent,每次调用都携带完整历史会使后续每次推理更昂贵且更不可靠。压缩策略 滚动窗口、分层摘要或结构化状态提取 应在定义的间隔应用,而不是在窗口溢出时。

记忆工程:设计持久化 AI 记忆系统

一旦推理调用完成,记忆工程决定什么值得持久化以及在什么条件下再次使用。这涵盖四个不同的问题:写入什么、存储在哪里、如何检索,以及如何随时间保持准确。

写入策略设计

写入策略设计是记忆工程中最容易被忽视的方面之一,但它对长期记忆质量有着不成比例的巨大影响。虽然检索系统通常获得最多关注,但检索质量最终受限于最初进入记忆存储的内容。

一个定义良好的写入策略规定了:

  • 哪些事件触发写入记忆。
  • 哪些信息有资格被存储。
  • 信息存储的格式,例如原始文本、结构化记录、提取的事实或摘要。
  • 接受新条目的置信度或验证要求。
  • 哪些 agents、工具或系统组件被允许写入特定的记忆命名空间。
  • 如何处理更新、更正和冲突信息。
  • 针对不同记忆类型的保留规则、过期策略和生存时间(TTL)要求。

没有明确的写入策略,系统往往会默认存储过多信息、对所有条目赋予相同的信任度,并无限期保留数据。随着时间的推移,低价值和过时的记忆不断累积,信噪比下降,检索质量退化。结果是记忆系统持续增长,却变得越来越没用。

存储层选择

不同的记忆类型服务于不同的目的,需要不同的存储后端。后端的选择也限制了可用的检索策略。

记忆类型 存储内容 存储后端 检索方法
工作记忆 活跃任务状态、中间结果 内存或短生命周期 K/V(Redis) 直接键查找
情景记忆 过去的交互、任务运行、决策 向量存储(Pinecone、Weaviate、Chroma) 语义相似度搜索
语义记忆 持久化事实、用户偏好、领域知识 向量存储 + K/V 混合 语义搜索或精确键查找
程序性记忆 学习到的工作流程、成功的行动模式 结构化存储或 prompt 注入 模式匹配、直接检索

OpenAI 的上下文个性化 cookbook 对于需要连续性的用例,在基于检索的记忆和基于状态的记忆之间做了一个有用的区分。基于检索的记忆将过去的交互视为松散相关的文档,对措辞变化和冲突更新很脆弱。结构化状态提取 写入类型化、经过验证的事实,而不是嵌入原始对话 对于需要在多个会话中可靠应用的事实,能产生更一致的结果。

图像

检索策略

从记忆读取不是一个单一操作。

设计良好的检索层首先检查工作记忆(快速、廉价、精确键查找) 当没有相关内容出现时,回退到情景记忆或语义记忆中的语义搜索 在返回结果前应用元数据过滤器来筛选新近度和信任级别 并且只注入当前步骤需要的内容。

记忆维护

没有维护策略的存储会随时间退化。条目不断累积,过时的事实与当前事实竞争,随着信噪比下降,检索质量也随之下降。以下维护例程在实践中很重要:对易变事实的置信度衰减、语义相似条目的去重、基于 TTL 的工作记忆和时效性数据过期,以及将旧的情景记录定期压缩为会话级摘要。

一个直接编码这些关注点的 MemoryEntry 模式使写入和维护逻辑更容易推理:

class MemoryEntry(BaseModel):
    content: str
    memory_type: str           # 工作 | 情景 | 语义 | 程序性
    importance: float          # 0.0–1.0,控制是否进入长期存储
    confidence: float          # 对易变事实随时间衰减
    trust_level: float         # 1.0 内部系统,0.5 用户输入,0.0 外部
    created_at: datetime
    expires_at: datetime | None
    provenance: dict           # agent_id, tool_name, session_id, input_hash

def should_write_to_long_term(entry: MemoryEntry) -> bool:
    return (
        entry.importance >= 0.6
        and entry.confidence >= 0.7
        and entry.trust_level >= 0.5
    )

检索边界:连接记忆与上下文工程

记忆工程和上下文工程通常被当作独立的学科来讨论,但在实践中它们密切相关。两者都是为了解决同一个核心问题:确保模型在正确的时间获得正确的信息。

从高层来看:

  • 记忆工程专注于持久化:哪些信息应该随时间被存储、更新、保留或遗忘。
  • 上下文工程专注于利用:对于特定任务,哪些信息应进入活跃上下文窗口,以及如何组织这些信息。

检索是这两个学科交汇的边界。

记忆系统产生候选信息。然后上下文组装决定:

  • 该信息是否应进入 prompt。
  • 应包含多少。
  • 它应放在上下文窗口中的什么位置。

管理好这个边界,是将记忆组件集合转化为一个连贯的 agent 系统的关键。

失败模式 #1:没有上下文预算的检索

最常见的失败之一是检索被独立于上下文组装来处理。

记忆搜索返回一组相关条目,上下文组装器将它们全部注入 prompt。随着更多记忆被添加,上下文窗口逐渐被检索内容填满,留给指令、工具输出、推理轨迹和任务特定信息的空间越来越少。

由此产生的症状往往具有误导性:

  • 检索质量看起来很高。
  • 相关记忆被成功找到。
  • 系统性能仍然下降。

在许多情况下,记忆系统正确完成了它的工作。失败是因为上下文组装缺乏预算机制。

更好的方法是感知检索的上下文组装。不是在检索之后再做预算,而是上下文层在检索开始前分配 Token 预算。然后检索层只返回符合该预算的最高价值记忆。

async def retrieve_for_step(
   self,
   step: AgentStep,
   max_tokens: int
) -> str:
   candidates = await self.memory.search(
       query=step.retrieval_query,
       max_results=10,
       filters={
           "trust_level": {"gte": 0.5},
           "expires_at": {"gt": datetime.now()}
       }
   )

   selected = []
   used = 0

   for entry in sorted(
       candidates,
       key=lambda e: e.relevance_score,
       reverse=True
   ):
       cost = self.token_count(entry.content)

       if used + cost > max_tokens:
           break

       selected.append(entry.content)
       used += cost

   return "\n\n".join(selected)

检索必须在上下文约束内运行,而不是假设下游有无限空间。

失败模式 #2:检索信息放置不当

仅凭检索质量是不够的。即使是高度相关的记忆,如果在上下文窗口内放置不正确,也可能失败。

一个常见问题是把检索纯粹当作搜索问题来处理,而忽略放置。检索到的记忆被随意追加到任何位置,而不考虑它们在当前推理步骤中的作用。

这在长上下文中影响更大。注意力在 prompt 中并非均匀分布。放在长上下文深处的信息,其影响力可能显著低于放在开头或结尾附近的信息。这导致一种微妙的失败模式:

  • 正确的信息被检索到。
  • 信息被插入上下文。
  • 模型表现得好像信息不存在。

检索成功了,但放置失败了。因此,上下文组装应该同时优化两者:

  • 选择:什么进入上下文窗口。
  • 放置:它在上下文窗口中的什么位置出现。

必须影响当前步骤的检索信息应放在活跃推理区域附近,而不是随意追加。

总结

上下文工程和记忆工程是同一系统的两层,该系统控制模型知道什么、何时知道,以及如何使用这些知识。

上下文工程在推理时运行,塑造活跃信息窗口。记忆工程跨越时间运行,塑造哪些信息持久化以及以后如何检索它们。

维度 上下文工程 记忆工程
核心问题 模型现在应该看到什么,以及如何看到? 系统应该保留什么,保留多久?
主要产物 每次推理调用组装的上下文窗口 跨调用和会话持久化的记忆条目
Token 管理 每个窗口组件的预算分配 每种条目类型的存储成本;每次查询的检索成本
压缩 工具输出在注入前摘要;历史滚动或提取 旧的情景记录被压缩;过时事实衰减或被剪除
新鲜度 滚动历史窗口;过时的轮次被丢弃 易变事实的 TTL;置信度随时间衰减
信任 来源层级决定组装顺序 每个条目追踪来源;低信任内容在写入前被净化
多 agent 每个 agent 独立组装自己的窗口 每个 agent 有作用域命名空间;跨 agent 事实用共享命名空间
失败模式 溢出、注意力退化、噪声组装 投毒、过时、检索遗漏、无界增长
维护 在定义的间隔主动压缩 TTL 过期、去重、置信度衰减、情景归档
交汇点 检索到的记忆进入上下文:预算和放置决定如何进入 上下文组装在 Token 预算约束内请求检索

总而言之,一个 agentic 系统只有在两层对齐时才能正常工作:记忆决定什么可用,上下文决定什么可执行。

  • 原文链接: x.com/beamnxw/status/208...
  • 鸿途知科网 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
版权声明

本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门