当前位置: 首页 > news >正文

一、Agent 记忆分层设计实践

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_CHARS=500# 单条消息超过此长度截断# 摘要替代: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 核心 API

classMemory:"""评分记忆系统"""defsave_qa(self,question,answer,score,keywords=None):"""保存一个评分问答对到 qa-*.md 文件"""passdefload_all_qa(self):"""加载所有评分问答"""passdefsearch(self,question,top_k=5):"""从记忆库中搜索最匹配的问答"""candidates=self.load_all_qa()candidates=self._apply_ttl(candidates)# 构建匹配候选# 使用 matcher.match() 进行语义匹配# 按 匹配分 × TTL衰减 × 评分 排序returnsorted(candidates,key=self._sort_key,reverse=True)[:top_k]

3.4 关键词提取

为了支持快速检索,系统自动从问题中提取关键词:

defextract_keywords(self,text):"""2-gram 切分 + 停用词过滤提取关键词"""# 对中文文本进行 2-gram(二元组)切分# 过滤停用词(的、了、是、在...)# 保留有实际意义的词作为关键词pass

设计选择:为什么用 2-gram 而不是分词?因为 2-gram 不需要词典,对某个特有术语(如"系统文档"、“系统C”、“系统A”)的覆盖更好,不会因为 OOV(Out-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_ENABLED=True# 记忆系统总开关MEMORY_TOP_K=5# 每次搜索返回的最多候选数

所有记忆行为都通过配置控制,可以在不修改代码的情况下调整记忆策略。

五、TTL 过期机制——让记忆保质保鲜

5.1 为什么需要 TTL?

知识是有时效性的。通用业务流程会随政策、季节和版本更新而变化。去年"创建工单"的步骤可能已经变了,如果一直使用旧记忆,反而会误导用户。

5.2 四种过期模式

我们设计了灵活的 TTL 机制,支持四种模式:

# memory.pyTTL_MODE_OFF="off"# 永不过期(适用于静态知识)TTL_MODE_HARD="hard"# 硬过期(超过 TTL 直接删除)TTL_MODE_LINEAR="linear"# 线性衰减(分数随天数线性下降)TTL_MODE_EXPONENTIAL="exponential"# 指数衰减(分数加速下降)
模式行为适用场景
off永不过期基础操作说明(如登录步骤)
hard到期直接删除活动规则、限时政策
linear分数线性下降一般业务知识,随时间缓慢过时
exponential分数指数级下降版本更新说明、即将变更的流程

5.3 TTL 权重计算

在排序时,TTL 衰减直接影响候选问答的排名:

def_apply_ttl(self,candidates):"""对候选记忆应用 TTL 过滤和衰减"""forcincandidates:age_days=(now-c.created_at).daysifmode=="hard"andage_days>MEMORY_TTL_DAYS:continue# 直接过滤掉elifmode=="linear":c.ttl_weight=max(0,1-age_days/MEMORY_TTL_DAYS)elifmode=="exponential":c.ttl_weight=math.exp(-MEMORY_DECAY_RATE*age_days)elifmode=="off":c.ttl_weight=1.0# 永远满分returncandidates

指数衰减的物理意义exp(-λ * t)模拟了"知识半衰期"的概念。假设MEMORY_DECAY_RATE=0.05,那么大约 14 天后衰减到 0.5,28 天后到 0.25,衰减速度前期快、后期慢,符合知识过期的直觉——刚发布的知识衰减最快,老知识如果还没被淘汰,反而趋于稳定。

六、排序策略——综合三大因子决策

6.1 排序公式

记忆搜索结果按以下复合指标排序:

sort_key = rel × ttl_w × score
  • rel(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(完全不相关)→ 总分 0
  • TTL 权重为 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 实践建议

  1. 分层不是越多越好:三层对于 FAQ 场景已经足够。层数过多会引入不必要的复杂度和维护成本。
  2. TTL 模式按内容类型选择:静态知识用off,版本变更用exponential,活动规则用hard
  3. 评分需要闭环:只存不评的记忆是垃圾。需要人工或自动化的评分反馈机制,让低分记忆自然淘汰。
  4. Markdown 存储适合中小规模:千级以下的 QA 库用文件系统完全够用。超过万级需考虑迁到向量数据库。

8.3 演进方向

当前的实现是一个良好的起点,后续可以演进的方向包括:

  • L2 记忆的向量化存储:用向量数据库替代文件系统,支持更高效的语义检索。
  • 自动评分系统:根据用户反馈(点赞/点踩/追问)自动更新 score。
  • 记忆合并与去重:多个低分类似问答自动合并为一个高质量问答。
  • 跨用户记忆共享:在权限控制基础上,让已沉淀的知识在不同用户间共享。

http://www.jsqmd.com/news/950609/

相关文章:

  • 从手写快排到AI生成代码:一个.NET工程师十二年间的算法观
  • 网络安全和安防建设方案(doc文件)
  • 基于Makey Makey与Scratch的校园互动问答系统设计与实现
  • 沪上珠宝首饰回收权威榜单,蒂芙尼回收首选上海禹竞名奢汇 - 奢侈品交易观察员
  • trick
  • 【仅剩47家获准试点】AI驱动的动态质押率系统:如何用联邦学习在不共享原始数据前提下提升抵押率容忍度22.6%?
  • 不如去杭州“躺平”一会儿!西湖边这条惬意漫步路线,太治愈了
  • 2026 年 6 月证券刷题神器实测:免费高效通关全攻略 - 讲清楚了
  • 别再手动转换了!CAPL脚本里整型数组与Hex字符串互转的通用函数库(附完整源码)
  • 开源征程,邀你同行|IvorySQL 2026 布道者招募启动,快来报名!
  • 2026苏州吴中/吴江/昆山瓷砖空鼓需要全部砸掉吗?本地专业答案 - 苏易修缮
  • 遥感入门不求人:用Python+ENVI 5.3快速识别植被、水体与裸土(附光谱曲线对比图)
  • 3步搞定Windows风扇控制难题:FanControl完整实用指南
  • DIY蓝牙音箱全流程:从电路设计到木工制作,打造个性化音频设备
  • Micro:bit与伺服电机打造圣诞旋转木马:从硬件连接到编程控制
  • 2026苏州姑苏/常熟老房子瓷砖空鼓翘边能彻底修好吗? - 苏易修缮
  • XDM浏览器扩展终极指南:如何快速安装并提升下载速度500%
  • 2026苏州姑苏/园区/相城梅雨季瓷砖空鼓发霉、返潮脱落怎么处理 - 苏易修缮
  • MATLAB小波多尺度图像配准与融合可视化工具(含测试图+可运行GUI源码)
  • 5分钟打造你的Windows桌面监控中心:TrafficMonitor插件终极指南
  • 2026年泰安装修设计公司推荐榜:尚城装饰中高端家装/高端别墅设计/整装施工/全屋定制/轻奢品质家装/宋式美学与新中式极简风家居推荐 - 品牌企业推荐师(官方)
  • 监管新规倒计时60天:金融机构AI投资系统合规改造清单(含证监会备案自查表V2.3)
  • 从一封邮件被删除说起:Wireshark深度解析POP3协议的‘状态机’与安全启示
  • 2026苏州吴江/昆山/常熟/太仓瓷砖空鼓怎么修?本地免砸砖修复方法大全 - 苏易修缮
  • 我用 AI 模拟字节跳动三面,系统设计轮答到一半面试官沉默了
  • 用AI写论文为何越用越累?复盘我的踩坑经验与正确用法
  • 【v 2.7.5 新版】爆火 Open Claw 完整部署教程(含安装包)
  • 用树莓派搭建Pi-Hole:打造无广告家庭网络的完整指南
  • 2026苏州全城免砸砖修瓷砖空鼓靠谱吗?本地实测真实效果 - 苏易修缮
  • 智能担保不是加AI,而是重定义风险契约——基于27家金融机构实测数据的5维评估模型