AI Agent 的长期记忆与 RAG:让智能体在长期任务中保持准确与一致

本文承接任务规划与多工具编排,系统讲解 AI Agent 的长期记忆与检索增强生成(RAG)实践:哪些信息应该留在对话上下文里,哪些应该持久化到外部存储,以及如何通过检索让 Agent 在长期任务中保持准确、一致和低成本。

本文承接任务规划与多工具编排,系统讲解 AI Agent 的长期记忆与检索增强生成(RAG)实践:哪些信息应该留在对话上下文里,哪些应该持久化到外部存储,以及如何通过检索让 Agent 在长期任务中保持准确、一致和低成本。

目录

  • 一、上下文窗口是 Agent 的第一道墙

  • 二、记忆分层:短期、工作与长期

  • 三、长期记忆的写入:记住什么、怎么更新

  • 四、RAG:让 Agent 按需召回知识

  • 五、上下文组装:把记忆与检索织进提示词

  • 六、时效、一致性与成本控制

  • 七、隐私与安全边界

  • 八、上线前检查清单

  • 结语

引言

在前三篇文章中,我们分别讨论了 AI Agent 的提示词传输、流式输出与异常处理,以及如何通过 Function Calling 让大模型安全调用业务系统,再把复杂目标拆解为可执行、可验证的多步工作流。完成这些之后,一个更隐蔽的问题浮出水面:

用户上周说过 “我更喜欢简洁的日报”,昨天让 Agent 生成过一份销售分析报告,今天又发起新的对话 ——Agent 还记得吗?

如果每次对话都从零开始,Agent 会反复询问已经告诉过它的信息;如果把所有历史都塞进上下文,模型很快会触达上下文窗口上限,成本也随之失控。长期记忆与检索增强生成(RAG)解决的,正是 “记住什么、忘掉什么、按需想起什么” 这三个问题。

本文将从工程实践出发,梳理记忆的分层设计、持久化方案与检索召回策略,并结合代码说明如何让 Agent 在长期任务中保持准确、一致和低成本。

一、上下文窗口是 Agent 的第一道墙

1.1 为什么不能把一切都塞进上下文

大模型拥有上下文窗口,但窗口不是无限大的;即使窗口足够大,也不意味着应该全部用满。原因有三:

  • 成本:输入 Token 费用与上下文长度成正比,长上下文直接推高每次调用的成本;

  • 干扰:大量无关信息会稀释模型对关键信息的注意力。研究观察到 “lost in the middle” 现象:模型对长文本中部内容的利用明显弱于开头和结尾;

  • 时效:历史记录中的旧结论可能已被推翻,保留过期信息反而会导致错误。

因此,Agent 必须把 “对话上下文” 和 “长期记忆” 分开对待。

1.2 什么该进上下文,什么该持久化

维度 对话上下文 长期记忆
容量 受上下文窗口限制 几乎无限(外部存储)
生命周期 当前会话 跨会话、跨任务
访问方式 全量进入模型 按需检索召回
成本 随 Token 线性增长 检索时按需付费
一致性 天然一致 需要处理过期与冲突

一个实用的分配原则是:

  • 留在上下文中:系统提示词、当前任务目标、最近几轮对话、本轮用户输入、工具执行结果;

  • 持久化到长期记忆:用户偏好、长期事实、历史任务的结论、跨会话反复需要的信息;

  • 交给 RAG 检索:领域知识库、产品手册、历史文档、FAQ 等静态或半静态资料。

一句话总结:上下文放 “正在进行的事”,长期记忆放 “反复需要的事”,RAG 检索放 “需要时才知道的事”。

二、记忆分层:短期、工作与长期

工程上可以把 Agent 的记忆分为三个层级:

记忆层级 生命周期 存储位置 更新方式 典型用途
短期记忆 单次会话 对话上下文 每次交互追加、截断或压缩 理解当前对话脉络
工作记忆 单次任务 任务表、步骤表 步骤执行时更新 记录任务进度与中间结果
长期记忆 跨会话、跨任务 向量库、KV、关系库 事后总结、显式写入 用户偏好、领域知识、历史结论

