大模型记忆系统架构设计:从向量化检索到个性化对话实践

📅 2026/8/15 3:38:56
大模型记忆系统架构设计:从向量化检索到个性化对话实践
1. 项目概述当大模型需要“记住”用户在AI应用遍地开花的今天大模型对话的“金鱼记忆”问题越来越突出。你跟一个智能客服聊了十分钟它可能还记得你第一句话问的是啥你跟一个内容创作助手反复打磨一篇文章它却常常忘记你十分钟前强调过的核心风格。这种上下文遗忘本质上是当前主流大模型架构的固有局限——它们通常只处理固定长度的上下文窗口超出部分的信息就“消失”了。“记忆系统”就是为了解决这个问题而生的工程组件。它不是一个学术概念而是一套实实在在的、能让大模型应用“记住”用户历史交互、偏好、习惯甚至未完成任务的技术设施。你可以把它想象成给大模型这个“天才健忘症患者”配了一个超级外脑和一位贴身的私人秘书。这个秘书记忆系统负责观察、记录、整理你和模型的所有对话并在你需要的时候精准地从海量记录中找出最相关的信息悄悄递给模型让它能做出更连贯、更个性化的回应。货拉拉作为同城货运的巨头其业务场景对记忆系统的需求尤为强烈。司机和货主在平台上的每一次交互——从询价、议价、约定时间地点到运输中的异常反馈、费用变更——都不是孤立的。一个高效的记忆系统能让智能客服、调度助手甚至风控模型都具备“认人识事”的能力从而提升服务效率与用户体验。今天我们就来深入拆解这套系统中最核心、也最考验工程功力的部分从海量历史数据中“提取”关键记忆并在需要时“召回”它们。2. 记忆系统的核心架构与设计思路一个完整的记忆系统远不止是存和取那么简单。它需要像人脑的记忆机制一样具备编码、存储、巩固、检索和遗忘等多个环节。在工程上我们将其抽象为一个分层、异步的流水线。2.1 整体架构视图我们的记忆系统主要由四个核心模块构成它们协同工作形成一个闭环记忆提取器这是系统的“感官”和“过滤器”。它实时监听用户与模型的所有交互对话流、事件日志等运用规则引擎和轻量级模型从中识别并抽取出值得存储为长期记忆的“记忆点”。比如用户说“我每次发货都喜欢下午因为上午仓库太忙”这里“偏好下午发货”就是一个高价值的记忆点。记忆向量化与存储提取出的记忆点是原始的文本片段。为了高效检索我们需要将其转化为机器更易理解的格式——向量一组高维数字。这个过程通常由嵌入模型完成。转化后的向量连同原始文本、元数据如用户ID、时间戳、记忆类型一起存入专门的向量数据库。向量数据库的优势在于能基于向量相似度进行快速近似检索。记忆召回器当新的用户查询到来时召回器开始工作。它首先将当前查询也向量化然后以该查询向量为“探针”去向量数据库中寻找最相似的K个记忆向量。这个过程就是“召回”目标是尽可能不遗漏任何相关记忆。记忆重排序与注入召回的记忆可能有几十条但大模型的上下文窗口是宝贵的。我们需要一个更精细的“重排序”层对召回结果进行二次打分和排序筛选出最相关、最重要的几条记忆。最后这些记忆会被格式化成特定的提示词如“根据用户历史信息...”注入到大模型的输入上下文中悄然影响其生成结果。这个架构的核心设计思路是“解耦”与“分层”。提取、向量化、召回、重排序每个环节独立发展便于迭代优化。例如我们可以单独升级嵌入模型来提升向量质量而不影响召回逻辑。2.2 为什么是“向量数据库重排序”你可能会问直接用传统数据库如MySQL存文本用关键词匹配如ES来检索不行吗对于记忆系统这通常不够。语义模糊性用户表达是多样的。“下午发货”和“别在上午安排”表达的是同一个偏好。关键词匹配难以捕捉这种语义关联。核心需求是“相似”而非“相同”我们找的是“相关”记忆不一定是包含相同词汇的记忆。向量相似度检索天生为此而生。效率与规模当记忆条目达到百万、千万级时基于向量索引的近似最近邻搜索ANN在速度和资源消耗上远优于复杂的文本匹配计算。而“重排序”是对向量检索“粗召回”的必要补充。向量检索可能因为语义漂移或嵌入模型局限性把一些表面相似但实际无关的记忆排在前列。重排序模型通常是一个轻量的交叉编码器会同时看查询和每一条召回记忆进行更精细的语义匹配打分从而提升最终结果的精准度。3. 记忆提取从对话流中捕捉“黄金片段”记忆提取是记忆系统的源头决定了记忆库的质量。我们的目标不是存下每一句对话那会成为信息垃圾场。我们要存的是浓缩的、结构化的、未来可能被用到的知识。3.1 提取策略规则与模型双驱动我们采用“规则为主模型为辅”的混合策略在保证可控性的前提下逐步提升智能化。基于规则的提取显式声明直接捕捉用户或模型带有明确记忆标记的语句。例如用户说“请记住我公司的发票抬头是XX科技有限公司”。我们可以通过正则表达式或关键词“记住”、“我公司是”、“我的地址是”来触发提取。对话结构分析在客服、导购等场景对话常有固定模式。例如在询价环节用户提供的“货物尺寸”、“重量”、“出发地/目的地”等信息可以通过槽位填充的方式提取为记忆。这是最稳定、可解释性最强的初期方案。基于轻量级模型的提取当规则难以覆盖复杂、隐式的表达时就需要模型上场。我们并不直接使用昂贵的大模型进行实时分析而是训练或微调一个轻量的文本分类或序列标注模型。任务定义可以将提取任务定义为判断“当前句子是否为值得存储的记忆点”二分类或者识别出句子中属于记忆实体的部分命名实体识别如“偏好时间”、“禁忌物品”。数据构建从历史对话日志中由运营或专家标注一批正负样本即可训练一个高效的分类器。这个模型可以识别出“我老婆对猫毛过敏以后叫车千万别派有宠物的司机”这类隐含重要信息的句子。3.2 记忆的结构化与消歧提取出的原始文本需要被加工成结构化的记忆对象以便于后续管理和检索。一个基本的记忆对象可能包含以下字段{ memory_id: uuid, user_id: user_123, content: 偏好下午发货因为上午仓库繁忙, embedding: [0.12, -0.05, ..., 0.78], // 向量表示 type: user_preference, // 记忆类型 entity: {time: afternoon, reason: warehouse_busy}, // 结构化信息 source: dialog_20231027_155302, timestamp: 2023-10-27T15:53:02Z, confidence: 0.92, // 提取置信度 expires_at: 2024-04-27T15:53:02Z // 可选过期时间 }关键点在于“消歧”。比如用户说“苹果”指的是水果、手机公司还是电影这需要结合上下文进行实体链接。我们在提取阶段可以引入一个简单的上下文窗口如前后各两句话利用轻量级NER模型或词典对核心实体进行初步消歧并将结果填入entity字段。这能为后续的向量化和召回提供更丰富的信号。实操心得冷启动与数据飞轮记忆系统启动初期高质量的记忆数据很少。我们的做法是先用严格的规则提取少量高置信度记忆确保记忆库的“纯净度”。同时将模型难以判断的样本低置信度流入一个人工审核队列审核后的结果反哺模型训练。随着系统运行这个“数据飞轮”会越转越快提取能力也越来越强。4. 记忆的向量化与索引构建打造高效的“记忆仓库”提取出的结构化记忆需要通过向量化才能被高效检索。这一步的核心是嵌入模型和向量数据库的选型与优化。4.1 嵌入模型选型与优化嵌入模型负责将文本映射为向量。它的质量直接决定了“记忆相似度”计算是否准确。选型考量通用 vs. 领域像text-embedding-ada-002这样的通用模型开箱即用效果不错。但对于货运垂直领域特定词汇如“厢货”、“平板车”、“搬运费”的语义可能捕捉不佳。理想路径是先用通用模型上线同时收集领域数据后期微调或训练领域专用嵌入模型。多语言支持货拉拉业务可能涉及多语言用户需考虑模型的多语言能力。上下文长度有些记忆内容较长需要嵌入模型支持长文本。性能与成本模型的推理速度、尺寸和API调用成本如果使用云端服务需纳入评估。优化实践指令微调我们发现在微调时给嵌入模型加入简单的指令能显著提升其在记忆检索任务上的表现。例如在训练样本的文本前加上“表示为用于检索的记忆”让模型更好地理解我们的使用场景。混合索引除了对完整的content字段生成向量我们还可以对结构化的entity字段如{time: afternoon}生成向量。在检索时可以尝试融合两种向量的相似度得分或者建立两个独立的向量索引供后续融合召回。4.2 向量数据库的工程实践我们选择了Milvus作为向量数据库。它开源、功能丰富、社区活跃适合大规模向量检索场景。索引类型选择Milvus支持HNSW、IVF_FLAT等多种索引。HNSWHierarchical Navigable Small World因其在召回率和查询速度上的良好平衡成为我们的首选。对于亿级以下的记忆库HNSW能提供毫秒级的检索延迟。M建立图时每个点的连接数和efConstruction索引构建参数影响索引构建速度和精度。我们通过实验在内存允许的情况下适当调高这些参数以换取更高的召回率。efSearch搜索参数则在查询时动态调整平衡搜索速度和召回率。分区与集合设计按用户分区这是最自然的分区策略。将同一用户的所有记忆存储在同一个分区Collection Partition中。这样99%的查询都只需要在一个用户分区内进行极大缩小了搜索范围提升了性能和资源隔离性。按记忆类型分集合如果记忆类型差异很大如“个人偏好”和“订单事实”可以考虑为不同类型建立不同的集合Collection并为每个集合选择最合适的嵌入模型和索引参数。元数据过滤向量检索经常需要结合元数据过滤。例如“召回用户A最近一个月内关于‘价格’类型的记忆”。Milvus支持在向量相似度搜索前/后对标量字段如user_id,type,timestamp进行过滤。我们的经验是对于分区键如user_id这类高筛选度的条件优先用分区剪枝对于其他条件根据其筛选度决定在检索前过滤减少搜索量还是检索后过滤保证召回率。踩坑记录向量维度对齐与版本管理嵌入模型升级意味着向量维度可能改变。直接切换会导致旧向量索引全部失效。我们的解决方案是双写过渡期新模型上线后在一段时间内对每条新记忆用新旧两个模型分别生成向量写入两个不同版本的集合。查询融合查询时同时查询新旧两个集合对召回结果进行去重和融合排序。异步迁移后台任务逐步将旧集合中的向量用新模型重新计算迁移到新集合。建立严格的版本号机制在记忆对象中记录embedding_model_version确保追溯性。5. 记忆召回策略在毫秒间找到“相关记忆”召回环节的目标是“快”和“全”即快速返回尽可能多的相关候选记忆。我们实现了多路召回策略以应对不同的查询场景。5.1 基于向量相似度的主通路召回这是最核心的召回路径。当用户发起一个新对话时使用与记忆库相同的嵌入模型将当前的查询语句或结合了最近几句对话的上下文转化为查询向量。在向量数据库中以该查询向量为中心搜索最相似的K个向量例如K50。这就是初步的召回结果。关键参数K的选择K值不是越大越好。太大会引入更多噪声增加后续重排序的压力太小可能遗漏关键记忆。我们通过AB测试根据“记忆被成功注入并产生正面效果”的比例来动态调整不同场景下的K值。对于常规对话K30是一个不错的起点。5.2 基于元数据与关键词的辅助召回单纯依赖向量检索有时会“跑偏”。因此我们增加了辅助召回通路作为补充和纠偏时间衰减召回用户的近期记忆通常比远古记忆更重要。我们设计了一个时间衰减函数在向量相似度得分的基础上叠加一个基于记忆新鲜度的加分。例如final_score similarity_score alpha * recency_score。这能让一周内的记忆获得更高的排名。关键词增强召回对于包含明确实体如地点“深圳北站”、货物类型“家具”的查询我们会同时使用传统搜索引擎如Elasticsearch对记忆的content和entity字段进行关键词检索。将ES返回的结果与向量召回结果进行融合。类型过滤召回在客服场景如果当前对话被识别为“投诉类”我们可以优先召回“投诉历史”或“解决方案”类型的记忆。5.3 多路召回结果的融合我们采用了“向量召回为主辅助召回为纠偏”的融合策略主通路向量数据库召回Top K条结果得到列表A。辅助通路根据元数据过滤、关键词检索等得到列表B。融合对列表B中的每条记忆计算其与查询的向量相似度如果之前没有然后将其“插入”到列表A的合适位置。插入的规则可以是如果B中某条记忆的相似度高于A中第M位的记忆则将其插入。这里M是一个阈值比如10。这保证了主通路结果的主体地位同时让辅助通路能将有价值但被向量检索遗漏或排后的记忆“提拔”上来。6. 记忆重排序与注入把对的记忆放在对的上下文里召回阶段的结果仍然是粗糙的。重排序的目标是“精”和“准”从几十条候选记忆中筛选出最相关、最关键的3-5条并将其组织成大模型能理解的提示词。6.1 重排序模型的选择与训练我们放弃了使用超大模型进行重排序成本太高而是采用交叉编码器。原理与生成向量用的双编码器如BERT将查询和记忆分别编码为向量再计算相似度不同交叉编码器将查询和记忆文本拼接在一起同时输入模型让模型直接输出一个相关度分数。这种方式能进行更精细的语义交互精度更高但无法像双编码器那样预先计算好记忆向量。训练数据我们从真实的对话日志中构造训练样本。将一次成功的、注入了记忆的对话作为正例随机采样其他不相关的记忆作为负例。让模型学习区分“相关”与“不相关”。模型轻量化我们使用bert-base这类基础模型进行微调并将其蒸馏为更小的模型如 TinyBERT以满足线上服务对低延迟的要求。6.2 重排序的上下文感知重排序模型不能只看孤立的查询和记忆。我们尝试将更丰富的上下文信息融入重排序输入[CLS] 当前查询 [SEP] 候选记忆 [SEP] 最近三轮对话历史 [SEP]这样模型在判断“下午发货”这条记忆是否相关时也能考虑到用户刚刚说过“我明天要发货”从而给出更准确的分数。6.3 记忆的格式化与安全注入经过重排序筛选出的最终记忆列表需要被安全、有效地注入到大模型的提示词中。格式化模板我们设计了一个清晰、无歧义的模板来组织记忆。例如以下是用户的历史相关信息供你在回复时参考 1. [记忆1内容] (来源对话时间1) 2. [记忆2内容] (来源对话时间2)明确标注来源既能提升模型使用的准确性也便于后续可解释性分析。注入位置与长度控制记忆通常被放在系统提示词System Prompt之后用户当前查询之前。必须严格控制注入记忆的总长度确保其与对话历史、当前查询的总和不超过模型上下文窗口并预留足够的空间给模型生成回答。我们会有一个截断策略优先保留重排序分数更高的记忆片段。安全与伦理过滤在注入前记忆内容会经过一个安全过滤器防止任何不当、偏见或敏感信息被传递给模型。同时我们尊重用户隐私对于明确标记为“临时”或“一次性”的记忆不会在后续对话中召回。注意事项记忆的“幻觉”与冲突记忆系统可能召回错误或过时的记忆。更棘手的是可能召回多条相互冲突的记忆如用户上次说“喜欢李师傅”这次说“李师傅开车太晃”。我们的应对策略是置信度与时间加权在重排序分数中融入记忆提取时的置信度和时间衰减因子让高置信、新鲜的记忆排名更靠前。冲突检测与消解在格式化时如果检测到多条记忆在关键实体上冲突可以尝试在提示词中加入一句简短的说明如“请注意用户关于司机偏好的表述可能存在变化”将冲突暴露给大模型让模型基于更全面的上下文自行判断。设置记忆优先级与生命周期为不同类型的记忆设置不同的优先级和过期时间。例如“过敏信息”优先级高、不过期“临时偏好”优先级低、24小时后过期。7. 系统实现、评估与迭代7.1 工程实现要点整个系统我们采用微服务架构核心服务包括记忆提取服务订阅对话消息队列实时处理。向量化与写入服务异步处理提取服务发出的记忆事件调用嵌入模型API写入向量数据库和元数据库。记忆召回与重排序服务提供低延迟的API接收查询返回排序后的记忆列表。记忆管理后台供运营人员查看、搜索、修正或删除用户记忆处理用户的数据权利请求如遗忘权。异步流水线是关键。从对话发生到记忆可用允许有秒级延迟。这让我们可以用批处理的方式调用嵌入模型降低成本也便于在写入前做一些去重、合并的后处理。7.2 如何评估记忆系统的效果记忆系统的好坏不能只看检索本身的指标如召回率、准确率更要看其对上层AI应用效果的提升。离线评估检索指标构建测试集评估记忆召回的Hit RateK前K条结果中至少包含一条相关记忆的概率和MRR平均倒数排名。人工评测采样大量对话由评测员判断系统召回的记忆是否相关、有用以及最终模型的回复是否因记忆而变得更准确、更个性化。在线评估A/B测试核心业务指标在客服场景对比开启/关闭记忆功能的实验组看问题解决率、对话轮次、用户满意度评分是否有显著提升。记忆使用指标监控记忆注入率有多少对话成功注入了记忆、记忆采纳信号能否通过模型回复检测到其确实参考了注入的记忆例如通过特定关键词或逻辑一致性判断。7.3 持续迭代的方向记忆系统是一个需要持续运营和迭代的工程。提取模型持续优化随着标注数据增多不断优化记忆提取模型识别更隐晦、更复杂的记忆点。嵌入模型领域化积累足够的领域对话数据后微调或训练专属的嵌入模型是提升召回效果性价比最高的方式之一。个性化重排序未来的重排序模型可以是个性化的考虑用户的长期行为模式。例如对于经常修改地址的用户“地址”类记忆的权重可以动态调整。记忆的主动应用当前记忆是被动召回的。未来可以探索主动记忆应用例如在用户长时间未使用服务后再次打开App时主动说“根据您的记录您通常在这个时间段需要货运服务是否需要现在下单”。构建一个大模型记忆系统就像为AI打造一个不断成长的外脑。从精准的提取、高效的索引到智能的召回与安全的注入每一个环节都充满了工程上的权衡与挑战。这套系统上线后最直观的感受就是AI对话变得“更懂你”了它开始有了“记忆的温度”。而这一切的背后是一套冷静、理性、持续优化的工程技术体系在支撑。技术的终点始终是更好地服务于人。