
1. 项目概述为什么AI需要“长期记忆”最近在折腾各种AI应用尤其是基于大语言模型的聊天机器人时我总感觉缺了点什么。比如你跟它聊了半小时从工作聊到生活甚至提到了你养的那只叫“元宝”的猫。但当你第二天再打开聊天窗口问它“我昨天跟你提过我家猫叫什么吗”它大概率会一脸茫然地回答“抱歉我们之前的对话内容没有被保留。” 这种体验就像跟一个永远只有7秒记忆的金鱼聊天每次对话都得从头开始深度和连续性无从谈起。这就是“会话失忆”问题也是当前绝大多数AI聊天应用的硬伤。它们通常采用“无状态”设计每次请求都是独立的模型只基于当前输入的提示词Prompt和有限的上下文窗口比如最新的几千个Token来生成回复。一旦对话轮次增多或者时间跨度拉长那些早期的重要信息——用户的偏好、历史决策、关键事实——就会被无情地“遗忘”。“给 AI Chat 加上长期记忆”这个项目就是为了解决这个核心痛点。它不是一个简单的聊天记录存储而是一套系统工程旨在让AI能够像人类一样从海量的过往交互中主动地、有选择地记住关键信息并在未来的对话中精准地、适时地回忆起来。我把它拆解为三个核心环节模型提取、程序把关、规则召回。这听起来有点抽象你可以把它想象成构建一个AI的“外置大脑”或“智能秘书”。模型提取这是记忆的“感知与理解”层。当用户说“我下周要去上海出差记得提醒我带厚外套”时AI需要理解这句话里的关键实体“上海”、“下周”、“厚外套”和意图“提醒”、“出差准备”。这一步我们依赖大语言模型本身强大的语义理解能力将非结构化的对话文本提炼成结构化的“记忆片段”。程序把关这是记忆的“筛选与入库”层。不是用户说的每一句话都值得记住。“你好”、“在吗”这种寒暄毫无价值而“我对花生严重过敏”则是关乎安全的黄金信息。这一步我们需要用程序化的规则和逻辑对模型提取出的记忆片段进行过滤、去重、合并和重要性评分确保存入记忆库的都是高价值、无噪音的“干货”。规则召回这是记忆的“检索与应用”层。当用户开启新一轮对话比如问“上海天气怎么样”时系统需要立刻从记忆库中将与“上海”、“天气”以及当前用户可能相关的历史信息如“下周去上海出差”找出来并巧妙地编织进本次对话的上下文Prompt中。这一步决定了记忆是否能被“用对地方”、“用对时机”。这个项目的价值不言而喻。对于个人助手它能打造真正懂你的专属AI伙伴对于客服机器人它能提供连贯、个性化的服务体验对于创意协作工具它能成为永不遗忘的灵感素材库。接下来我就把这套从零搭建“AI长期记忆系统”的完整思路、技术选型和踩坑经验毫无保留地分享出来。2. 核心架构与设计思路拆解在动手写代码之前我们必须把架构想清楚。一个健壮的长期记忆系统不能是简单地把聊天记录扔进数据库然后每次对话前把全部历史塞给模型——那样会迅速耗尽宝贵的上下文窗口并且让模型淹没在无关信息里效果反而更差。我的设计目标是低成本、高效率、高准确率。低成本意味着不能过度依赖昂贵的GPT-4等闭源模型进行全量记忆处理高效率要求记忆的存储和检索必须快速不能拖慢对话响应高准确率则要求记住的信息是相关的、有用的并且能被正确召回。2.1 整体架构设计整个系统可以看作一个围绕核心对话流程的“记忆处理流水线”。我设计了一个四层架构交互层用户与AI的直接对话界面。每次用户发送消息除了生成回复还会触发记忆处理流程。记忆处理层核心写入流水线用户消息 - 模型提取 - 程序把关 - 存储至记忆库。读取流水线用户新消息 - 规则召回 - 从记忆库检索相关记忆 - 注入对话上下文。存储层用于持久化保存结构化记忆片段的数据库。这里的选择至关重要它直接关系到检索效率。智能层提供语义理解用于提取和向量化用于检索能力的大语言模型和嵌入模型。这个架构的关键在于记忆的“写入”和“读取”是异步、解耦的。写入流程在后台安静处理不影响主对话的实时性读取流程则在每次对话前快速执行确保上下文的新鲜度。2.2 技术栈选型与考量1. 记忆提取模型轻量化 vs. 重量级方案A重量级直接使用对话的主模型如GPT-4进行提取。优点是提取质量极高能理解复杂语境。缺点是成本高昂每次对话都要额外消耗Token且响应延迟会增加。方案B轻量化使用专门的、参数较小的开源模型如经过指令微调的 Llama 3.2 3B、Qwen2.5 3B 或 Mistral 7B。优点是成本极低可以部署在本地或廉价云服务器专事专办速度也快。我的选择方案B。对于记忆提取这种相对明确的任务识别关键事实、意图、情感轻量化模型完全够用。我最终选择了Qwen2.5-3B-Instruct它在中文理解、指令跟随和效率上取得了很好的平衡可以在消费级显卡上流畅运行。将记忆提取任务与主对话任务分离是控制成本和保证系统响应速度的关键决策。2. 记忆存储与检索关系型 vs. 向量数据库关系型数据库如PostgreSQL, MySQL擅长存储严格结构化的数据通过SQL进行精确查询。但记忆的召回往往基于语义相似度“上海”和“魔都”而非精确匹配这是关系型数据库的短板。向量数据库如Chroma, Weaviate, Qdrant, Pinecone专为存储和检索向量嵌入Embeddings设计。我们可以将每一条记忆文本通过嵌入模型转化为一个高维向量检索时将用户问题也转化为向量然后计算余弦相似度找到最相关的几条记忆。这完美契合了“语义搜索”的需求。我的选择向量数据库。我选择了ChromaDB因为它轻量、开源、易于集成并且提供了简单的本地持久化方案非常适合中小型项目起步。对于生产环境Qdrant或Weaviate在性能和分布式方面更有优势。3. 嵌入模型通用 vs. 领域特定嵌入模型负责将文本转化为向量。它的质量直接决定检索的相关性。通用模型如OpenAI的text-embedding-3-small、text-embedding-ada-002或开源的BGE、Sentence-Transformers系列。它们在不同领域都有不错的表现。我的选择我选择了BGEBAAI/bge-small-zh-v1.5这个开源模型。原因有三第一它对中文优化极好第二模型尺寸小约100MB推理速度快第三开源免费可以本地部署避免了API调用带来的延迟和费用。对于中文场景它是性价比极高的选择。4. 规则引擎硬编码 vs. 可配置“程序把关”和“规则召回”都需要规则。初期我采用硬编码在代码逻辑里但随着规则增多比如“过滤所有问候语”、“合并关于同一主题的多次提及”代码会变得难以维护。我的演进我设计了一个简单的JSON 规则配置文件。例如过滤规则可以写成{“action”: “filter”, “type”: “greeting”, “patterns”: [“你好”, “在吗”, “早上好”]}。召回规则可以定义不同对话意图下应该检索记忆库中的哪些“标签”下的内容。这使得非开发人员如产品经理也能参与规则的调整和优化。3. 核心模块实现细节与实操要点架构确定后我们来深入每个核心模块看看代码具体怎么写有哪些坑要避开。3.1 模型提取从对话中“挖”出金子提取模块的目标是输入一段原始对话文本输出一条或多条结构化的记忆记录。每条记录至少应包含记忆内容核心事实、实体标签如人物、地点、事件、情感倾向可选、重要性分数、时间戳。实现步骤对话预处理合并连续的用户消息或AI消息去除无意义的语气词和重复内容。这一步能减少噪音。构造提取提示词Prompt这是决定提取质量的关键。我的Prompt模板如下你是一个信息提取助手。请从以下用户对话中提取出值得长期记忆的关键事实、用户偏好或重要信息。 要求 1. 只提取客观事实和明确的用户陈述不要提取疑问句或猜测。 2. 用简洁的陈述句概括记忆内容。 3. 为每条记忆标注相关的实体类型如 [人物]、[地点]、[时间]、[偏好]、[健康]、[工作] 等。 4. 评估该条记忆的重要性分数1-55为最重要如过敏信息、长期偏好。 5. 如果对话中不包含值得记忆的信息请输出“无”。 对话内容[此处填入预处理后的对话文本] 请以JSON格式输出格式如下 { memories: [ { content: 记忆内容概括, entities: [实体1, 实体2], importance: 重要性分数, tags: [标签1, 标签2] } ] }注意Prompt的设计需要反复调试。初期我让模型直接输出原始句子结果发现很多记忆冗长且包含无关细节。后来强制要求“用简洁的陈述句概括”效果大幅提升。同时明确要求输出JSON格式便于后续程序解析。调用轻量模型进行推理使用LangChain、LlamaIndex或直接调用模型的API将构造好的Prompt发送给Qwen2.5-3B-Instruct模型获取返回的JSON。结果解析与后处理解析模型返回的JSON。这里一定要做好错误处理模型有时会“胡言乱语”不按格式输出。我的策略是尝试解析JSON如果失败则记录日志并将该条对话标记为“提取失败”等待后续人工复查或采用更保守的规则如只提取包含明确关键词的句子。绝不能因为一条错误的提取导致整个流程崩溃。实操心得批量处理不要每句话都调用一次模型这样延迟太高。可以积累一定轮次如5-10轮对话或一定时间窗口如1分钟内的对话一次性提交给模型进行批量提取能显著提高效率。重要性评分校准模型给出的重要性分数可能不准。我增加了一个后置规则对于包含“过敏”、“密码”、“地址”、“账号”等安全敏感词的记忆自动将重要性提升至5对于包含“喜欢”、“讨厌”、“习惯”等偏好词的重要性不低于4。用规则来弥补模型的不足。3.2 程序把关设立记忆的“海关”提取出的记忆是原始的可能重复、矛盾或价值很低。程序把关模块就像一个严格的海关决定哪些记忆能“入境”存储。核心规则设计去重规则语义去重计算新记忆与记忆库中已有记忆的向量相似度。如果相似度超过阈值如0.9则判定为重复。此时不是简单丢弃而是合并。例如旧记忆“用户喜欢喝咖啡。”新记忆“用户每天早上一杯美式。”可以合并为“用户有喝咖啡的习惯偏好美式通常在早上。”关键词去重对于同一实体如“项目A”如果在短时间内如1小时内出现多条记忆只保留信息量最丰富的一条。过滤规则低重要性过滤重要性分数低于2的记忆直接丢弃例如“今天天气不错”。无关内容过滤通过关键词黑名单过滤掉问候语、告别语、无意义的感叹词等。不确定性过滤对于模型提取出的、包含“可能”、“也许”、“听说”等不确定性词汇的记忆予以降权或过滤。冲突解决规则如果新记忆与旧记忆在事实上冲突例如旧记忆说“用户对猫毛过敏”新记忆说“用户养了一只猫”这是一个危险信号。我的处理策略是优先相信更新的信息但将旧记忆标记为“待核实”并在下次相关对话时尝试引导用户确认例如“您之前提到对猫毛过敏但现在似乎养了猫您的过敏情况是否有变化”。这需要更复杂的逻辑初期可以记录冲突日志人工处理。技术实现 这一部分主要是业务逻辑代码。我使用Python编写核心是一个MemoryGatekeeper类它接收提取出的记忆列表依次应用上述规则最后输出一个“洁净”的记忆列表准备存入向量数据库。class MemoryGatekeeper: def __init__(self, vector_store, similarity_threshold0.9): self.vector_store vector_store # 连接到的向量数据库客户端 self.similarity_threshold similarity_threshold def process(self, new_memories): filtered_memories [] for mem in new_memories: # 规则1: 低重要性过滤 if mem[importance] 2: continue # 规则2: 关键词过滤 (示例) if self._contains_blacklist_words(mem[content]): continue # 规则3: 语义去重与合并 similar_mem self._find_similar_memory(mem[content]) if similar_mem: merged_mem self._merge_memories(similar_mem, mem) # 更新向量库中的旧记忆 self._update_memory_in_store(similar_mem[id], merged_mem) continue # 新记忆已被合并不单独添加 # 通过所有检查加入待存储列表 filtered_memories.append(mem) return filtered_memories def _find_similar_memory(self, content): # 使用嵌入模型将content转化为向量并在向量库中搜索最相似的Top1 # 如果相似度 threshold则返回该记忆否则返回None ...3.3 向量存储与规则召回构建记忆的“索引”与“查询”这是让记忆“活”起来的关键一步。我们需要把过滤后的记忆以及用户的当前问题都转化为向量并通过巧妙的检索策略找到最相关的记忆。1. 记忆的向量化与存储使用我们选定的嵌入模型BGE将每条记忆的content字段转化为一个768维取决于模型的向量。将向量、以及记忆的元数据原始内容、标签、重要性、时间戳一起存入ChromaDB。元数据非常重要它允许我们在进行向量相似度搜索的同时进行元数据过滤。例如我们可以只检索tags包含[偏好]的记忆。2. 召回规则的设计召回不是简单的“把最相似的Top K条记忆找出来”。我们需要更精细的策略策略一基于当前对话意图的召回。首先用一个小型分类模型或关键词匹配判断用户当前消息的意图是“查询信息”、“寻求建议”还是“闲聊”。不同意图下召回的侧重点不同。例如“查询信息”时侧重召回事实类记忆“寻求建议”时侧重召回用户的偏好和历史决策类记忆。这可以通过在检索时添加不同的元数据过滤器来实现。策略二时间衰减加权。记忆是有时效性的。用户三年前说“我喜欢某款手机”和上周说“我喜欢某款手机”权重应该不同。我在计算最终相关性分数时会引入一个时间衰减因子让更近的记忆获得更高的排名。策略三重要性加权。在提取时我们打了重要性分数在召回时也要用上。可以将向量相似度得分与重要性分数进行加权融合确保关键记忆如过敏信息即使语义不是最相关也能在特定场景下被召回。3. 检索的实现class MemoryRetriever: def __init__(self, vector_store, embed_model): self.vector_store vector_store self.embed_model embed_model def retrieve(self, query, intentNone, top_k5): # 1. 将用户查询向量化 query_vector self.embed_model.embed(query) # 2. 构建元数据过滤器 (基于意图) filter_condition None if intent query_fact: filter_condition {tags: {$contains: fact}} elif intent seek_preference: filter_condition {tags: {$contains: preference}} # 3. 执行向量相似度搜索并应用元数据过滤 results self.vector_store.query( query_embeddings[query_vector], n_resultstop_k, wherefilter_condition # ChromaDB的过滤语法 ) # 4. 对结果进行后处理时间衰减、重要性加权 processed_results self._rerank_results(results, query) return processed_results def _rerank_results(self, results, query): final_scores [] for mem, sim_score in zip(results[memories], results[similarities]): # 计算时间衰减因子 (例如指数衰减) time_decay self._calc_time_decay(mem[timestamp]) # 计算加权分数 weighted_score sim_score * 0.7 mem[importance] * 0.2 time_decay * 0.1 final_scores.append((mem, weighted_score)) # 按加权分数重新排序 final_scores.sort(keylambda x: x[1], reverseTrue) return [mem for mem, _ in final_scores[:top_k]]4. 记忆的注入检索到的记忆列表需要被注入到本次对话的提示词中。不能简单拼接否则会干扰模型。标准的做法是在系统提示词System Prompt或用户消息前增加一个专门的“记忆上下文”部分。例如系统指令你是一个有帮助的助手并且拥有以下关于用户的长期记忆 memory_context - 用户对花生严重过敏。重要性5 时间2023-10-01 - 用户住在北京是一名软件工程师。重要性4 时间2023-10-05 - 用户最近在学习和使用Python语言。重要性3 时间2023-10-10 /memory_context 请基于这些记忆和当前对话提供更贴切的回答。 当前用户问题推荐一家附近的餐厅。这样模型就能在生成回复时自然地考虑到用户的过敏史和地理位置。4. 系统集成、调试与效果评估将各个模块串联起来集成到现有的AI聊天应用中并验证其效果是项目从理论走向实践的最后一步也是最容易出问题的一步。4.1 集成模式同步 vs. 异步同步集成在响应用户消息的同一请求链路中顺序执行“记忆召回 - 生成回复 - 记忆提取与存储”。优点是逻辑简单数据强一致。缺点是会显著增加接口响应时间尤其是提取和存储比较耗时时用户体验差。异步集成用户消息到达后主线程立即进行“记忆召回 - 生成回复”并返回。同时将“用户消息和AI回复”作为一个任务放入消息队列如Redis, RabbitMQ。由另一个或多个后台工作线程消费队列执行耗时的“记忆提取与存储”操作。我的选择异步集成。这是保证对话流畅性的关键。我使用Redis作为简单的消息队列。主服务只负责实时对话和记忆召回将需要处理的对话记录推送到Redis的List中。一个独立的Python Worker进程持续从队列中拉取任务调用记忆处理流水线。这样即使用户在密集聊天也不会感到卡顿。4.2 效果评估指标与测试方法如何判断这个记忆系统是好是坏不能只靠感觉需要设计可量化的评估指标。召回准确率人工构造一批测试用例。例如先与AI进行多轮对话注入一些关键记忆如“我女儿叫小花今年5岁”。然后在新的对话中提问相关的问题如“我的孩子多大了”。检查AI的回复是否正确引用了记忆。计算正确召回的比例。记忆相关性对于系统自动提取并存储的记忆进行人工抽样审查。判断这些记忆是否是“值得记住”的干货而不是垃圾信息。可以定义一些标准如“是否包含具体实体或事实”、“是否表达了明确的偏好或意图”。系统性能延迟记忆召回环节增加的延迟应控制在100-200毫秒内。吞吐量后台Worker处理记忆任务的速度能否跟上对话产生的速度避免队列堆积。存储增长记忆库的容量增长是否在预期内。需要设置记忆的自动清理策略例如定期如每月清理重要性低于某个阈值且超过一定时间如半年未被引用的记忆。4.3 常见问题与排查实录在开发和测试过程中我遇到了不少典型问题这里记录下排查思路问题1AI回复开始变得“奇怪”或“自相矛盾”。排查首先检查注入的记忆上下文。很可能是因为召回了过多或不相关的记忆干扰了模型的主任务。例如在讨论编程问题时却注入了大量关于用户饮食偏好的记忆。解决调整召回数量减少top_k参数从默认的5条尝试减少到3条甚至2条。优化召回策略强化基于意图的过滤。确保“闲聊”意图不会召回“工作”标签的记忆。增加相关性阈值在检索时设置一个最低相似度阈值如0.75低于此值的记忆即使排在前列也不注入。问题2记忆提取模块漏掉了重要信息或者提取出错误信息。排查查看提取模型的输入Prompt和输出日志。常见原因有1) Prompt指令不够清晰2) 对话文本过长或格式混乱导致模型理解偏差3) 模型本身能力有限。解决迭代优化Prompt这是最重要的步骤。在Prompt中提供更具体的例子Few-shot Learning明确告诉模型“什么是好记忆”。例如在Prompt里加一段“好的记忆示例{‘content’: ‘用户计划在12月去北海道旅游’ ‘tags’: [‘旅行’ ‘计划’] ‘importance’: 4}”。对话分段处理如果单次对话很长可以尝试按话题或时间将其分割成多个较短的段落分别进行提取然后再合并去重。模型升级如果经过Prompt优化后效果仍不理想考虑使用能力更强的轻量模型如Qwen2.5-7B或者对于极其重要的场景可以谨慎地、按需调用GPT-4等大模型进行二次校验。问题3向量数据库检索速度随着数据量增长而变慢。排查记忆条数超过10万条后简单的全量向量比较会变得很慢。解决使用索引ChromaDB、Qdrant等向量数据库支持建立HNSW或IVF等近似最近邻ANN索引能在大数据量下实现毫秒级检索。确保在初始化集合时正确创建了索引。分库分表可以按用户ID对记忆进行分库每个用户的数据独立存储和检索避免全局搜索。元数据预过滤在计算向量相似度之前先利用元数据如用户ID、标签、时间范围进行一次快速的数据库查询大幅缩小候选集再进行精细的向量检索。问题4用户抱怨AI“记错了”。排查这是最严重的问题。可能是1) 记忆提取时发生了错误概括2) 记忆合并时产生了歧义3) 不同会话间记忆冲突未妥善解决。解决提供记忆查看与修正接口在应用前端为用户提供一个“记忆库管理”页面让他们能看到AI记住了关于他们的哪些信息并允许他们手动删除或修改错误的记忆。这增加了透明度和用户控制感。建立冲突检测与提示机制当系统检测到高度相似但略有矛盾的新旧记忆时如旧记忆“不喜欢香菜”新记忆“点了香菜”可以在下次相关对话中以自然的方式向用户确认“我记得您之前好像不太喜欢香菜您的口味有变化吗” 这既能修正错误也体现了AI的“细心”。引入记忆置信度为每条记忆增加一个置信度字段初始值来自提取时的重要性评分和模型本身的置信度。当用户多次确认或该记忆被频繁成功召回时提升其置信度当记忆被用户手动修改或长期未被使用时降低其置信度。低置信度的记忆在召回时权重降低。5. 进阶优化与未来展望当基础系统跑通后我们可以从“能用”向“好用”、“智能”迈进进行一些进阶优化。5.1 记忆的抽象与泛化目前的记忆是具体的“事实片段”。更高级的记忆系统应该能进行抽象总结。例如从“周一喝了拿铁”、“周三喝了美式”、“周五喝了卡布奇诺”多条具体记忆中可以抽象出一条更高阶的记忆“用户有每周多次饮用咖啡的习惯口味多样”。这种抽象记忆在回答“用户喝咖啡频繁吗”这类概括性问题时更有用。这可以通过定期如每周用一个总结性Prompt让模型对某个标签下的具体记忆进行聚类和概括来实现。5.2 个性化记忆策略不同的用户对记忆的需求和偏好不同。有的用户希望AI记住所有生活细节有的则更注重隐私。我们可以让用户自定义记忆规则记忆开关允许用户完全关闭长期记忆功能。记忆领域让用户选择AI可以记住哪些领域的信息如工作、学习、娱乐屏蔽其他领域如健康、财务。自动清理周期让用户设置记忆的自动保存时长如1个月、1年、永久。5.3 多模态记忆扩展当前的系统只处理文本。但用户的记忆可能包含图片如分享过的宠物照片、文件如上传的工作文档甚至语音消息。未来的扩展方向是将这些多模态信息也纳入记忆体系。例如图片使用多模态大模型如GPT-4V描述图片内容生成文本摘要存入记忆库。文档解析文档内容提取关键知识点、结论或待办事项作为结构化记忆存储。这需要更复杂的提取管道和存储设计可能需要存储文件的索引或向量化后的特征但能极大地丰富记忆的维度。5.4 与知识库的结合长期记忆库关于用户的信息和外部知识库关于世界的信息可以联动。例如当用户提到“我肩膀疼”AI不仅可以从记忆库中召回“用户上周健身过度”还可以从知识库中检索“肩周炎的缓解方法”将两者结合给出更精准的建议“根据您上次健身的情况这可能是肌肉劳损建议您先休息并冷敷可以尝试以下几个拉伸动作...”。构建一个有效的AI长期记忆系统是一个在成本、效果和复杂性之间不断权衡的工程。它没有一劳永逸的银弹需要持续地迭代Prompt、调整规则、优化检索策略。我从一个简单的想法开始通过“模型提取、程序把关、规则召回”这三层架构将其落地过程中最大的体会是让AI拥有记忆本质上是将人的认知管理思维翻译成机器可执行的逻辑与算法。每一次调试都是在对“什么是值得记住的”以及“如何有效地记住和回忆”进行更深入的理解。这个系统目前还在持续优化中但它已经让我的AI助手变得前所未有的“贴心”和“连贯”。如果你也在构建类似的AI应用不妨从这个小而美的记忆模块开始尝试它带来的体验提升将是质的飞跃。