2.1 短期记忆:会话内的滚动窗口

短期记忆就是第一篇文章讨论过的对话上下文。会话变长后,可以采用截断、摘要或两者的组合:

  • 截断:只保留最近 N 轮消息;

  • 摘要:把较早的对话压缩为一段要点,替换掉原文;

  • 滚动窗口 + 摘要:最近几轮保留原文,更早的合并成摘要 —— 这是当前最主流的方案。

2.2 工作记忆:任务执行中的状态

工作记忆在上一篇 “任务规划与多工具编排” 中已经出现:任务表、步骤表、确认记录、调用日志。它不依赖模型上下文,而是持久化在数据库里,让长任务可以在服务重启后恢复。

2.3 长期记忆:跨会话的知识沉淀

长期记忆是本文的重点。它的常见形态包括:

  • 键值记忆:适合用户偏好这类 “一个键对应一个值” 的信息,例如 “报告语言 = 中文”;

  • 结构化记忆:适合属性明确的实体,例如客户、项目的字段化信息;

  • 语义记忆(向量):适合无法用键精确描述的开放信息,例如 “用户更关注华东区业务” 这类需要语义匹配的内容。

三类存储并非互斥。实践中常以 KV 或关系库保存确定性信息,以向量库保存语义化信息,再统一通过一个 “记忆服务” 对外暴露读写接口。

三、长期记忆的写入:记住什么、怎么更新

3.1 记忆从哪里来

长期记忆不是把每句对话都存下来,而是从对话中提取可复用的信息。常见来源有三类:

  • 用户显式声明:”以后都用中文写报告”—— 直接、可信,优先级最高;

  • 模型隐式推断:从用户行为中推断偏好,例如用户连续三次要求压缩篇幅;

  • 任务事后总结:任务结束时把结论、产出和关键参数写入记忆,供后续任务复用。

提取动作可以由单独的模型调用完成,也可以在任务结束时统一执行。下面是一次提取结果的示例:

{
  "extracted": [
    {
      "type": "preference",
      "key": "report_language",
      "content": "用户偏好使用中文撰写报告",
      "importance": 0.8
    },
    {
      "type": "fact",
      "key": "customer_a_domain",
      "content": "客户 A 为制造业客户,主要使用 ERP 系统",
      "importance": 0.6
    },
    {
      "type": "task_result",
      "key": "sales_analysis_2026_08",
      "content": "8 月销售下降主要因华东区大客户流失",
      "importance": 0.7
    }
  ]
}

3.2 写入:新增、覆盖与失效

记忆更新只有三种操作,关键是选对操作:

  • 新增:记忆库中不存在该信息时写入;

  • 覆盖:同一键出现新值,且新值来自更高优先级来源(用户显式纠正 > 模型推断 > 旧记录)时更新;

  • 失效:信息确认过期(如订单已关闭、客户已流失)时标记删除,而不是让旧值和新值同时存在。

3.3 重要性评分与淘汰策略

存储空间和检索质量都要求记忆库 “精而不滥”。一个简单的记忆服务可以维护重要性、访问时间和有效期:

import time
from dataclasses import dataclass
@dataclass
class Memory:
    key: str
    content: str
    importance: float          # 0-1,越高越不容易被淘汰
    source: str                # user / assistant / tool / summary
    created_at: float
    updated_at: float
    last_access_at: float
    ttl: int | None = None     # 秒;None 表示长期有效
    def expired(self, now: float) -> bool:
        return self.ttl is not None and now - self.updated_at > self.ttl
