
1. 项目概述当大模型需要“记住”用户在货拉拉这样日订单量巨大的同城货运平台每天有海量的用户与司机在交互。想象一下你是一位经常需要搬家或运送大件物品的用户每次打开App都希望系统能记住你的偏好比如你习惯用哪种车型、你常联系的搬家师傅是谁、你上次反馈说某个司机服务特别好。对于司机而言他们也希望平台能记住自己的服务习惯、常跑的路线、以及和哪些老客户合作愉快。这种“记忆”能力是提升用户体验、构建平台粘性的关键。然而传统基于规则或简单标签的用户画像系统在面对大模型驱动的智能客服、智能调度、个性化推荐等场景时显得力不从心。大模型LLM虽然拥有强大的理解和生成能力但其上下文窗口有限且本质上是“无状态”的——它无法记住跨对话、跨会话的长期信息。这就是“大模型记忆系统”要解决的核心问题如何让大模型拥有持续、准确、可用的长期记忆使其能像一位熟悉的老朋友一样与用户互动。货拉拉大模型记忆系统的工程实践正是为了解决这一挑战。它不是一个简单的缓存或数据库而是一套从信息提取、结构化存储、到高效召回的完整技术体系。简单来说它的工作流是从海量的多轮对话、用户行为、订单日志等非结构化数据中智能地“提取”出有价值的记忆点如用户偏好、关键事实、情感倾向将其转化为结构化的“记忆单元”并存储当用户再次发起对话或产生交互时系统能根据当前上下文从庞大的记忆库中精准地“召回”最相关的记忆注入到大模型的提示词中从而让大模型做出更个性化、更连贯的响应。这套系统是AI工程化落地的典型代表它连接了大模型的前沿能力与实际的业务需求其背后的“提取”与“召回”环节充满了工程上的权衡与巧思。接下来我将深入拆解从提取到召回的全链路分享我们在实践中趟过的坑和积累的经验。2. 记忆系统的核心架构与设计思路构建一个大模型记忆系统首先要回答几个关键问题记忆什么怎么存何时用怎么用这直接决定了系统的架构设计。2.1 记忆的范畴与分类并非所有信息都值得被记忆。盲目存储所有对话历史会导致存储爆炸和召回噪音。我们根据业务价值将记忆分为几个核心类别事实性记忆用户明确陈述的、相对稳定的信息。例如“我住在北京朝阳区三元桥”、“我公司经常需要运送打印机耗材”、“我对猫毛过敏”。这类记忆准确性要求最高。偏好性记忆用户通过行为或对话隐含表现出的倾向。例如多次选择“厢式货车”、与特定司机师傅互评五星、在夜间下单频率更高。这类记忆需要从行为中挖掘。情感性/关系性记忆用户对平台、司机或某次服务的情感反馈。例如“上次的李师傅非常细心包装得很结实”、“雨天加价让我不太舒服”。这类记忆对于维护用户关系和提升服务质量至关重要。会话性记忆单次对话中涉及的上下文主要用于保证当前对话的连贯性通常具有较短的生命周期。我们的系统主要聚焦于长期记忆即事实性、偏好性和情感性记忆。这些记忆构成了用户的“数字画像”是提供个性化服务的基础。2.2 整体架构设计整个记忆系统可以抽象为一个经典的“写-存-读”管道但其每个环节都针对大模型的特点进行了特别设计。[数据源] -- [记忆提取器] -- [记忆存储器] -- [记忆召回器] -- [大模型] (对话、行为日志) (LLM 规则) (向量库 图数据库) (检索 重排) (提示词增强)写入路径记忆提取数据源实时对话流、用户行为事件点击、下单、评价、订单详情数据。记忆提取器这是系统的“感官”。它持续监听数据源运用大模型作为理解引擎结合预定义规则判断当前信息是否包含值得长期记忆的内容并将其结构化提取出来。存储层记忆存储记忆库采用混合存储架构。向量数据库用于存储记忆的嵌入式向量核心服务于基于语义相似度的快速召回。我们选用的是Milvus主要看中其在高维向量上的性能和在云原生环境下的成熟度。图数据库用于存储记忆之间的关系。例如“用户A” - [偏好] - “厢式货车”“用户A” - [表扬过] - “司机B”。这有助于实现基于关系的复杂召回如“找到这个用户好评过的司机”。Neo4j是当前的选择。传统数据库/缓存用于存储记忆的元数据创建时间、类型、置信度、来源和原始文本片段提供精确的关键词查询和事务管理。读取路径记忆召回记忆召回器这是系统的“思考”环节。当需要服务用户如智能客服对话时召回器根据当前用户ID和对话上下文生成一个或多个“查询”。检索与重排查询被同时发送到向量库做语义搜索和图数据库做关系查询。初步检索出的记忆候选集会经过一个“重排序”模型综合考虑相关性、新鲜度、置信度等因素选出Top-K条最相关的记忆。提示词组装最终选出的记忆被格式化成自然语言描述作为“上下文”或“系统指令”的一部分注入到大模型的提示词中从而影响其生成结果。设计思路的核心这个架构的核心思想是解耦。提取、存储、召回各司其职通过明确的接口连接。提取层专注于“理解”存储层专注于“组织”召回层专注于“关联”。这样的设计使得每个环节都可以独立优化、迭代和扩展。3. 记忆提取从混沌到结构化的关键一跃记忆提取是整个系统的源头决定了记忆库的质量。垃圾进垃圾出。我们的目标是高精度、高覆盖地捕捉有价值信息。3.1 基于大模型的智能提取最初我们尝试过纯规则的方式正则表达式、关键词匹配但很快发现其局限性无法理解语义、无法处理多样化的表达、召回率低。例如用户说“我住望京”和“公司在望京soho附近”规则很难统一识别出“位置”这个记忆点。因此我们转向了以大模型为判断和抽取核心的方案。具体流程如下触发与过滤并非所有对话流都需经过大模型那样成本太高。我们首先设置一个轻量级规则过滤器过滤掉明显无意义的会话如“你好”、“在吗”或业务确定性高的场景如用户明确选择车型“小面”可直接作为偏好记忆入库。只有通过过滤的文本片段才会进入大模型处理管道。记忆点识别与分类我们将提取任务设计成一个对大模型的指令微调任务。提示词Prompt大致如下你是一个专业的用户信息分析助手。请分析下面的用户对话判断是否包含以下类别的、值得长期记忆的用户信息 - 个人事实如常住地址、公司地址、联系方式、身体状况禁忌 - 服务偏好如对车型、搬运服务、时间的偏好 - 情感反馈如对司机、费用、平台功能的表扬或投诉 - 关系绑定如指定某位司机服务 如果包含请严格按照JSON格式输出包含字段memory_type记忆类型 memory_content记忆内容文本 confidence你的置信度0-1 expiration建议过期时间如“永久”、“30天”。 如果不包含任何值得长期记忆的信息请输出{memory_type: none}。 对话文本[用户输入的实际文本]我们使用货拉拉场景的对话数据对如Llama 3、Qwen等基础模型进行了少量参数的微调LoRA使其更擅长识别货运领域的特定记忆点。结构化与归一化大模型输出的memory_content可能是自然语言如“用户说他住在朝阳区三元桥”。为了便于后续存储和召回我们需要将其归一化为结构化数据。这一步通常结合一个小的文本解析模型或规则。示例对于地址“朝阳区三元桥”我们可能调用内部的地理编码服务将其归一化为标准的{city: “北京” district: “朝阳区” poi: “三元桥”}格式并关联到用户的“常用发货地”属性。对于偏好“喜欢用厢式货车”则映射到用户画像的preferred_vehicle_type: “box_truck”字段。3.2 提取环节的工程实践与挑战挑战一成本与延迟的平衡大模型API调用即使是自研模型有成本和延迟。我们的解决方案是异步批处理非实时性要求的记忆提取如从历史订单评论中挖掘情感记忆采用离线批处理任务夜间运行。模型蒸馏将微调后的大模型教师模型的知识蒸馏到一个更小、更快的模型学生模型上用于线上实时流量的初步筛选只有高不确定性的case才fallback到大模型。缓存策略对频繁出现的、模式固定的记忆点如各种地址表述建立缓存直接匹配避免重复调用模型。挑战二提取的准确性与置信度模型可能会“幻觉”出不存在的记忆或误判。置信度阈值为模型输出的confidence设置阈值如0.7低于阈值的不入库或进入人工审核队列。多源验证对于关键事实如地址尝试与用户档案中的已有信息交叉验证。如果冲突则置信度降低或触发澄清流程例如让智能客服主动询问确认。持续监控与迭代我们构建了一个记忆提取的评估看板定期抽样检查准确率、召回率。将错误案例加入训练集持续迭代微调模型。实操心得Prompt工程比想象中重要在微调模型之前我们在Prompt上花了大量时间。一个清晰的、包含负样本示例的Prompt能极大提升零样本或少样本下的提取效果。例如在Prompt中明确写出“用户说‘今天天气真好’不属于任何记忆类别”能有效减少模型对闲聊内容的误判。4. 记忆存储为高效召回设计的数据组织存储不是目的召回才是。因此存储结构的设计必须服务于后续的检索需求。我们采用了“向量图关系型”的混合存储模式。4.1 向量数据库存储语义的“影子”记忆的文本内容经过嵌入模型Embedding Model转化为高维向量例如768维或1024维。这个向量就是记忆的“语义影子”。嵌入模型选型我们测试了多种开源模型如BGE、text2vec和商用API。最终选择了在中文领域、特别是生活服务类文本上表现稳定的BGE模型并针对货运场景的词汇如“厢货”、“搬运费”、“里程”进行了微调。关键是要保证同一语义的记忆如“我要搬家”和“我有家具需要运输”的向量距离尽可能近。向量库的schema设计在Milvus中一个记忆条目不仅包含向量字段还包含标量字段用于过滤。{ “id”: “memory_123”, “vector”: [0.12, -0.05, …, 0.78], // 嵌入向量 “user_id”: “u_1001”, “memory_type”: “preference”, “content_text”: “用户多次选择厢式货车”, “source”: “order_history”, “timestamp”: 1698765432, “confidence”: 0.95 }user_id和memory_type是后续检索时最重要的过滤条件。我们通常按user_id进行集合分区能大幅提升查询效率。4.2 图数据库刻画记忆的关系网络这是让记忆“活”起来的关键。许多有价值的洞察隐藏在关系里。图模型设计节点用户、司机、车型、地址、物品类别等实体。边关系类型如HAS_PREFERENCE用户-车型、LIVES_IN用户-地址、PRAISED用户-司机、USED_FOR车型-物品类别。应用场景协同过滤式召回当用户A的记忆不足时可以通过图查询“与用户A有相似偏好例如都喜欢用某车型的其他用户还喜欢什么”作为补充记忆。复杂关系查询“给我召回用户上次表扬过的、并且常跑中关村路线的司机”。这种多跳查询用向量检索很难表达用图数据库则非常自然。记忆溯源与解释当一条记忆被召回时我们可以通过图数据库快速找到它的来源哪次对话、哪个订单增强系统的可解释性。4.3 传统数据库可靠的元数据管家PostgreSQL用于存储所有记忆的完整元数据和原始文本。它是向量库和图库的“锚点”提供精确查询通过user_id和memory_type直接拉取某个用户的所有偏好记忆。事务支持记忆的写入、更新、删除需要保证一致性。备份与归档存储完整的、不可变的记忆日志。三者如何协同工作当一条新记忆产生时写入PostgreSQL生成唯一ID。文本内容通过嵌入模型生成向量存入Milvus并关联PostgreSQL的ID。记忆内容被解析出的实体用户、司机、地址等和关系更新到Neo4j中。注意事项数据一致性是个大坑混合存储带来了数据一致性的挑战。我们采用了“异步最终一致性”策略。以PostgreSQL为“主记录”任何记忆的增删改都以PostgreSQL的事务为准。然后通过消息队列如Kafka将变更事件发布出去由消费者异步更新向量库和图库。这意味着在极短时间窗口内三个库的数据可能有细微延迟但对于记忆召回场景这是可接受的权衡。关键是要有完善的数据监控和补偿修复机制。5. 记忆召回在正确的时间送上正确的记忆召回是记忆系统的价值出口。目标是在低延迟通常要求100ms的前提下从海量记忆中精准找出最相关的几条。5.1 召回链路详解一次完整的召回请求通常由某个业务服务如智能客服对话引擎发起参数包括user_id和当前的query用户最新的一句话或对话上下文。查询构造基础查询直接使用当前用户的query作为向量检索的输入文本。例如用户说“还是叫上次那种大车吧”query就是这句话。查询增强为了提升召回率我们会对query进行增强。例如使用大模型对query进行改写或扩展同义词扩展“大车” - “厢式货车 大型货车”或者利用图数据库先查出该用户的常用地址、偏好车型将这些信息拼接到query中形成更丰富的检索文本。多路召回向量检索路将增强后的query转化为向量在Milvus中搜索与该用户相关的通过user_id过滤、且向量距离最近的Top-N条记忆。这是召回的主体负责捕捉语义相似性。图检索路在Neo4j中以当前用户为起点执行图遍历查询。例如“查找该用户所有的PRAISED关系并返回被表扬的司机节点及其属性”。这条路负责捕捉明确的、结构化的关系。关键词检索路备用在某些对确定性要求极高的场景如用户明确说“我住在XX小区”我们会直接用该关键词在PostgreSQL中进行精确或模糊匹配作为兜底。重排序 多路召回会得到一个合并的、较大的候选记忆列表比如50条。直接返回前几条可能不是最优的因为向量检索只考虑了语义相似度忽略了其他重要因素。 我们训练了一个轻量级的重排序模型例如基于Cross-Encoder的BERT小型模型它的任务是对(query, memory)进行打分。这个分数综合了语义相关性模型本身的核心能力。记忆新鲜度越近的记忆通常权重越高。记忆置信度提取时模型给出的置信度。记忆类型优先级事实性记忆可能比情感性记忆在特定场景下更重要。 经过重排序模型重新打分后选出最终的Top-K通常K3~5条记忆。5.2 召回策略的精细化设计不同的业务场景需要不同的记忆召回策略。我们设计了一个可配置的“召回策略引擎”。客服场景优先召回“情感反馈”和“事实性记忆”。当用户表达不满时如果能立刻回忆起“用户上周投诉过运费问题”客服AI就能更体贴地回应。推荐场景优先召回“偏好性记忆”和通过图数据库发现的“协同过滤记忆”。用于推荐车型、增值服务等。调度场景优先召回与地址、时间相关的“事实性记忆”以及用户与司机的“关系绑定”记忆辅助调度系统做更人性化的派单。在策略引擎中我们可以调整各召回路的权重、过滤的记忆类型、重排序模型的特征权重等。这一切都通过配置中心动态管理无需重启服务。5.3 性能优化与缓存之道召回链路的性能至关重要尤其在高并发场景下。向量检索优化Milvus索引的选择HNSW vs. IVF和参数调优是基础。我们根据数据规模和召回延迟要求选择了HNSW因为它适合高召回率、低延迟的场景。同时严格按user_id分区将搜索范围缩小到单个用户的数据子集这是最大的性能提升点。多级缓存L1缓存本地缓存使用Guava Cache或Caffeine缓存单个用户最近被召回的高频记忆如常用地址。过期时间较短如5分钟。L2缓存分布式缓存使用Redis缓存经过重排序后的、用户维度的最终记忆集合。Key设计为user:memory:{user_id}:{scene}过期时间根据场景设定客服场景短推荐场景可稍长。缓存更新当系统写入一条新的高置信度记忆时会主动失效该用户相关的缓存确保下次召回能获取到最新记忆。异步预加载对于即将进入可能使用记忆场景的用户例如用户打开客服页面可以提前异步触发一次轻量级的记忆召回将结果预热到缓存中从而在用户真正发起对话时实现“零等待”。实操心得重排序模型不必复杂但数据要准我们最初尝试用非常复杂的模型做重排序效果提升并不明显反而延迟增加。后来发现关键在于训练重排序模型所用的(query, memory, relevance_score)数据对要高质量。我们通过大量业务人员标注并结合线上点击、转化数据作为反馈信号构建了高质量的训练集。一个在小而精的数据集上训练的简单Cross-Encoder模型其效果远好于在嘈杂数据上训练的大模型。6. 工程实践中的挑战与解决方案在构建和迭代这套系统的过程中我们遇到了无数坑以下是几个最具代表性的挑战及我们的应对之策。6.1 记忆冲突与消解用户可能在不同时间说出矛盾的信息。例如3月说“我住望京”6月说“我搬去通州了”。系统里就会存在两条矛盾的“常住地址”记忆。我们的解决方案置信度与时间加权每条记忆都有置信度和时间戳。在召回时对于同一类型的记忆我们会进行聚合。例如地址记忆优先选择置信度高且更新的。也可以设计一个衰减函数让旧记忆的权重随时间下降。显式记忆优先用户明确说“我搬家了新地址是XXX”产生的记忆其权重远高于系统从对话中推测出的地址记忆。主动澄清机制当系统检测到高置信度的新记忆与旧记忆直接冲突且旧记忆近期被使用过可以触发一个主动澄清。例如让智能客服在对话中自然地问一句“对了看到您之前提过住望京现在主要发货地址还是那里吗” 用户的回答会产生一条更高置信度的新记忆并标记旧记忆为“已覆盖”。6.2 记忆的“保鲜”与遗忘不是所有记忆都值得永久保存。用户的偏好会变过时的记忆会产生干扰。我们的解决方案显式过期时间在提取阶段模型或规则可以预测记忆的“保质期”。例如“对某个司机的表扬”可能设置半年过期“手机号”可能设置永久。隐式衰减与淘汰我们为每条记忆设计了一个“能量值”。每次该记忆被成功召回并得到用户正面交互如用户确认、订单成交能量值增加长时间未被使用能量值缓慢衰减。系统有一个后台任务定期清理能量值低于阈值的记忆或将其归档到冷存储。场景化记忆生命周期不同场景记忆生命周期不同。客服会话的上下文记忆对话结束即失效用户偏好记忆则长期保留但会衰减。6.3 系统可观测性与调试记忆系统是个“黑盒”如何知道它工作得好不好为什么这次召回了这条记忆我们的解决方案全链路日志与Trace为每一次记忆的提取、存储、召回请求分配唯一的Trace ID。记录下关键决策点的信息提取时的原始文本、模型输出、置信度召回时的查询语句、各召回路的结果、重排序分数等。这便于问题追踪和复盘。记忆效果评估看板我们定义了多个业务指标记忆利用率被召回的记忆中有多少比例最终被用于大模型生成并影响了用户交互记忆准确率抽样检查被系统标记的记忆是否真实准确业务指标提升使用记忆系统后客服解决率、用户满意度、推荐点击率等核心业务指标是否有提升我们通过A/B测试来严格衡量。记忆沙盒与调试工具我们开发了一个内部工具允许产品经理和工程师输入一个用户ID和模拟对话实时查看系统会提取出什么记忆以及召回链条的完整过程。这对于理解系统行为和调试策略至关重要。6.4 安全与隐私考量记忆系统涉及大量用户数据安全和隐私是红线。数据脱敏在记忆提取后、存储前对敏感信息手机号、身份证号、详细地址门牌号进行严格的脱敏处理。存储的是脱敏后的信息仅在必要的、有严格权限控制的下游服务中才通过令牌化的方式换取真实信息。用户控制提供用户隐私中心让用户可以查看、管理甚至删除平台关于自己的“记忆”。这是合规要求也是建立信任的关键。访问审计所有对记忆库的读写操作都有完整的审计日志确保可追溯。7. 未来演进方向目前这套系统已经稳定服务了货拉拉多个核心场景但技术演进永无止境。我们正在探索以下几个方向记忆的主动应用与触发当前的记忆召回是被动的基于用户当前query。未来我们希望系统能更“主动”例如检测到用户频繁在雨天叫车可以主动推送“雨天用车注意事项”或相关优惠根据用户过去的投诉记忆在类似场景出现风险时提前预警给客服。多模态记忆当前的记忆主要是文本。未来用户上传的货物图片识别出是易碎品、沟通时的语音语调识别出焦急情绪都可以作为多模态记忆存储和召回让记忆更立体。记忆的推理与合成系统不应只是记忆的“复读机”。我们希望它能对记忆进行简单的推理。例如从“用户表扬了李师傅的搬运技术”和“用户抱怨王师傅搬运有磕碰”这两条记忆中可以合成出一条更高阶的“用户非常看重搬运过程中的物品保护”的偏好记忆。这需要更复杂的图神经网络或大模型推理能力。更轻量、更廉价的架构向量数据库和图数据库的运维成本不低。我们正在评估新一代的、支持混合检索的一体化数据库以及通过量化、剪枝等技术压缩嵌入模型和重排序模型在保证效果的同时进一步降低成本。构建大模型记忆系统就像为AI打造一个不断成长的“数字大脑”。从精准的提取到智能的召回每一步都充满了工程上的挑战与乐趣。这套系统没有银弹必须紧密结合自身业务场景从简单版本开始通过持续的数据飞轮和算法迭代逐步演化成熟。希望我们在货拉拉的这些实践能为你带来一些启发。