主题
混合记忆架构设计
1. 从一个常见的翻车场景开始
你写资料 Agent 时,有没有遇到过这种情况:用户问了一个技术细节,Agent 洋洋洒洒回了一大段,但仔细一看,引用的官方文档是两年前的版本,提到的 API 名字虽然语义相近,却不是真实存在的参数名;好不容易找到的一段论文出处,其实是某篇博客的二手转述。
问题不一定出在模型本身。更常见的是:进入上下文的资料,没有经过充分筛选。
在讨论资料检索之前,值得先退一步看 Agent 记忆常被拆成的三层:当前会话里的工作记忆、跨会话的情节记忆,以及面向知识库检索的语义记忆。生产级 Agent 如果只做好第一层,很快会在长对话和跨会话场景中丢上下文;语义记忆又最容易因为只依赖向量相似度而召回过期或不可引用的材料。所以混合记忆架构的关键,是让这三层各司其职,而不是把所有负担都压到向量检索上。
2. 先画一张整体地图
Agent 混合记忆架构的核心问题:当系统面对一堆来源不同、时间不同、可信度不同的资料时,怎么把它变成“可信、可追溯、可交给不同 Agent 使用”的上下文?
可以分成三个层次:
| 层次 | 解决什么问题 | 像什么 |
|---|---|---|
| 工作记忆 | 当前任务的状态和临时信息 | 桌面上的文件 |
| 长期知识库 | 跨任务复用的资料和规则 | 书架上的藏书 |
| 语义检索层 | 从藏书里找到和当前任务相关的片段 | 图书目录 + 检索系统 |
这篇文章主要聚焦在长期知识库和语义检索层:资料怎么入库、怎么检索、怎么筛选、怎么交给不同 Agent。
3. 把记忆当成资料系统来设计
我们前面聊过向量化与语义检索。那套流程能解决一个核心问题:当用户抛出一个目标,系统可以从知识库里召回语义相近的片段。
但在 Agent 项目里,这只能算资料检索的一部分。Agent 真正面对的,是一批来源不同、时间不同、版本不同、可信度也不同的材料:
| 资料类型 | 示例 | 使用时关心的问题 |
|---|---|---|
| 产品文档 | API reference、配置说明、迁移指南 | 当前版本是否仍然有效 |
| 技术文章 | 架构说明、工程复盘、设计草案 | 观点是否有证据支撑 |
| 需求资料 | PRD、用户反馈、访谈纪要 | 结论是否对应真实场景 |
| 项目记录 | Issue、PR、CHANGELOG、发布说明 | 变更发生在哪个版本 |
| 外部资料 | 论文、官方文档、权威项目文档 | 来源是否能被引用 |
| 历史产物 | 旧产物、结构、审稿意见 | 哪些内容已经用过 |
如果只把这些资料切块、向量化、塞进向量库,系统很快会遇到几个麻烦:
- 专有名词和精确片段容易漏掉。资料 Agent 要找
Vectorize的 metadata filter、FTS5、Reciprocal Rank Fusion时,关键词本身比语义相似度更可靠。 - 版本和时间会改变结论。同一个框架在不同版本的 API 可能不同,旧产物里的经验可能已经不适用于当前项目。
- 来源可信度不能只靠相似度判断。论文、官方文档、社区博客、内部草稿都可能语义相关,但审稿时的权重不同。
- 上下文窗口装的是筛选后的资料对象。把语义相近的 Top-K 片段直接交给执行 Agent,常常会带来重复、过期、不可引用或缺少出处的材料。
所以混合记忆架构要做的,不是让资料"看起来相关",而是让资料进入 Agent 上下文之前,先经过一套可解释的检索和筛选流程。
4. 向量检索不能包打天下
向量检索擅长找"意思接近"的材料。它适合这样的请求:
- 「找一下 RAG 里关于外部知识库的资料」
- 「补充几段关于 hybrid search 的背景」
- 「看看有没有和审稿上下文可信度相关的文章」
但 Agent 任务常常提出更具体的约束:
| 任务请求 | 只用向量检索的风险 | 需要补充的能力 |
|---|---|---|
| 「只引用 2026 年仍然有效的官方文档」 | 召回旧版本说明,模型难以自行判断是否过期 | 时间/版本过滤 |
| 「找 Cloudflare D1 是否支持全文检索」 | 召回语义相近的数据库文章,但漏掉 FTS5 关键词 | 关键词检索 + 结构化来源筛选 |
| 「这段话有没有一手资料支撑」 | 召回观点相近的二手文章,不能证明出处可靠 | 来源可信度排序 |
| 「对比向量检索和关键词检索的边界」 | 只返回语义描述,缺少能核验的术语和机制 | 关键词检索 + rerank |
| 「审稿时检查引用是否对应正文」 | 只知道片段相关,不知道哪句话来自哪个来源 | 引用追踪 |
RAG 主要回答"知识从哪里来"的问题。但 Agent 系统还要继续回答:哪些资料可以进入上下文、哪些可以作为引用、哪些只能当作启发。
这种感受也反映在公开基准里。CRAG(Comprehensive RAG Benchmark)在 4,409 条跨领域事实问答上的评测显示:纯 LLM 只有约 34% 的准确率,朴素 RAG 能提升到约 44%,而引入 hybrid retrieval、rerank、query rewriting 等优化后的 SOTA 系统也才达到约 63%。这说明即便加了检索,仍然有近四成问题不能仅靠向量相似度解决。来源可信度、版本过滤和关键词命中,正是补上这部分缺口的方向。
这就是混合检索要补上的部分:向量检索负责扩大语义候选集;关键词检索负责保住精确术语;结构化查询负责版本、时间、作者、来源类型这些确定性条件;rerank 和引用追踪负责把候选材料整理成 Agent 能用的上下文。
5. 资料层怎么划分
资料系统不应该只按"数据量"选存储方式,更应该按访问模式划分。Agent 项目可以先拆成三层:
| 层级 | 存放内容 | 主要查询方式 | 主要使用者 |
|---|---|---|---|
| 语义片段层 | 文档 chunk、段落摘要、标题上下文 | 向量检索 | 资料 Agent、执行 Agent |
| 全文索引层 | 原文片段、标题、术语、代码标识符 | 关键词检索、BM25/FTS | 资料 Agent、审稿 Agent |
| 元数据层 | 来源、作者、时间、版本、可信度、引用 ID | SQL/结构化查询 | 资料 Agent、审稿 Agent、引用检查器 |
这三层可以落在不同基础设施上,也可以由同一个搜索系统承载。以 Cloudflare 体系为例,Vectorize 更适合语义向量检索,D1 可以保存元数据并借助 SQLite FTS5 做全文检索,AI Search 这类托管搜索能力则把索引、metadata filter 和 hybrid search 进一步封装起来。
切分策略会直接影响检索质量。知识库 chunk 通常从 300–800 tokens 起步,太小的 chunk 检索精度高但上下文不足,太大的 chunk 又容易淹没关键术语。无论 chunk 多大,写入时都要同时保留标题层级、段落边界和来源 URL,否则后面的引用追踪会很难做。
关键点落在索引设计上:
| 字段 | 用途 |
|---|---|
doc_id | 标识同一篇资料,供去重和引用聚合使用 |
chunk_id | 标识具体片段,供上下文拼装和引用定位使用 |
source_type | 区分论文、官方文档、项目文档、博客、内部草稿 |
source_url | 保存可追溯出处 |
published_at / updated_at | 支持时间过滤和时效性排序 |
product_version / api_version | 支持版本过滤 |
authority_score | 表示来源可信度,例如官方文档高于转述文章 |
license / quote_policy | 约束是否可引用、可摘录、可改写 |
used_in | 记录某篇产物已经使用过哪些资料 |
一条资料进入系统时,通常要同时写入三类索引:向量索引用于语义召回,全文索引用于精确命中,元数据表用于过滤、排序和引用追踪。这是一种有意识的冗余。它增加了写入成本,但换来的是资料 Agent 和审稿 Agent 能从不同角度核验同一批材料。
6. 混合检索管线
任务发起后,如果检索直接变成一次 topK: 8 的向量查询,后续 Agent 会缺少判断来源、版本和引用边界的依据。更稳妥的做法是把管线拆成七步。
第一步:查询理解
资料 Agent 先把任务需求转成检索计划。计划里至少包含四类信息:
| 计划项 | 示例 |
|---|---|
| 主题意图 | RAG、hybrid search、Cloudflare Vectorize、FTS5 |
| 精确关键词 | metadata filtering、Reciprocal Rank Fusion、FTS5 |
| 结构化约束 | 只要官方文档/论文,排除社区转述 |
| 时间/版本约束 | 优先 2026 年仍有效的资料,或指定框架版本 |
这一步可以由 LLM 辅助,但不要把它当成最终判断。LLM 适合把自然语言需求拆成查询计划,具体过滤仍应落到搜索系统和数据库条件里。
第二步:多通道召回
同一个检索计划会同时触发多条通道:
| 通道 | 解决的问题 | 示例 |
|---|---|---|
| 向量检索 | 找到语义相关材料 | 召回 RAG、知识密集型任务、外部知识库相关论文 |
| 关键词检索 | 命中专有名词和代码标识符 | 命中 FTS5、metadata filter、hybrid=True |
| 结构化查询 | 过滤来源、版本、语言、作者 | 只保留官方文档、论文、项目内文档 |
| 时间/版本过滤 | 排除过期资料 | 排除旧 API、旧产品能力、旧实验结论 |
向量检索和关键词检索负责扩大候选集,结构化查询和时间/版本过滤负责缩小候选集。两类动作都需要保留,否则资料可能过散,也可能过早收窄。
第三步:来源可信度计算
Agent 系统需要区分「可引用资料」和「参考线索」。可以先用一组简单规则:
| 来源类型 | 默认处理 |
|---|---|
| 论文、标准、官方文档 | 可进入引用候选 |
| 项目源码、CHANGELOG、Issue、PR | 可作为项目事实依据 |
| 权威项目文档 | 可进入引用候选,但要记录版本 |
| 社区文章、论坛讨论 | 可作为线索,通常不直接作为强引用 |
| 未知来源、无时间资料 | 默认降权或排除 |
可信度用于让审稿 Agent 知道一段上下文的用法:可以支撑结论、只能提示方向,还是需要继续查证。
更进一步,CraniMem 的研究表明,给记忆增加"门控"(gating)和"边界"(boundedness)能显著降低干扰信息进入长期记忆的概率。它的核心思路是:进入记忆前先按目标相关性过滤,短期信息放在有容量上限的情节缓冲里,只有高价值痕迹才会被整合进知识图谱。这和我们把资料分成语义片段、全文索引和元数据三层,并对来源可信度做排序的做法,方向是一致的。
第四步:rerank
多通道召回会得到几组分数:向量相似度、关键词匹配分、结构化命中、时间新鲜度、来源可信度。它们不能直接相加,因为分数含义不同。
常见做法有两类:
- 用 Reciprocal Rank Fusion 这类融合方法,把不同检索结果按排名合并,减少对原始分数标定的依赖。Atlan 的 Advanced RAG 指南把 hybrid retrieval(向量 + 关键词 + RRF)列为当前生产系统的默认起点,因为它同时覆盖了语义扩展和精确术语命中。
- 用 reranker 对候选片段和任务重新打分,把「与当前部分是否相关」「能否回答具体问题」「是否能作为证据」纳入排序。
在 Agent 系统里,rerank 的目标是把最适合进入下一步执行或审稿的片段排在前面。
第五步:去重
同一篇资料可能同时被多个通道命中。比如一段官方文档既包含 metadata filtering 关键词,也和「按版本过滤向量检索」语义相关。去重至少要处理三类重复:
| 重复类型 | 处理方式 |
|---|---|
同一 chunk_id | 合并通道分数和命中原因 |
同一 doc_id 的相邻片段 | 合并成更完整的上下文块 |
| 不同来源转述同一事实 | 优先保留一手来源,二手来源作为线索 |
去重阶段需要处理文本重复,也需要保留「为什么被命中」:关键词命中了什么、语义通道给了多少分、结构化过滤为什么放行。审稿 Agent 后面会用到这些解释。
第六步:截断
截断阶段不能只取 Top-K。Agent 上下文需要平衡几类材料:
- 1-2 条定义或机制资料,帮助执行 Agent 讲清概念。
- 2-3 条项目相关资料,帮助产物贴住当前系统。
- 1-2 条反例或边界资料,帮助审稿 Agent 检查结论是否过满。
- 必要的引用元数据,帮助后续生成出处和核验引用。
如果只按相关性截断,容易得到一组彼此重复的资料;如果只按来源可信度截断,又可能缺少能解释工程取舍的上下文。截断阶段要保留多样性,也要保留可引用性。
第七步:引用追踪
进入 Agent 上下文的每个片段,都应该带上引用信息:
ts
type RetrievedContext = {
chunkId: string
docId: string
title: string
sourceUrl: string
sourceType: 'paper' | 'official-doc' | 'project-doc' | 'issue' | 'blog'
publishedAt?: string
updatedAt?: string
productVersion?: string
quotePolicy: 'cite' | 'paraphrase-only' | 'internal-only'
hitReasons: string[]
text: string
}执行 Agent 可以用 text 组织产物,审稿 Agent 则检查 sourceUrl、sourceType、updatedAt、quotePolicy 和 hitReasons。这样处理后,资料会以有来源、有边界、有使用规则的上下文对象进入 Agent 协作,而不是只作为一段可塞进 prompt 的文本。
7. 资料 Agent 和审稿 Agent 需要不同的上下文
同一套检索架构,在不同 Agent 面前应该输出不同形态。
资料 Agent 需要宽召回
资料 Agent 的目标是发现可用材料。它可以接受更宽的候选集,也可以保留一些「暂时不能引用但可能提示方向」的线索。它的上下文更像资料卡片:
| 字段 | 作用 |
|---|---|
| 资料摘要 | 快速判断是否继续阅读 |
| 命中原因 | 说明是关键词命中、语义命中还是结构化命中 |
| 来源等级 | 区分官方、论文、项目记录、社区材料 |
| 时间/版本 | 判断是否需要再查新资料 |
| 相关片段 | 给执行 Agent 后续使用 |
资料 Agent 更关心召回覆盖率。只要候选资料没有明显污染,就可以先保留,再交给后续 rerank、去重和审稿环节收窄。
在多 Agent 场景里,记忆还需要区分"共享"和"私有"。共享工作区记忆(shared workspace memory)定义为所有 Agent 都能读写的任务上下文,比如当前处理的数据或已确认的计划;而每个 Agent 的专属记忆只对它相关的任务开放。资料 Agent 和审稿 Agent 的上下文差异,正是这种设计在知识检索层面的体现。
审稿 Agent 需要窄上下文
审稿 Agent 的目标是判断产物是否可靠。它不需要看到所有资料,只需要看到和产物主张对应的证据:
| 审稿问题 | 所需上下文 |
|---|---|
| 这句话有没有出处 | 对应 chunk_id、source_url、引用位置 |
| 这个结论是否过期 | updated_at、product_version、变更记录 |
| 这是否属于二手转述 | source_type、来源链路 |
| 这里是否混用了概念 | 术语定义片段、相邻上下文 |
| 引用是否过长或不可用 | quote_policy、摘录长度、改写记录 |
审稿 Agent 的上下文应该更窄、更结构化,也更可追溯。它不需要猜某段材料从哪里来,也不应该只凭「看起来合理」通过一段技术判断。
8. 写入和更新:让资料持续可用
混合检索的质量不只取决于查询,也取决于资料写入方式。Agent 项目里的资料更新通常分为四步:
- 采集:接入官方文档、论文、项目文档、Issue、PR、CHANGELOG、历史产物。
- 解析:保留标题层级、段落边界、代码块、表格、更新时间、版本号和 URL。
- 索引:同一片段写入向量索引、全文索引和元数据表。
- 回收:发现过期资料后降权、归档或标记为旧版本,不让它继续支撑当前结论。
写入阶段最容易被忽略的是「保留原始边界」。如果切块时丢掉标题、版本和来源 URL,后面再做引用追踪会很困难;如果只保存向量,不保存原文和元数据,审稿 Agent 就很难核验上下文是否可信。
对 Agent 系统来说,资料生命周期可以用一条约束概括:
任何进入产物判断的资料,都应该能追溯到原始来源、更新时间和被使用的位置。
这条约束会影响索引字段、上下文对象、引用生成和审稿流程。它让混合检索从「找相似文本」变成「提供可信上下文」。
9. 评测与可观测性
混合检索上线后,需要观察一组和产物质量相关的指标:
| 指标 | 观察问题 |
|---|---|
| 关键词命中率 | 专有名词、API 名称、版本号是否被稳定召回 |
| 来源覆盖率 | 是否优先召回论文、官方文档和项目事实 |
| 过期资料占比 | 是否有旧版本资料进入最终上下文 |
| 去重率 | 是否大量重复召回同一来源 |
| 引用可追溯率 | 产物引用是否能回到 chunk_id 和 source_url |
| 审稿拦截率 | 审稿 Agent 拦下了多少无来源、过期或误用资料 |
| 上下文利用率 | 执行 Agent 最终使用了哪些片段,哪些被浪费 |
这些指标能帮助团队判断问题出在召回、排序、资料写入还是审稿规则。比如关键词命中率低,优先检查全文索引和查询计划;过期资料占比高,优先检查 metadata filter;引用可追溯率低,优先检查切块和上下文对象。
评测时除了看正常查询,也建议引入带噪声的对比测试:在资料流里注入不相关片段,观察系统是否会把干扰信息召回进上下文。如果噪声环境下的性能下降明显,往往说明门控或去重环节还不够强。
10. 总结
Agent 项目里的混合记忆架构,本质上是一套可信资料检索架构。它的目标是把合适的资料、以合适的结构、交给合适的 Agent。
关键要点:
- 向量检索适合语义召回,但不能单独处理专有名词、版本过滤、来源可信度和引用追踪。
- 资料需要同时进入向量索引、全文索引和元数据表,用写入冗余换取检索和审稿能力。
- 混合检索管线包括查询理解、多通道召回、来源可信度、rerank、去重、截断和引用追踪。
- 资料 Agent 更需要宽召回,审稿 Agent 更需要窄而可信的上下文。
- 资料写入阶段必须保留标题、版本、时间、来源 URL 和引用策略,否则后续审稿很难核验。
- 检索质量要通过关键词命中率、过期资料占比、引用可追溯率和审稿拦截率持续观察。
把这套架构放回 Agent 流程里,Agent 会围绕一组可追溯的资料对象协作:资料 Agent 负责发现,执行 Agent 负责组织,审稿 Agent 负责核验。
一句话总结:混合记忆架构不是让 Agent 记住更多,而是让它只记住对的、可追溯的、能用的资料。