AI Agent记忆系统设计:Gliding Horse三层架构与CPU式管理实践
1. 项目概述:当AI开始拥有“记忆”
最近在折腾AI Agent开发的朋友,估计都绕不开一个核心难题:如何让AI记住东西?不是那种对话里“嗯嗯啊啊”的短期上下文,而是真正像人一样,能记住过去几小时、几天甚至几周的关键信息,并在需要时精准调取。这直接决定了Agent是只能执行简单指令的“一次性工具”,还是能处理复杂、长周期任务的“智能伙伴”。
我最近深度研究并实践了Gliding Horse这套记忆系统,它来自Agent Harness框架。这个名字很有意思,“滑翔的马”,听起来既优雅又充满力量感。它的设计理念非常吸引我:让AI的记忆管理像CPU管理内存一样高效、分层、有序。这不再是简单地把对话历史往向量数据库里一扔了事,而是构建了一套从瞬时工作记忆到长期归档记忆的完整架构。
简单来说,Gliding Horse试图解决的是当前AI Agent领域的“记忆失忆症”。你训练了一个很棒的Agent,它能写代码、能分析数据,但当你让它基于昨天的讨论继续修改方案,或者让它记住你的个人偏好时,它往往表现得像个金鱼。Gliding Horse就是给这条“金鱼”装上了一个分层的记忆硬盘和一套智能的索引系统。
这套系统适合谁?如果你是AI应用开发者、产品经理,或者对Agent架构感兴趣的技术爱好者,想要构建能真正“持续学习”和“个性化”的智能应用,那么理解Gliding Horse背后的思想,会比单纯调用某个API更有价值。它提供的是一个设计范式,而不仅仅是一个工具。
2. 核心架构解析:三层记忆与CPU式管理
Gliding Horse的核心,在于其清晰的三层记忆架构。这并非凭空想象,而是借鉴了计算机体系结构中经典的存储层次结构(寄存器-缓存-内存-硬盘),并将其巧妙地映射到AI的认知过程中。
2.1 三层记忆结构详解
第一层是工作记忆(Working Memory)。这相当于CPU的寄存器和L1/L2缓存。它的容量极小,但速度极快,存取延迟极低。在Gliding Horse中,工作记忆直接与Agent的“思考循环”绑定,保存着当前任务执行所需的全部即时信息:当前目标、上一步的输出、工具调用的结果、以及从长期记忆中提取出来的最相关片段。它的生命周期很短,通常只存在于一个任务执行周期内。设计的关键在于“极致的相关性”和“极低的延迟”,确保Agent“手边”永远有最需要的信息。
注意:工作记忆的设计最容易犯的错误是“塞得太满”。有些实现会把整个会话历史都放进去,这会导致核心信息被淹没,推理速度下降。Gliding Horse的策略是主动过滤和摘要,只保留对当前推理步骤有直接因果或逻辑关联的信息。
第二层是短期记忆(Short-Term Memory)。这对应着计算机的主内存(RAM)。它的容量比工作记忆大得多,可以保存最近一段时间(例如过去24小时或最近100轮对话)的完整交互历史。短期记忆是构成会话连续性的基础。用户会觉得Agent“记得刚才聊过什么”,主要就是靠这一层。它的实现通常基于向量数据库(如Chroma, Weaviate)或高性能键值存储,通过向量相似度检索来快速找到与当前查询相关的历史片段。
第三层是长期记忆(Long-Term Memory)。这就是计算机的硬盘或SSD了。它用于存储需要永久或长期保留的信息,比如用户的个人档案、领域专业知识、项目核心文档、以及从过往经历中提炼出的“经验教训”。长期记忆的挑战不在于存储,而在于高效的索引和唤醒。Gliding Horse在这里引入了“记忆凝结”的概念:不是简单存储原始对话,而是定期对短期记忆中的内容进行总结、去重、打标,形成结构化的“记忆晶体”存入长期记忆。例如,连续十次对话中用户都提到了“喜欢用Markdown写文档”,这个偏好就会被凝结成一个标签为[用户偏好,文档格式]的记忆晶体存入长期记忆。
2.2 “像CPU一样思考”的管理策略
分层只是基础,如何让数据在各层之间高效流动,才是Gliding Horse的精髓,也是其“CPU式”思维的体现。
- 加载(Loading):当Agent开始处理一个新任务或用户输入时,它首先会从长期记忆中,根据任务目标和个人画像,检索出可能相关的“记忆晶体”集合。这个过程就像程序启动时从硬盘加载必要的数据段到内存。然后,结合短期记忆中最近的上下文,筛选出最相关的信息,注入到工作记忆中,供核心推理逻辑使用。这个加载过程是预测性的,旨在让Agent“有备而来”。
- 存储(Storing):任务执行过程中产生的新信息(思考过程、工具返回结果、用户反馈)会首先写入工作记忆。一个任务步骤完成后,系统会判断哪些信息具有超越当前任务的保留价值。如果是重要的中间结论或事实,会写入短期记忆;如果是具有普遍意义的模式、用户确认的偏好或任务最终成果,则会在任务结束后,通过“凝结”过程,提炼并存入长期记忆。
- 替换与淘汰:工作记忆在每个推理步骤后都可能被清空或大部分替换,只保留跨步骤的状态信息。短期记忆采用滑动窗口或LRU(最近最少使用)策略,淘汰旧的对话轮次。长期记忆虽然理论上永久保存,但也会通过重要性评分和访问频率,对记忆晶体进行归档或降级,防止无效信息污染检索池。
这种主动、预测性的内存管理,使得Agent能够将有限的“注意力带宽”集中在最相关的信息上,大大提升了复杂任务处理的效率和连贯性。
3. 核心组件与实现拆解
理解了架构,我们来看看Gliding Horse是如何用具体组件实现这套理念的。它不是一个单一模块,而是一个由多个协同工作的子系统构成的“记忆中枢”。
3.1 记忆编码器与向量化策略
记忆的存储前提是编码。Gliding Horse没有采用单一的编码方式,而是根据记忆类型和用途进行差异化处理。
- 对于事实与知识:主要使用嵌入模型(如
text-embedding-3-small)进行密集向量化。这是实现语义检索的基石。关键技巧在于分块(Chunking)策略。对于长文档,不能简单粗暴地按固定字数切分。Gliding Horse会优先在段落、标题等语义边界进行切分,并为每个块生成一个概括性的“摘要标题”,这个标题也会被单独向量化,用于粗筛,从而提高长文档检索的精度和效率。 - 对于事件与过程:除了向量化,还会提取结构化元数据。例如,一个“完成用户注册”的记忆,其元数据可能包括:
{类型: 任务, 状态: 成功, 涉及实体: [用户A, 数据库], 时间戳: 2023-10-01 10:00, 耗时: 2.3秒}。这些元数据可以用于基于属性的快速过滤(“给我找出所有失败的任务”),与基于向量的语义检索(“用户遇到注册问题”)形成互补。 - 对于偏好与模式:采用关键词/标签化与轻量化向量结合。例如,“用户偏好深色模式”这个记忆,会被打上
[UI, 偏好, 深色模式]的标签,同时生成一个轻量向量。检索时可以先通过标签快速缩小范围,再用向量做精细匹配。
3.2 记忆检索器:从相似度到相关性
检索是记忆系统的“CPU缓存命中”环节。Gliding Horse的检索器不是简单的“向量相似度排序”,而是一个多阶段、重排名的管道。
- 召回阶段:根据当前查询,并行地从不同记忆层和索引中召回候选记忆。可能同时查询:短期记忆的向量索引、长期记忆中特定标签下的记忆晶体、以及基于元数据的过滤结果。这一步追求“全”,避免遗漏。
- 粗排阶段:对召回的所有候选记忆进行快速打分。打分函数不仅仅是余弦相似度,而是融合了:
- 语义相关性:向量相似度得分。
- 时间衰减:越近的记忆得分权重越高,这模拟了人类的记忆规律。
- 访问频率:经常被用到的记忆,可能更重要。
- 记忆强度:在存入时根据重要性手动或自动赋予的权重。
- 精排阶段:将粗排后的Top-K个记忆(比如20个),连同当前的完整上下文(工作记忆中的内容),一起送给一个大语言模型(LLM)进行重排序和摘要。让LLM判断:“在这些记忆中,哪些对回答当前问题或完成当前步骤最直接、最关键?”LLM可以理解更复杂的逻辑关系,比如因果关系、矛盾关系,这是单纯向量匹配做不到的。
- 注入阶段:将精排后的Top-N个记忆(比如5个),以结构化的格式(如“根据之前的记录:1... 2...”)注入到Agent的提示词(Prompt)中,成为工作记忆的一部分。
实操心得:很多团队在实现检索时,只做到第一步就结束了,导致检索结果虽然“相似”但不“有用”。加入LLM重排步骤,虽然增加了一次API调用,但对最终任务成功率的提升非常显著,尤其是在复杂决策场景下。你可以从较小的K值(如10)开始实验,平衡效果与成本。
3.3 记忆凝结与遗忘机制
这是赋予AI“成长性”和“管理性”的关键。
记忆凝结:这是一个离线或低优先级后台任务。系统会定期(如每天)扫描短期记忆,寻找可以“凝结”的模式。例如:
- 摘要凝结:将关于同一个主题的多次分散对话,总结成一段连贯的叙述。
- 偏好提取:从用户多次的选择或肯定中,抽象出一条明确的偏好规则。
- 模式发现:识别出任务执行过程中的常见成功路径或失败陷阱。 凝结后的“记忆晶体”会被赋予更丰富的元数据和更高的初始强度值,存入长期记忆。这个过程大大压缩了记忆的存储体积,并提升了记忆的质量。
遗忘机制:没有遗忘的记忆系统最终会被垃圾信息拖垮。Gliding Horse实现了软遗忘和硬遗忘。
- 软遗忘:通过记忆强度衰减实现。长期不访问的记忆,其强度会随时间缓慢下降。在检索时,强度是打分因子之一,强度过低的记忆很难被召回,相当于被“封存”了。
- 硬遗忘:提供手动或基于规则的API,允许主动删除特定记忆。例如,可以设置规则:“当用户明确说‘忘记我刚才说的’时,删除最近三轮对话中用户提供的所有信息。”这符合数据隐私和用户控制的需求。
4. 在Agent Harness中的集成与实践
Gliding Horse并非一个孤立运行的系统,它是为增强Agent Harness框架中的Agent能力而设计的。理解它的集成方式,才能更好地应用。
4.1 与Agent核心循环的协作
在一个典型的基于Agent Harness的Agent运行周期中,Gliding Horse在以下节点被触发:
- 任务初始化:Agent收到主任务或用户输入。此时,记忆系统启动加载流程,根据任务描述和用户ID,从长期和短期记忆中检索相关背景,预加载到工作记忆的“上下文”区域。
- 每一步推理前:在Agent决定下一步行动(思考、调用工具、回复)前,工作记忆会结合上一步的结果,再次向短期/长期记忆发起一次快速检索,确保拥有最新的相关信息。这类似于CPU的缓存预取。
- 每一步推理后:将这一步产生的重要结果(工具执行结果、新的推理结论)作为新记忆,写入工作记忆,并标记其潜在价值。
- 任务结束时:触发记忆的存储流程。对整个任务流中标记为高价值的信息进行凝结,并决定其归宿(进入短期或长期记忆)。同时,清理本次任务的工作记忆,为下一个任务做准备。
这种深度集成使得记忆的读写成为Agent推理流程中无缝的一部分,而不是事后附加的日志功能。
4.2 状态管理与上下文维护
Agent在运行中会维护一个会话状态(Session State)。Gliding Horse的工作记忆本质上是这个会话状态中最活跃、最核心的部分。实现时,需要精心设计这个状态对象的结构,例如:
class AgentSessionState: def __init__(self, user_id, session_id): self.user_id = user_id self.session_id = session_id self.current_goal = None # 当前目标 self.working_memory = { 'context': [], # 从记忆系统加载的上下文 'step_history': [], # 本轮任务已执行的步骤历史 'tool_results': [], # 工具调用结果缓存 'derived_facts': [] # 推理得出的中间事实 } self.short_term_memories = [] # 指向短期记忆的引用或ID记忆系统需要能够读取和更新这个状态。当从记忆系统检索时,结果会被注入到working_memory['context']中。当存储记忆时,系统会从step_history,tool_results等字段中提取有价值的信息。
4.3 配置参数与性能调优
部署Gliding Horse时,有一系列参数需要根据实际场景调优:
| 参数组 | 关键参数 | 说明 | 调优建议 |
|---|---|---|---|
| 检索相关 | top_k_recall | 召回阶段候选记忆数量 | 通常50-100。太小易遗漏,太大增加重排负担。 |
top_n_final | 最终注入工作记忆的记忆条数 | 通常3-7条。受限于LLM上下文窗口,需保证核心信息不超限。 | |
similarity_threshold | 向量相似度最低阈值 | 过滤掉明显不相关的记忆。可从0.7开始实验。 | |
| 记忆凝结 | condensation_interval | 凝结任务运行间隔 | 根据业务活跃度设置,如每小时或每天。 |
min_occurrence_for_preference | 形成偏好所需的最少出现次数 | 避免偶然事件被误判为偏好,通常>=3。 | |
| 遗忘机制 | decay_rate | 记忆强度衰减率 | 控制记忆“保质期”。值越大忘得越快。 |
forget_strength_threshold | 硬遗忘的强度阈值 | 低于此值的记忆可被自动清理。 |
性能调优的核心原则是平衡:检索的召回率与精度、记忆的丰富度与检索速度、存储的完整性与成本。建议从一个小而具体的场景开始,设定可量化的评估指标(如任务完成率、用户满意度、平均响应延迟),然后进行A/B测试,逐步调整参数。
5. 实战:构建一个具有记忆的智能客服Agent
理论说得再多,不如动手试一下。我们设想一个场景:为一个SaaS产品构建一个智能客服Agent,它需要记住用户的产品使用历史、过往的工单问题以及沟通中透露的个人偏好。
5.1 场景定义与记忆规划
首先,我们需要规划这个客服Agent需要哪些记忆:
- 长期记忆:
- 用户档案:公司规模、所属行业、订阅版本、关键联系人。这是静态基础信息。
- 产品知识:产品文档、常见问题解答、更新日志。这是领域知识。
- 历史问题模式:从解决过的工单中凝结出的“某行业客户常遇到A问题,解决方案是B”这类经验。
- 短期记忆:
- 本次会话记录:当前对话的完整历史。
- 近期交互:过去7天内该用户的所有咨询记录。
- 工作记忆:
- 当前问题描述:用户本次提交的具体问题。
- 已尝试方案:在本轮对话中,Agent已经推荐或尝试过的解决方案。
- 加载的相关背景:从长/短期记忆中检索到的与该用户、该问题相关的所有信息。
5.2 分步实现与代码要点
我们使用伪代码结合Python风格来描述关键步骤。
步骤1:初始化记忆系统与Agent
# 初始化记忆存储(这里用字典模拟,实际应用需连接数据库) long_term_store = VectorStore(index='user_profiles') # 存储用户档案向量 short_term_store = VectorStore(index='session_history') # 存储会话向量 memory_consolidator = MemoryConsolidator() # 记忆凝结器 # 初始化客服Agent,并注入记忆系统客户端 class CustomerSupportAgent: def __init__(self, memory_client): self.memory = memory_client self.working_memory = {}步骤2:用户发起咨询时的记忆加载
def handle_user_query(self, user_id, query): # 1. 从长期记忆加载用户档案和可能相关的知识 user_profile = self.memory.recall_long_term(user_id, query) relevant_knowledge = self.memory.recall_knowledge_base(query) # 2. 从短期记忆加载近期会话 recent_chats = self.memory.recall_short_term(user_id, limit=5) # 3. 将所有相关信息整合,注入工作记忆 self.working_memory['context'] = format_context( user_profile, relevant_knowledge, recent_chats ) self.working_memory['current_query'] = query # 4. Agent基于丰富的工作记忆开始推理... response = self.reason_and_act() return response步骤3:在推理过程中动态检索假设Agent在推理中决定要检查某个特定错误码的解决方案。
def reason_and_act(self): # ... 部分推理逻辑 if need_check_error_code('ERR_1001'): # 动态从记忆(特别是知识库)中检索该错误码的详细信息 error_details = self.memory.recall_by_metadata( store='knowledge_base', filters={'type': 'error_code', 'code': 'ERR_1001'} ) # 将检索结果动态加入工作记忆 self.working_memory['retrieved_details'] = error_details # ... 继续推理并生成回复步骤4:会话结束后的记忆存储与凝结
def end_session(self, user_id, session_log, resolution_summary): # 1. 将完整的会话日志存入短期记忆 self.memory.store_short_term(user_id, session_log) # 2. 如果问题得到解决,凝结经验 if resolution_summary['status'] == 'resolved': new_experience = self.memory_consolidator.condense( problem=session_log['problem'], solution=resolution_summary['solution'], user_context=self.working_memory['context'] ) # 将凝结后的经验存入长期记忆的“问题模式”库 self.memory.store_long_term('solution_patterns', new_experience) # 3. 识别并存储用户偏好(例如,用户多次要求“把解决方案发我邮箱”) detected_preferences = extract_preferences(session_log) for pref in detected_preferences: self.memory.store_long_term('user_preferences', pref, user_id)5.3 效果评估与迭代
部署后,我们需要评估这个“有记忆”的客服Agent的效果:
- 效率指标:平均解决时间是否缩短?转接人工坐席的比例是否下降?
- 质量指标:用户满意度评分(CSAT)是否提升?同一用户重复提问同一问题的频率是否降低?
- 记忆有效性指标:Agent在回复中主动引用历史信息的比例是多少?这些引用是否准确相关?
通过监控这些指标,我们可以反过来调整记忆系统的参数:例如,如果发现Agent经常引用不相关的旧信息,可能需要提高相似度阈值或改进凝结策略;如果发现无法记住关键偏好,可能需要降低偏好提取的阈值。
6. 常见陷阱、挑战与优化策略
在实际部署Gliding Horse或类似记忆系统时,我踩过不少坑,也总结出一些优化策略。
6.1 典型问题与排查清单
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| Agent回复变慢 | 1. 检索的候选集(top_k_recall)过大。2. 记忆凝结任务阻塞主线程。 3. 向量索引未优化,查询慢。 | 1. 监控检索各阶段耗时,缩小top_k_recall。2. 将凝结改为异步后台任务。 3. 检查向量数据库性能,考虑使用HNSW等更快的索引算法。 |
| 记忆检索不准确,总找旧/错信息 | 1. 向量嵌入模型与任务不匹配。 2. 缺少元数据过滤,仅靠语义相似度。 3. 记忆强度衰减过快,重要记忆被“软遗忘”。 | 1. 在领域数据上微调嵌入模型,或更换更适配的模型。 2. 在检索中结合时间、类型等元数据过滤器。 3. 调整衰减率,或对重要记忆设置初始高强度。 |
| 长期记忆膨胀,存储成本高 | 1. 所有信息都存为长期记忆,缺少凝结和摘要。 2. 没有有效的遗忘机制。 | 1. 强化凝结流程,只存结构化、去重的“晶体”。 2. 实施基于访问频率和强度的自动归档策略。 |
| Agent表现不一致,时好时坏 | 1. 检索结果具有随机性(尤其是相似度边缘的记忆)。 2. 工作记忆加载的内容每次略有差异,影响推理。 | 1. 在精排阶段使用LLM重排,提升结果稳定性。 2. 确保工作记忆的初始化流程是确定性的,例如固定检索条数并按综合评分严格排序。 |
| 用户感到隐私担忧 | 1. Agent过于具体地引用了历史对话细节。 2. 无法提供“忘记”某些信息的机制。 | 1. 在回复时对引用信息进行适度概括,而非直接引用原文。 2. 必须提供硬遗忘API,并确保数据物理删除。 |
6.2 高阶优化技巧
- 混合检索策略:不要只依赖向量检索。对于用户ID、时间范围、事件类型等精确匹配查询,先用传统数据库(如SQL)过滤,再用向量检索在结果子集中做语义匹配,可以极大提升效率和准确率。
- 记忆重要性预测:在存储记忆时,用一个轻量级模型(甚至是一组规则)预测该记忆未来的重要性,并赋予其初始强度。例如,用户明确说“这个很重要”的语句,其初始强度应设为最高。
- 上下文感知的检索:检索查询不应只是用户当前的一句话。而应将当前工作记忆中的任务目标、已执行步骤等也作为查询的一部分,让检索更贴合Agent当前的“思维状态”。
- 测试与评估体系:建立记忆系统的专项测试集。例如,构造一系列需要记忆才能回答的问答对(“我昨天说的那个方案是什么来着?”),定期跑测试,监控准确率变化。
6.3 关于成本与规模的考量
记忆系统,尤其是依赖大模型进行重排和凝结的系统,会增加计算和API调用成本。在规模应用时需考虑:
- 缓存策略:对高频但不变的记忆(如产品知识),其检索结果可以缓存一段时间。
- 异步与批处理:记忆凝结、强度衰减计算等任务,完全可以放在异步队列中定时批处理,不影响实时交互。
- 分级存储:访问频率极低的长期记忆,可以从昂贵的向量数据库迁移到更廉价的对象存储中,仅保留其元数据和索引在快速存储里。
Gliding Horse记忆架构为我们设计实用的AI Agent提供了一个强大的蓝图。它告诉我们,AI的记忆不是附属功能,而是核心能力。实现它需要细致的工程设计和持续的调优,但带来的回报是Agent能力质的飞跃——从一个健忘的“任务执行器”变成一个真正有延续性、有个性化的“智能体”。