class MemoryStore:
    def __init__(self, max_items: int = 200):
        self._items: dict[str, Memory] = {}
        self._max_items = max_items
    def remember(self, key, content, importance,
                 source="user", ttl=None):
        now = time.time()
        existing = self._items.get(key)
        if existing:
            existing.content = content
            existing.importance = max(existing.importance, importance)
            existing.updated_at = now
            existing.ttl = ttl
        else:
            self._items[key] = Memory(
                key=key, content=content, importance=importance,
                source=source, created_at=now, updated_at=now,
                last_access_at=now, ttl=ttl,
            )
        self._evict_if_needed()
    def recall(self, key):
        item = self._items.get(key)
        if item is None or item.expired(time.time()):
            return None
        item.last_access_at = time.time()
        return item.content
    def _evict_if_needed(self):
        if len(self._items) <= self._max_items:
            return
        now = time.time()
        self._items = {k: v for k, v in self._items.items()
                       if not v.expired(now)}
        while len(self._items) > self._max_items:
            key = min(self._items,
                      key=lambda k: (self._items[k].importance,
                                     self._items[k].last_access_at))
            del self._items[key]

上面代码的核心思想只有两点:新信息覆盖旧信息,来源可信度更高时可以提升重要性;容量不足时,优先淘汰低重要性、久未访问的条目。 生产环境建议把这段逻辑替换为 Redis + 向量库,并加上多租户隔离与审计。

四、RAG:让 Agent 按需召回知识

RAG(Retrieval-Augmented Generation,检索增强生成)解决的是 “知识不在对话里、也不在记忆里,但在某个资料库里” 的问题。它让模型在生成前先从外部知识源检索相关片段,再基于这些片段作答。

4.1 RAG 的基本流程

  1. 切分(Chunking):把长文档切成适合检索的片段;

  2. 向量化(Embedding):把每个片段编码成向量;

  3. 索引(Indexing):建立向量索引,支持相似度检索;

  4. 召回(Retrieval):把用户问题编码成向量,检索最相似的片段;

  5. 重排(Rerank):对召回结果做精细排序,剔除无关内容;

  6. 组装(Assembly):把精选片段与对话上下文一起交给模型。

4.2 切分不是简单按字数切

切分质量直接影响检索效果。常见做法包括:

  • 固定长度 + 重叠:按固定 Token 数切分,相邻片段保留一定重叠,避免语义在切点被截断;

  • 语义切分:按段落、标题或语义完整性切分,适合结构化的手册与文档;

  • 父子片段:检索小片段定位位置,生成时把包含它的更大段落一并给出,兼顾精度与上下文。

4.3 向量不是万能的:混合检索

纯向量检索对语义相近的表述很有效,但对精确匹配(订单号、型号、法规条文)反而不如关键词检索。生产系统通常采用混合检索

  • 向量召回负责 “语义相似”;

  • 关键词检索(如 BM25)负责 “精确命中”;

  • 两者结果合并去重后,再交给重排模型排序。

def build_context(question, user_id, recent_messages, top_k=5):
    # 1. 长期记忆:用户画像等确定性信息
    profile = memory_service.get_profile(user_id)
    # 2. 混合检索:向量召回 + 关键词召回 + 重排
    vector_hits = vector_store.search(question, top_k=top_k \* 2)
    keyword_hits = bm25_index.search(question, top_k=top_k \* 2)
    merged = deduplicate(vector_hits + keyword_hits)
    reranked = reranker.rerank(question, merged)[:top_k]
    # 3. 按 Token 预算组装上下文
    return {
        "system": SYSTEM_PROMPT,
        "profile": profile,
        "knowledge": format_snippets(reranked),
        "history": recent_messages[-6:],
        "question": question,
    }

4.4 什么时候该检索

检索不是每轮都必须发生。可以按规则触发(问题包含 “是什么、怎么用、最新、对比” 等信号),也可以像工具调用一样,把 “是否检索、检索什么” 交给模型决策。后者更灵活,但要在检索工具中绑定权限与数据范围,避免模型检索到无权访问的内容。

五、上下文组装:把记忆与检索织进提示词

检索到内容之后,如何摆放也影响效果。建议按照以下顺序与预算组装上下文:

区块 内容 建议预算
系统提示词 人设、规则、能力边界 固定
长期记忆 用户画像、关键偏好 5% – 10%
检索片段 RAG 召回的知识 30% – 40%
最近对话 近几轮历史 20% – 30%
当前输入 本轮用户意图 必须保留

