Agent 记忆分层设计实践在智能问答系统中记忆是让 Agent 从一次性对话进化为持续学习型助手的核心能力。本文深入解析一个某个 FAQ 系统中的三层记忆架构——从对话历史到评分记忆库再到意图级复用带你理解如何让 Agent 越用越聪明。一、为什么需要分层记忆传统的 FAQ 问答系统通常采用检索-匹配-回答的固定流程。每次对话都是孤立的上一轮的优质回答不会对下一轮产生任何影响。这在通用知识库问答场景中暴露了三个问题重复提问浪费 Token用户反复问如何创建工单系统每次都走一遍完整检索和 ReAct 流程。知识无法沉淀人工维护的优秀问答例如客服整理的高分问答无法被系统直接利用。上下文割裂同一轮对话中用户的追问“那审核流程呢”如果不结合前文根本无法理解。于是我们设计了三层记忆架构L1→L2→L3让记忆逐层抽象、逐层持久化L1 对话历史 → L2 评分记忆库 → L3 意图复用 (短期) (中期) (长期) 每轮会话 高分QA沉淀 高置信度直接复用二、L1 对话历史——短期工作记忆2.1 设计定位L1 是最底层的对话历史记忆采用per-session 隔离设计。每一轮对话 session 拥有独立的存储空间不会互相干扰。2.2 持久化方案我们使用 Markdown 文件进行持久化每个 session 对应一个独立的 .md 文件。这种方式兼具人类可读性和机器可解析性——运维人员可以直接用文本编辑器查看对话历史调试时无需启动任何数据库客户端。会话记录结构 - per-session 隔离存储 - Markdown 格式持久化 - 按时间顺序记录对话轮次2.3 历史压缩策略对话历史不能无限增长否则上下文窗口会爆炸。我们设计了两阶段压缩机制# 截断策略超长消息直接截断HISTORY_SLIM_CHARS500# 单条消息超过此长度截断# 摘要替代assistant 的回答用 summary 替代# 原始回答 → summary 文本保留核心信息具体来说用户消息超过HISTORY_SLIM_CHARS字符的进行截断保留开头部分。Assistant 回答用summary替代完整回答。这基于一个观察——在 RAG 场景中assistant 的回答通常来自于检索到的知识片段而摘要就能保留核心信息大幅减少 Token 消耗。2.4 实现要点classSessionStore:对话历史存储per-session 隔离defsave_to_markdown(self,messages,session_id,summary):将对话历史保存为 Markdown 文件# 每轮对话追加到 session 对应的 .md 文件# 包含时间戳、角色、消息内容/摘要passdefload_session(self,session_id):加载指定 session 的对话历史passdefcompress_history(self,messages):压缩历史截断长消息 summary 替代完整回答pass为什么用 Markdown在开发阶段Markdown 比数据库更容易调试和排查问题。你可以直接cat一个 .md 文件看到完整的对话流而不需要写 SQL 查询。生产环境也可以平滑迁移到数据库存储。三、L2 评分记忆库——中期知识沉淀3.1 设计定位L2 是本文的核心——评分记忆系统Scoring Memory。它的职责是从对话历史中识别出高质量的问答对存储起来供后续复用。3.2 存储格式带 YAML Frontmatter 的 Markdown每个评分问答存储为一个qa-*.md文件使用YAML frontmatter承载元数据--- id: qa-20250601001 question: 如何在系统X中创建工单 score: 0.95 source_file: purchase_module.md source_location: 业务管理 工单创建 created_at: 2025-06-01T10:30:00Z keywords: [系统X, 工单, 创建] --- 在系统X中创建工单的步骤如下 1. 登录系统X进入「业务管理」模块 2. 点击「新建工单」按钮 3. 填写供应商信息、商品明细、数量单价 4. 确认无误后点击「提交」 5. 系统自动进入审核流程YAML frontmatter 的设计让元数据与内容分离搜索时只解析 frontmatter 就可以做快速过滤不需要加载完整内容。3.3 核心 APIclassMemory:评分记忆系统defsave_qa(self,question,answer,score,keywordsNone):保存一个评分问答对到 qa-*.md 文件passdefload_all_qa(self):加载所有评分问答passdefsearch(self,question,top_k5):从记忆库中搜索最匹配的问答candidatesself.load_all_qa()candidatesself._apply_ttl(candidates)# 构建匹配候选# 使用 matcher.match() 进行语义匹配# 按 匹配分 × TTL衰减 × 评分 排序returnsorted(candidates,keyself._sort_key,reverseTrue)[:top_k]3.4 关键词提取为了支持快速检索系统自动从问题中提取关键词defextract_keywords(self,text):2-gram 切分 停用词过滤提取关键词# 对中文文本进行 2-gram二元组切分# 过滤停用词的、了、是、在...# 保留有实际意义的词作为关键词pass设计选择为什么用 2-gram 而不是分词因为 2-gram 不需要词典对某个特有术语如系统文档、“系统C”、“系统A”的覆盖更好不会因为 OOVOut-of-Vocabulary问题丢失关键词。四、L3 意图复用——长期智能决策4.1 设计定位L3 是最上层的记忆层解决高频固定问题的高效响应。当一个问题满足以下条件时直接复用记忆中的答案跳过完整的检索和 ReAct 流程高置信度语义匹配分数超过阈值高评分score threshold分数阈值可配置4.2 工作流程用户问题 → 意图识别(intent.py) ├─ 置信度高 score ≥ 阈值 → 直接复用 L2 记忆答案L3 命中 ├─ 置信度中等 → 走正常 ReAct 流程检索知识库 生成回答 └─ 置信度低闲聊 → 走 Skip 策略直接问候L3 是 L2 的快车道——当 L2 记忆库中的某个问答被反复验证为高质量高 score它就会被提升到 L3 级别后续同类问题直接命中响应时间从秒级降至毫秒级。4.3 配置化控制# config.pyMEMORY_ENABLEDTrue# 记忆系统总开关MEMORY_TOP_K5# 每次搜索返回的最多候选数所有记忆行为都通过配置控制可以在不修改代码的情况下调整记忆策略。五、TTL 过期机制——让记忆保质保鲜5.1 为什么需要 TTL知识是有时效性的。通用业务流程会随政策、季节和版本更新而变化。去年创建工单的步骤可能已经变了如果一直使用旧记忆反而会误导用户。5.2 四种过期模式我们设计了灵活的 TTL 机制支持四种模式# memory.pyTTL_MODE_OFFoff# 永不过期适用于静态知识TTL_MODE_HARDhard# 硬过期超过 TTL 直接删除TTL_MODE_LINEARlinear# 线性衰减分数随天数线性下降TTL_MODE_EXPONENTIALexponential# 指数衰减分数加速下降模式行为适用场景off永不过期基础操作说明如登录步骤hard到期直接删除活动规则、限时政策linear分数线性下降一般业务知识随时间缓慢过时exponential分数指数级下降版本更新说明、即将变更的流程5.3 TTL 权重计算在排序时TTL 衰减直接影响候选问答的排名def_apply_ttl(self,candidates):对候选记忆应用 TTL 过滤和衰减forcincandidates:age_days(now-c.created_at).daysifmodehardandage_daysMEMORY_TTL_DAYS:continue# 直接过滤掉elifmodelinear:c.ttl_weightmax(0,1-age_days/MEMORY_TTL_DAYS)elifmodeexponential:c.ttl_weightmath.exp(-MEMORY_DECAY_RATE*age_days)elifmodeoff:c.ttl_weight1.0# 永远满分returncandidates指数衰减的物理意义exp(-λ * t)模拟了知识半衰期的概念。假设MEMORY_DECAY_RATE0.05那么大约 14 天后衰减到 0.528 天后到 0.25衰减速度前期快、后期慢符合知识过期的直觉——刚发布的知识衰减最快老知识如果还没被淘汰反而趋于稳定。六、排序策略——综合三大因子决策6.1 排序公式记忆搜索结果按以下复合指标排序sort_key rel × ttl_w × scorerel(relevance)语义匹配度由matcher.match()计算ttl_w(TTL weight)时间衰减权重0~1 之间score人工/系统评分的综合分0~1 之间6.2 完整搜索流程load_all_qa() → 从文件系统加载所有 QA ↓ _apply_ttl() → 过滤过期项 计算 TTL 权重 ↓ 关键词 原问题构建候选 → 降低搜索空间 ↓ matcher.match() → 语义匹配计算 rel ↓ 排序: rel × ttl_w × score → 取 TOP-K 返回6.3 设计哲学三个因子相乘而非相加是为了让任何一个因子为 0 都直接出局匹配度为 0完全不相关→ 总分 0TTL 权重为 0已过期→ 总分 0评分为 0从未验证→ 总分 0这种设计确保了返回的记忆既相关、又新鲜、又可靠。七、三层记忆的协作流程将三层记忆串联起来完整的协作流程如下用户提问 │ ▼ ┌──────────────────────────────────────────┐ │ L3 意图识别 (intent.py) │ │ 检查是否有高置信度 高评分记忆可用 │ │ ├─ 命中 → 直接返回记忆答案 │ │ └─ 未命中 → 进入下一层 │ └──────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────┐ │ L2 评分记忆库 (memory.py) │ │ 搜索评分记忆按 rel × ttl_w × score 排序 │ │ ├─ 高分匹配 → 返回答案 │ │ └─ 低分/未匹配 → 进入正常 ReAct 流程 │ └──────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────┐ │ 正常 ReAct 流程 L1 对话历史上下文 │ │ → 检索知识库 → LLM 生成回答 │ │ → 生成新 QA 对 → 评估 → 存入 L2 记忆库 │ └──────────────────────────────────────────┘ │ ▼ 返回给用户 更新 session_store (L1)八、总结与最佳实践8.1 三层记忆的定位总结层级名称存储持久化作用范围访问速度L1对话历史Markdown (per-session)session 级别当前对话上下文极快L2评分记忆库Markdown (qa-*.md YAML)持久化跨 session快L3意图复用内存缓存持久化(来源L2)高频固化问题毫秒级8.2 实践建议分层不是越多越好三层对于 FAQ 场景已经足够。层数过多会引入不必要的复杂度和维护成本。TTL 模式按内容类型选择静态知识用off版本变更用exponential活动规则用hard。评分需要闭环只存不评的记忆是垃圾。需要人工或自动化的评分反馈机制让低分记忆自然淘汰。Markdown 存储适合中小规模千级以下的 QA 库用文件系统完全够用。超过万级需考虑迁到向量数据库。8.3 演进方向当前的实现是一个良好的起点后续可以演进的方向包括L2 记忆的向量化存储用向量数据库替代文件系统支持更高效的语义检索。自动评分系统根据用户反馈点赞/点踩/追问自动更新 score。记忆合并与去重多个低分类似问答自动合并为一个高质量问答。跨用户记忆共享在权限控制基础上让已沉淀的知识在不同用户间共享。
一、Agent 记忆分层设计实践
发布时间:2026/6/4 19:46:22
Agent 记忆分层设计实践在智能问答系统中记忆是让 Agent 从一次性对话进化为持续学习型助手的核心能力。本文深入解析一个某个 FAQ 系统中的三层记忆架构——从对话历史到评分记忆库再到意图级复用带你理解如何让 Agent 越用越聪明。一、为什么需要分层记忆传统的 FAQ 问答系统通常采用检索-匹配-回答的固定流程。每次对话都是孤立的上一轮的优质回答不会对下一轮产生任何影响。这在通用知识库问答场景中暴露了三个问题重复提问浪费 Token用户反复问如何创建工单系统每次都走一遍完整检索和 ReAct 流程。知识无法沉淀人工维护的优秀问答例如客服整理的高分问答无法被系统直接利用。上下文割裂同一轮对话中用户的追问“那审核流程呢”如果不结合前文根本无法理解。于是我们设计了三层记忆架构L1→L2→L3让记忆逐层抽象、逐层持久化L1 对话历史 → L2 评分记忆库 → L3 意图复用 (短期) (中期) (长期) 每轮会话 高分QA沉淀 高置信度直接复用二、L1 对话历史——短期工作记忆2.1 设计定位L1 是最底层的对话历史记忆采用per-session 隔离设计。每一轮对话 session 拥有独立的存储空间不会互相干扰。2.2 持久化方案我们使用 Markdown 文件进行持久化每个 session 对应一个独立的 .md 文件。这种方式兼具人类可读性和机器可解析性——运维人员可以直接用文本编辑器查看对话历史调试时无需启动任何数据库客户端。会话记录结构 - per-session 隔离存储 - Markdown 格式持久化 - 按时间顺序记录对话轮次2.3 历史压缩策略对话历史不能无限增长否则上下文窗口会爆炸。我们设计了两阶段压缩机制# 截断策略超长消息直接截断HISTORY_SLIM_CHARS500# 单条消息超过此长度截断# 摘要替代assistant 的回答用 summary 替代# 原始回答 → summary 文本保留核心信息具体来说用户消息超过HISTORY_SLIM_CHARS字符的进行截断保留开头部分。Assistant 回答用summary替代完整回答。这基于一个观察——在 RAG 场景中assistant 的回答通常来自于检索到的知识片段而摘要就能保留核心信息大幅减少 Token 消耗。2.4 实现要点classSessionStore:对话历史存储per-session 隔离defsave_to_markdown(self,messages,session_id,summary):将对话历史保存为 Markdown 文件# 每轮对话追加到 session 对应的 .md 文件# 包含时间戳、角色、消息内容/摘要passdefload_session(self,session_id):加载指定 session 的对话历史passdefcompress_history(self,messages):压缩历史截断长消息 summary 替代完整回答pass为什么用 Markdown在开发阶段Markdown 比数据库更容易调试和排查问题。你可以直接cat一个 .md 文件看到完整的对话流而不需要写 SQL 查询。生产环境也可以平滑迁移到数据库存储。三、L2 评分记忆库——中期知识沉淀3.1 设计定位L2 是本文的核心——评分记忆系统Scoring Memory。它的职责是从对话历史中识别出高质量的问答对存储起来供后续复用。3.2 存储格式带 YAML Frontmatter 的 Markdown每个评分问答存储为一个qa-*.md文件使用YAML frontmatter承载元数据--- id: qa-20250601001 question: 如何在系统X中创建工单 score: 0.95 source_file: purchase_module.md source_location: 业务管理 工单创建 created_at: 2025-06-01T10:30:00Z keywords: [系统X, 工单, 创建] --- 在系统X中创建工单的步骤如下 1. 登录系统X进入「业务管理」模块 2. 点击「新建工单」按钮 3. 填写供应商信息、商品明细、数量单价 4. 确认无误后点击「提交」 5. 系统自动进入审核流程YAML frontmatter 的设计让元数据与内容分离搜索时只解析 frontmatter 就可以做快速过滤不需要加载完整内容。3.3 核心 APIclassMemory:评分记忆系统defsave_qa(self,question,answer,score,keywordsNone):保存一个评分问答对到 qa-*.md 文件passdefload_all_qa(self):加载所有评分问答passdefsearch(self,question,top_k5):从记忆库中搜索最匹配的问答candidatesself.load_all_qa()candidatesself._apply_ttl(candidates)# 构建匹配候选# 使用 matcher.match() 进行语义匹配# 按 匹配分 × TTL衰减 × 评分 排序returnsorted(candidates,keyself._sort_key,reverseTrue)[:top_k]3.4 关键词提取为了支持快速检索系统自动从问题中提取关键词defextract_keywords(self,text):2-gram 切分 停用词过滤提取关键词# 对中文文本进行 2-gram二元组切分# 过滤停用词的、了、是、在...# 保留有实际意义的词作为关键词pass设计选择为什么用 2-gram 而不是分词因为 2-gram 不需要词典对某个特有术语如系统文档、“系统C”、“系统A”的覆盖更好不会因为 OOVOut-of-Vocabulary问题丢失关键词。四、L3 意图复用——长期智能决策4.1 设计定位L3 是最上层的记忆层解决高频固定问题的高效响应。当一个问题满足以下条件时直接复用记忆中的答案跳过完整的检索和 ReAct 流程高置信度语义匹配分数超过阈值高评分score threshold分数阈值可配置4.2 工作流程用户问题 → 意图识别(intent.py) ├─ 置信度高 score ≥ 阈值 → 直接复用 L2 记忆答案L3 命中 ├─ 置信度中等 → 走正常 ReAct 流程检索知识库 生成回答 └─ 置信度低闲聊 → 走 Skip 策略直接问候L3 是 L2 的快车道——当 L2 记忆库中的某个问答被反复验证为高质量高 score它就会被提升到 L3 级别后续同类问题直接命中响应时间从秒级降至毫秒级。4.3 配置化控制# config.pyMEMORY_ENABLEDTrue# 记忆系统总开关MEMORY_TOP_K5# 每次搜索返回的最多候选数所有记忆行为都通过配置控制可以在不修改代码的情况下调整记忆策略。五、TTL 过期机制——让记忆保质保鲜5.1 为什么需要 TTL知识是有时效性的。通用业务流程会随政策、季节和版本更新而变化。去年创建工单的步骤可能已经变了如果一直使用旧记忆反而会误导用户。5.2 四种过期模式我们设计了灵活的 TTL 机制支持四种模式# memory.pyTTL_MODE_OFFoff# 永不过期适用于静态知识TTL_MODE_HARDhard# 硬过期超过 TTL 直接删除TTL_MODE_LINEARlinear# 线性衰减分数随天数线性下降TTL_MODE_EXPONENTIALexponential# 指数衰减分数加速下降模式行为适用场景off永不过期基础操作说明如登录步骤hard到期直接删除活动规则、限时政策linear分数线性下降一般业务知识随时间缓慢过时exponential分数指数级下降版本更新说明、即将变更的流程5.3 TTL 权重计算在排序时TTL 衰减直接影响候选问答的排名def_apply_ttl(self,candidates):对候选记忆应用 TTL 过滤和衰减forcincandidates:age_days(now-c.created_at).daysifmodehardandage_daysMEMORY_TTL_DAYS:continue# 直接过滤掉elifmodelinear:c.ttl_weightmax(0,1-age_days/MEMORY_TTL_DAYS)elifmodeexponential:c.ttl_weightmath.exp(-MEMORY_DECAY_RATE*age_days)elifmodeoff:c.ttl_weight1.0# 永远满分returncandidates指数衰减的物理意义exp(-λ * t)模拟了知识半衰期的概念。假设MEMORY_DECAY_RATE0.05那么大约 14 天后衰减到 0.528 天后到 0.25衰减速度前期快、后期慢符合知识过期的直觉——刚发布的知识衰减最快老知识如果还没被淘汰反而趋于稳定。六、排序策略——综合三大因子决策6.1 排序公式记忆搜索结果按以下复合指标排序sort_key rel × ttl_w × scorerel(relevance)语义匹配度由matcher.match()计算ttl_w(TTL weight)时间衰减权重0~1 之间score人工/系统评分的综合分0~1 之间6.2 完整搜索流程load_all_qa() → 从文件系统加载所有 QA ↓ _apply_ttl() → 过滤过期项 计算 TTL 权重 ↓ 关键词 原问题构建候选 → 降低搜索空间 ↓ matcher.match() → 语义匹配计算 rel ↓ 排序: rel × ttl_w × score → 取 TOP-K 返回6.3 设计哲学三个因子相乘而非相加是为了让任何一个因子为 0 都直接出局匹配度为 0完全不相关→ 总分 0TTL 权重为 0已过期→ 总分 0评分为 0从未验证→ 总分 0这种设计确保了返回的记忆既相关、又新鲜、又可靠。七、三层记忆的协作流程将三层记忆串联起来完整的协作流程如下用户提问 │ ▼ ┌──────────────────────────────────────────┐ │ L3 意图识别 (intent.py) │ │ 检查是否有高置信度 高评分记忆可用 │ │ ├─ 命中 → 直接返回记忆答案 │ │ └─ 未命中 → 进入下一层 │ └──────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────┐ │ L2 评分记忆库 (memory.py) │ │ 搜索评分记忆按 rel × ttl_w × score 排序 │ │ ├─ 高分匹配 → 返回答案 │ │ └─ 低分/未匹配 → 进入正常 ReAct 流程 │ └──────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────┐ │ 正常 ReAct 流程 L1 对话历史上下文 │ │ → 检索知识库 → LLM 生成回答 │ │ → 生成新 QA 对 → 评估 → 存入 L2 记忆库 │ └──────────────────────────────────────────┘ │ ▼ 返回给用户 更新 session_store (L1)八、总结与最佳实践8.1 三层记忆的定位总结层级名称存储持久化作用范围访问速度L1对话历史Markdown (per-session)session 级别当前对话上下文极快L2评分记忆库Markdown (qa-*.md YAML)持久化跨 session快L3意图复用内存缓存持久化(来源L2)高频固化问题毫秒级8.2 实践建议分层不是越多越好三层对于 FAQ 场景已经足够。层数过多会引入不必要的复杂度和维护成本。TTL 模式按内容类型选择静态知识用off版本变更用exponential活动规则用hard。评分需要闭环只存不评的记忆是垃圾。需要人工或自动化的评分反馈机制让低分记忆自然淘汰。Markdown 存储适合中小规模千级以下的 QA 库用文件系统完全够用。超过万级需考虑迁到向量数据库。8.3 演进方向当前的实现是一个良好的起点后续可以演进的方向包括L2 记忆的向量化存储用向量数据库替代文件系统支持更高效的语义检索。自动评分系统根据用户反馈点赞/点踩/追问自动更新 score。记忆合并与去重多个低分类似问答自动合并为一个高质量问答。跨用户记忆共享在权限控制基础上让已沉淀的知识在不同用户间共享。