5.1 检索、记忆与工具调用如何分工

当 Agent 同时具备记忆、RAG 和 Function Calling 时,需要明确三者各管一段:

能力 解决什么问题 典型数据 时效
长期记忆 个性化的、反复需要的信息 用户偏好、历史结论 跨会话
RAG 静态、海量的知识资料 手册、FAQ、历史文档 资料更新时刷新
工具调用 实时、确定性的业务数据 天气、订单、库存 实时

判断顺序可以是:先查记忆(用户相关)→ 再查知识(RAG)→ 必要时调用工具(实时数据)。例如用户问 “我上个月的销售报告结论是什么”,答案在记忆中;问 “公司退货政策是什么”,答案在 RAG 中;问 “现在订单 10086 到哪了”,答案必须通过工具实时获取。

5.2 检索结果也要做 “质量门”

召回片段不应原样塞进上下文。建议:

  • 过滤与问题相似度过低的片段;

  • 对片段做去重与去噪音(广告、导航、页脚);

  • 标注来源,让模型在引用时给出出处;

  • 若召回内容自相矛盾,优先采纳更新、更权威的来源,并如实说明。

六、时效、一致性与成本控制

6.1 记忆会过期

偏好可能改变,事实可能过时。长期记忆需要三类失效机制:

  • TTL(生存时间):为临时性信息设置有效期,到期自动失效;

  • 事件驱动失效:业务状态变更时主动删除或覆写相关记忆,例如订单关闭后清除订单相关缓存;

  • 用户显式修正:用户纠正 Agent 时,立即覆盖旧记忆并提高该条记忆的优先级。

6.2 一致性与溯源

记忆与资料可能互相冲突。缓解手段包括:

  • 每条记忆与检索片段都记录来源与更新时间;

  • 生成时要求模型在依据不足时明确说 “我不确定”,而不是编造;

  • 对 “事实类” 回答开启引用溯源,用户可点击查看依据。

6.3 让成本可控

长期记忆与 RAG 的目标之一就是降本:

  • 缓存:相同问题的检索结果与模型回答按用户维度缓存;

  • 分层召回:先在记忆与高频知识里查,查不到再检索全量知识库;

  • 控制检索量:只召回必要数量的片段,而不是越多越好 —— 片段太多反而稀释注意力;

  • 摘要压缩:长期任务中定期把已完成部分压缩为摘要,释放上下文预算。

6.4 可观测性

和任务编排一样,记忆与检索也需要留痕:检索了什么、召回了哪些片段、使用了哪些记忆、各自耗时多少。统一的 memory_idchunk_idcall_id 贯穿全链路,才能定位 “为什么答错”。

七、隐私与安全边界

长期记忆跨会话保留用户信息,安全边界比单次对话更严格:

  • 最小化存储:不存储明文密码、密钥、身份证号、完整支付信息;确需使用时临时获取;

  • 多租户隔离:记忆与知识库按用户 / 租户分区,检索时强制注入数据范围条件,不能跨租户召回;

  • 权限绑定:检索和写入都走服务端鉴权,模型生成的 “我要看某人的记忆” 不是授权;

  • 用户权利:向用户提供查看、导出、删除个人记忆的入口,删除操作同步清理向量库副本;

  • 脱敏与审计:记录记忆的写入来源、操作者与时间,敏感内容入库前脱敏。

八、上线前检查清单

  • 是否明确了 “进上下文 / 进长期记忆 / 走 RAG 检索” 的边界?

  • 短期记忆是否具备滚动窗口与摘要压缩能力?

  • 长期记忆是否有提取、新增、覆盖、失效的完整生命周期?

  • 记忆更新是否遵循 “用户显式纠正优先” 的冲突消解规则?

  • 是否设置了重要性评分与容量上限,避免记忆库无限膨胀?

  • RAG 是否使用混合检索(向量 + 关键词)与重排,而非仅向量召回?

  • 检索是否触发于明确信号,且绑定权限与数据范围?

  • 上下文组装是否有固定的顺序与 Token 预算?

  • 记忆与资料是否记录来源与时间,支持过期、失效与溯源?

  • 是否实现多租户隔离、敏感信息脱敏与用户删除入口?

  • 是否用真实长对话与知识变更场景评估准确率、一致性与成本?

结语

上下文窗口是 Agent 的第一道墙,但墙外不是一片空白 —— 长期记忆负责 “记住反复需要的信息”,RAG 负责 “按需想起知识库里的信息”,工具调用负责 “获取实时确定的信息”。三者协同,才能让 Agent 在长期任务中既准确、又一致、还便宜。

与任务编排同理,模型负责判断 “该想起什么”,确定性代码负责 “记住什么、检索什么、谁能看”。把记忆写入、失效、权限与审计固化在应用层,Agent 才能安全地越用越懂用户。

下一篇可以继续讨论多 Agent 协作:当一个任务大到单智能体难以胜任时,如何把目标分发给多个各司其职的智能体,以及它们之间如何通信、避免冲突并汇总出统一结果。

本文来自投稿,不代表知派立场,如若转载,请注明出处:https://www.zinpai.com/news/4625.html

(1)
Kevin的头像Kevin
上一篇 2026年9月7日 下午3:41
下一篇 2026年9月8日 下午4:43

相关推荐

  • 星巴克、耐克成功背后的秘密:如何用“微观市场”洞察打造爆款产品?

    为什么星巴克能颠覆传统的咖啡消费方式?为什么耐克能从一款跑鞋成长为全球运动品牌巨头?答案藏在对“微观市场”的深刻洞察中

    行业动态 2025年12月8日
    43900
  • 离岸人民币稳定币,已从“不可能”变为“不排除”

    【引言】 在美元稳定币席卷全球支付场景之际,一个关键问题浮出水面:人民币能否搭乘这趟快车?华泰证券的报告《再问稳定币》将目光投向了东方,深入探讨了港币及离岸人民币稳定币的可能性与挑战。当香港立法为稳定币敞开大门,当数字人民币跨境试点稳步推进,一条基于区块链技术、助力人民币国际化的“加密新航道”似乎正在浮现。本文将解析,离岸人民币稳定币距离现实还有几步之遥。 …

    2025年12月17日
    46000
  • 利润承压,增长点在哪?2025跨境电商卖家生存现状深度解析

    【引言】 2025年,跨境电商行业在“大融合”中快速发展,但卖家们的真实感受却是“冰火两重天”。一方面,新兴平台和渠道带来了新的增长机遇;另一方面,近半数卖家利润下滑,行业“内卷”加剧。本文将基于雨果跨境的调研数据,深入剖析卖家的经营现状,探寻在压力之下,真正的增长机会藏在哪里。 【核心分析:营收与利润的剪刀差】 报告数据显示,2025年跨境卖家的经营状况呈…

    2025年12月11日
    66100
  • 圈层经济崛起:新消费时代如何“入圈”与“破圈”?

    引言:你是否发现,如今的年轻人不再简单地被“年龄”或“收入”定义,而是因为共同的兴趣爱好聚合成一个个“圈层”?从JK制服到脱口秀,从露营到咖啡文化,圈层正成为品牌连接消费者的新密码。秒针营销科学院的《中国消费者兴趣圈层白皮书》揭示了一个核心趋势:传统的人口属性细分已失效,兴趣圈层正在重塑营销逻辑。 正文:1. 什么是圈层?圈层是因共同兴趣、爱好、价值观而聚集…

    2025年12月11日
    72000
  • 腾讯 2027 AI 产品经理培训生正式开招!

    腾讯 2027 AI 产品经理培训生正式开招!不限专业,没有传统笔试。8 月 13 日启动投递,9 月 4 日截止。
    这次开放的职位,都是腾讯一线的产品。混元 HY3 基础模型、WorkBuddy、ima、Marvis、腾讯云等方向都有机会进入,具体以最终岗位安排为准。

    2026年8月22日
    36000

发表回复

登录后才能评论

联系我们

邮件:service@zinpai.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信