1. 项目概述为什么我们放弃了知识图谱方案最近在AI智能体Agent的圈子里关于“记忆”的讨论热度一直居高不下。每隔几天你就能看到一个新的“记忆层”方案冒出来宣称能解决智能体健忘、上下文窗口有限的问题。作为一名长期在AI应用层摸爬滚打的开发者我和团队在构建我们自己的智能体平台Vektori时也深入研究了这个问题。我们发现市面上绝大多数方案都走向了同一条路将对话历史压缩成知识图谱Knowledge Graph。这听起来很酷对吧把非结构化的对话变成结构化的实体和关系网络似乎是一种优雅的“理解”和“记忆”方式。但经过一番实践和踩坑后我们得出了一个可能有些反直觉的结论对于动态、开放域的智能体对话记忆基于知识图谱的压缩方案本质上是一种“有损压缩”而且是在信息摄入阶段就做出的、不可逆的决策。这就像你在整理一个装满各种零碎物件的工具箱为了放进一个整齐的、有固定格子的收纳盒你不得不提前决定哪些螺丝刀、哪些扳手是“重要”的然后把那些形状不规则、或者你觉得暂时用不上的小零件直接扔掉。问题是你永远无法预知下一次维修任务具体需要哪个不起眼的小垫片。这正是我们在Vektori项目中遇到的困境。我们最初也尝试了图谱路线但很快发现为了将对话“塞”进预设的图谱模式Schema大量细微的上下文、语气、未明确表述的意图以及那些暂时看不出关联性的“边缘信息”都被丢弃了。这种“记忆”是僵化的它基于我们开发者对“什么信息重要”的假设而非智能体在后续交互中真实、动态的需求。因此我们彻底转向了一个不同的架构思路并决定将其开源。今天我就来详细拆解我们为什么“弃坑”知识图谱以及我们设计的“三层记忆”架构是如何工作的。2. 知识图谱作为记忆层的核心缺陷剖析在深入我们的方案之前有必要先彻底理解为什么主流的知识图谱KG方法在智能体记忆这个场景下会“水土不服”。这不仅仅是技术选型问题更是对智能体交互本质的理解偏差。2.1 “有损压缩”的不可逆性知识图谱构建的核心流程可以概括为信息抽取 - 实体/关系识别 - 图谱构建与存储。当应用于对话历史时这个流程的致命弱点在于其前置的、不可逆的决策点。假设一次用户与智能体的对话涉及购买一台笔记本电脑。信息抽取模型可能会识别出实体“用户”、“笔记本电脑”、“品牌A”、“预算8000元”、“编程用途”。关系可能是“用户-询问-笔记本电脑”、“笔记本电脑-品牌是-品牌A”、“用户-有预算-8000元”、“笔记本电脑-用于-编程”。这个过程已经发生了信息丢失上下文丢失用户可能说“我主要用来写Python和跑一些轻量级数据模型偶尔也剪剪视频”。图谱可能只留下“编程用途”而“轻量级数据模型”和“偶尔剪视频”这两个对平衡CPU、GPU、内存至关重要的限定词很可能因为不符合预设的“用途”关系模式而被忽略或者被模糊地归为“多媒体处理”。否定与不确定性丢失用户说“我不太喜欢品牌B的售后”。这句话在知识图谱中极难有效表达。它可能被完全丢弃或者被错误地简化为一个负面的“喜欢”关系但“不太喜欢”的程度和“售后”这个具体原因这些细微差别都消失了。时序与过程信息丢失对话是动态的。用户可能先问“品牌A的X型号如何”然后基于回答又问“那和品牌C的Y型号比呢”。图谱通常只记录最终状态用户考虑了品牌A和C但丢失了决策的思考路径先关注A再对比C。这对于理解用户偏好至关重要。关键在于在“摄入”Ingestion阶段我们就必须用一个固定的“模式之网”Schema去过滤流动的、开放的对话信息流。我们提前决定了“实体类型”人、组织、产品和“关系类型”购买、询问、属于的范畴。任何无法被这个模式捕获的信息在那一刻就被判定为“噪声”并丢弃。然而智能体在未来任务中需要回溯的很可能就是这些被丢弃的“噪声”。2.2 模式僵化与查询的局限性知识图谱的优势在于对已知模式的复杂查询例如“找出所有用户询问过的、用于编程且预算在5000-10000元的笔记本电脑品牌”。这建立在两个前提上1) 我们提前知道会关心“用途”和“预算”这类属性2) 这些属性已被正确、一致地抽取和填充。但在开放域的智能体对话中用户的需求天马行空。今天讨论编程电脑明天可能问旅游攻略后天聊哲学问题。为所有可能的话题预先定义一套完整的模式是不现实的。即使采用动态模式或开放信息抽取其抽取结果也是不稳定、不完整的并且依然受限于抽取模型本身的能力偏见。更关键的是智能体的记忆查询往往是模糊的、基于语义的、甚至是指代性的。用户可能会说“还记得我之前跟你提过的那台电脑吗你当时说它的显卡有点问题。” 这里的“那台电脑”和“有点问题”是强烈的上下文指代。基于图谱的查询需要先将这个自然语言问题解析成图谱查询语言如Cypher, SPARQL这本身就是一个NLP难题并且严重依赖于之前抽取的实体链接是否准确。如果当初“显卡有点问题”这个评论因为过于模糊未被抽取为结构化关系那么这次查询就会失败。实操心得模式定义的陷阱我们在早期尝试中曾为“产品推荐”场景精心设计了一个包含数十个实体和关系的模式。最初几天效果似乎不错直到用户开始和智能体闲聊起产品的颜色、手感、甚至包装盒设计。这些信息全部落入“其他”类别或直接丢失。当我们试图扩展模式来容纳“颜色”和“手感”时又发现不同品类的产品属性差异巨大手机的手感和沙发的手感完全不是一回事导致模式迅速膨胀且难以维护。我们意识到试图用一个静态的“模式篮子”去装下所有对话的“信息活水”是注定徒劳的。3. Vektori的三层记忆架构设计哲学基于对上述缺陷的深刻认识我们为Vektori设计了全新的记忆架构。其核心哲学是放弃在摄入阶段进行不可逆的、有损的结构化压缩转而采用一种“分层存储、按需回溯”的策略将原始信息作为记忆的“基石”完整保留。我们的架构包含三个层次自底向上分别是3.1 L2原始语句层——记忆的“源代码”这是整个架构的基石也是最关键的不同点。我们永久保存每一轮对话的原始文本Raw Sentences不做任何删除或概括。这些文本按会话Session和时序索引存储。你可以把它想象成数据库的“Write-Ahead Log”或源代码管理的完整提交历史。作用提供绝对的、无损的信息保真度。当需要验证一个事实、追溯一个观点的原始语境、或者理解一个模糊指代时L2是最终的权威来源。存储与开销是的这需要存储空间。但在云存储成本极低的今天文本数据的存储开销对于绝大多数应用而言是可接受的。更重要的是L2数据在常规查询中默认不加载它只在需要深度追溯时才被触发访问因此对日常查询性能几乎没有影响。设计考量我们为每条原始语句附加了丰富的元数据包括会话ID、时间戳、说话者用户/智能体、以及在前端渲染所需的定位信息。这确保了回溯时的精准定位。3.2 L1事件片段层——自动发现的“故事单元”如果说L2是连续的“数据流”那么L1就是从中自动识别出的、有意义的“段落”或“章节”。我们称之为“事件片段”Episodes。一个事件片段可能是一次完整的产品查询、一个故障排查过程、一段偏好的讨论。如何生成我们不依赖人工预定义的模式。而是采用无监督或自监督的对话分割与聚类算法结合语义相似度自动将连续的对话流切分并聚合到不同的事件片段中。例如连续多轮关于“选择笔记本电脑”的对话会被归入同一个“笔记本电脑选购”事件片段。优势动态性模式是自动从数据中发现的而非强加的。它能适应新的话题和对话风格。保真性事件片段本身可以包含指向L2原始语句的指针集合或者存储经过轻度、可逆的概括如生成一个摘要但核心是它保持了对话片段的连贯语义单元。高效检索相比在海量原始语句中搜索在数量少得多的“事件片段”层面进行语义检索效率要高得多。这构成了我们记忆系统的“主索引”。3.3 L0提取事实层——高频访问的“缓存”这是最上层也是访问速度最快的层面。它包含了从对话中提取出的、经过高质量过滤的确定性事实Extracted Facts。例如“用户偏好16GB内存”、“用户预算上限为8000元”、“用户排除了品牌B”。与知识图谱的区别关键区别在于L0的事实是扁平化、去模式化的。我们不强制要求它们构成一个连通的图。它们更像是一个个独立的“断言”Assertions或“键值对”附带置信度和来源指向L1和L2。查询时我们进行的是高效的向量相似度搜索或关键词搜索。作用服务于对延迟极度敏感的、简单的事实性问答。比如用户问“我的预算是多少”系统可以直接从L0层快速返回“8000元”而无需回溯整个对话历史。质量过滤并非所有提取的事实都会进入L0。我们通过一个质量过滤层只保留高置信度、高确定性的信息避免将模型的猜测或模糊表述作为事实存储。三层之间的关系L2是地基完整保存一切。L1是基于L2内容自动构建的语义索引层。L0是从L1/L2中蒸馏出的高价值信息缓存。当智能体需要记忆时查询首先快速扫描L0如果不够则深入L1进行语义搜索相关事件片段如果需要核实或获取完整上下文则最终定位到L2的原始语句。图谱结构如果我们需要可以构建在L1或L0之上作为特定视图而不是取代它们。4. 架构实现与核心环节解析理解了设计哲学我们来看看具体如何实现这个三层架构。这里会涉及一些工程上的关键决策。4.1 数据存储方案选型存储设计必须满足分层、高效检索和成本可控的要求。L2原始语句存储选择对象存储如AWS S3、MinIO或高性能的文档数据库如MongoDB。理由L2数据量大但访问模式是“低频、大批量读取”按会话读取或“极低频、单点读取”追溯某句话。对象存储成本极低且吞吐量高非常适合这种场景。我们按{session_id}/{turn_index}.txt的格式存储原始文本和元数据JSON格式。文档数据库则提供了更灵活的查询能力如按时间范围、说话者过滤适合对回溯查询有更复杂需求的场景。实操配置示例伪代码# 存储原始语句 def save_raw_turn(session_id, turn_index, speaker, text): object_key fsessions/{session_id}/{turn_index:06d}.json data { text: text, speaker: speaker, timestamp: time.time(), session_id: session_id, turn_index: turn_index } s3_client.put_object(BucketRAW_BUCKET, Keyobject_key, Bodyjson.dumps(data))L1事件片段存储选择向量数据库如Pinecone, Weaviate, Qdrant结合元数据数据库如PostgreSQL。理由L1的核心操作是基于语义的相似性搜索。向量数据库为此进行了优化。我们将每个事件片段的语义摘要或关键语句编码成向量Embedding存入向量库。同时在PostgreSQL中存储该片段的元数据唯一ID、所属会话、起止轮次指针、创建时间、以及指向L2原始语句的指针列表。索引策略向量索引我们选择HNSWHierarchical Navigable Small World它在精度和召回率之间取得了很好的平衡且支持动态增量插入非常适合对话这种流式数据。L0提取事实存储选择内存缓存如Redis 向量数据库/关系型数据库。理由L0要求极快的读取速度。我们将最热、最确定的事实例如用户姓名、当前核心任务目标放在Redis中。更多的事实则存储在向量数据库用于语义搜索如“和预算相关的事实”或关系型数据库用于精确键值查询如“user_preference_budget: 8000”中。定期根据访问频率和新鲜度更新缓存。4.2 事件片段的自动发现算法这是L1层的核心技术。我们的目标是无需人工标注自动从对话流中切分并聚类出有意义的事件片段。切分Segmentation方法结合多种信号。语义转折计算相邻对话轮次之间的语义向量余弦相似度。如果相似度低于某个自适应阈值则可能是一个话题边界。时间间隔长时间停顿可能表示一个话题的结束。对话行为识别用户或智能体的“重启性”话语如“好了我们换个话题”、“再问一下...”、“另外...”。实现我们采用一个轻量级模型如基于BERT的句子编码器计算每轮对话的向量然后通过一个滑动窗口计算局部相似度变化结合规则进行切分。聚类Clustering与片段形成方法在线聚类算法。流程当一个新的对话轮次或一个小片段产生后计算其语义向量并与现有的所有事件片段的核心向量进行相似度比较。如果与某个现有片段的相似度高于阈值则将其归入该片段并更新该片段的核心向量如取均值。否则创建一个新的事件片段。关键参数相似度阈值需要动态调整。我们根据片段内对话的紧密程度内部相似度方差来微调该阈值避免片段过大或过小。注意事项处理模糊边界对话话题的转换常常是渐进的而非一刀切。我们的算法会允许一个对话轮次以一定概率属于多个片段软聚类并在元数据中记录这种关联强度。这在处理“承上启下”的对话时非常有用。4.3 查询路由与信息融合当智能体需要“回忆”时例如处理用户输入“像我之前说的...”记忆系统按以下流程工作查询解析首先解析当前用户查询和对话上下文生成一个搜索查询向量和一组关键词。L0快速查找用关键词在L0的事实缓存中进行精确匹配和向量相似度搜索。如果找到高置信度、完全匹配的答案如“预算8000”直接返回。L1语义搜索如果L0结果不充分使用查询向量在L1的向量数据库中搜索最相关的K个事件片段例如K3。上下文获取与融合从向量数据库返回的片段ID到元数据库中找到对应的起止轮次指针。根据指针从L2存储中读取对应的原始对话文本。将L0的事实、L1的片段摘要/关键句、以及L2的原始文本片段一起组合成一份丰富的“记忆上下文”。提供给智能体将这份融合了多层次信息的上下文作为系统提示System Prompt的一部分注入给大语言模型LLM由LLM来最终理解和利用这些记忆进行回复。这种“路由-融合”机制确保了智能体既能快速获取高度提炼的事实又能根据需要深入到最原始的对话细节中实现了效率与保真度的平衡。5. 性能基准与效果评估理论再好也需要数据验证。我们设计了一套评估体系并与典型的基于知识图谱的记忆方法进行了对比。5.1 评估数据集与指标我们采用了公开的智能体长期记忆评估基准例如LongMemEval数据集。这个数据集包含多轮、多话题的扩展对话并在后续对话中设置了需要依赖长期记忆才能正确回答的问题。核心指标记忆召回率Memory Recall智能体能否正确回忆起之前对话中提及的事实、观点或承诺。上下文保真度Context Fidelity当需要追溯时智能体提供的细节是否准确有无扭曲或混淆。查询延迟Query Latency从触发记忆查询到获得记忆上下文的时间特别是P95和P99延迟。存储开销Storage Overhead记忆系统占用的磁盘/内存空间。5.2 Vektori架构的基准测试结果在我们的内部测试和针对LongMemEval-S数据集的评估中我们的三层架构表现如下记忆召回率达到了73%的综合得分。这是一个显著的提升。分析发现提升主要来自两个方面对模糊指代和隐含信息的处理当问题涉及“你之前提到的那个有点贵但性能好的选项”时基于图谱的系统往往失败因为“有点贵但性能好”很难被预先抽取为结构化属性。而我们的系统通过L1的语义搜索能找到相关事件片段并通过L2原始文本确认具体指代。对否定和条件信息的保留用户说“如果超过9000我就不考虑了”。图谱可能只记录“预算9000”而丢失了“超过...就不考虑”这个条件逻辑。我们的原始文本层完整保留了这一信息。上下文保真度在需要提供引用或细节的问题上我们的系统能够精确指向原始对话的轮次和语句而基于图谱的系统通常只能提供抽取后的“事实”无法追溯到具体表述有时甚至会因抽取错误而提供失真信息。性能与开销查询延迟得益于L0缓存对于简单事实查询延迟与图谱方案相当毫秒级。对于复杂的语义查询由于L1层向量检索的高效性整体延迟仍控制在可接受范围百毫秒级且P99延迟更稳定因为避免了复杂图谱查询可能出现的性能抖动。存储开销L2原始文本存储使总存储空间比纯图谱方案增加了约2-5倍取决于对话长度和压缩率。然而考虑到文本存储的廉价性以及L2数据冷存储的成本总拥有成本TCO的增加远低于性能收益。L1和L0的存储开销与图谱方案处于同一量级。5.3 与知识图谱方案的对比分析我们将两种方案的核心差异总结如下表特性维度传统知识图谱记忆方案Vektori 三层记忆架构信息摄入有损、不可逆压缩。依赖预设模式丢弃模式外信息。无损存储。原始对话完整保留L2。结构化/提取是后续的、可逆的视图。记忆保真度低。信息被抽象和简化丢失细节、语境和模糊表述。高。可通过L2追溯到任何一句话的原始语境信息零失真。模式灵活性低。需要预先定义或不断扩展模式难以适应开放域对话。高。L1事件片段自动发现无需预定义模式。可适应任意新话题。查询能力擅长对已知模式的复杂关系查询。不擅长处理模糊语义、指代和自然语言问题。擅长语义相似性搜索和精确原文回溯。更贴合人类自然提问方式。实现复杂度高。需要维护图谱模式、实体链接、关系抽取管道以及图数据库。中。核心是向量检索和文本存储技术栈更现代、更统一。适用场景领域高度固定、数据结构化明确的场景如企业知识库、特定产品客服。开放域、动态性强的智能体对话需求不可预知需要高保真记忆。6. 常见问题、挑战与实战调优在实际部署和开发Vektori的过程中我们遇到了不少挑战也积累了一些调优经验。6.1 如何处理超长对话和存储膨胀这是最常被问到的问题。完整保存所有原始对话会不会最终拖垮系统分层存储与生命周期管理我们对L2数据实施生命周期策略。例如热数据最近7天的会话原始数据存储在高速存储如SSB上。温数据7天前至90天内的数据转移到成本更低的标准对象存储。冷数据90天前的数据可以进行压缩归档甚至转移到冰川存储。当需要追溯时虽然有一定延迟但仍可获取。关键点即使转移到冷存储数据依然存在未被删除。这与图谱方案丢弃信息有本质区别。事件片段的归纳与摘要L1层的事件片段并非一成不变。对于非常古老或庞大的片段可以运行一个后台任务用LLM生成一个更精炼的摘要同时保留指向关键原始语句的指针。这样可以在不丢失溯源能力的前提下压缩L1层的存储和检索负担。选择性保存在极端情况下可以对L2数据实施基于策略的清理。例如只永久保存标记为“重要”的会话或用户明确要求保存的会话。但这需要谨慎因为“重要性”难以自动判断。6.2 向量搜索的“语义漂移”问题L1层依赖向量相似度搜索如果编码模型Embedding Model不够好或者对话话题非常发散可能导致搜索不准确。混合检索Hybrid Search我们不单纯依赖向量搜索。采用“向量搜索 关键词搜索BM25”的混合模式。首先进行向量搜索得到语义相关候选集再用关键词搜索进行重排序Re-ranking。这结合了语义匹配和精确词汇匹配的优点显著提高了召回率和准确率。查询扩展Query Expansion在将用户查询转换为搜索向量前先用LLM对查询进行小幅重写或扩展生成多个同义或相关的查询表述分别进行搜索后再合并结果。这有助于捕捉查询的不同侧面。领域自适应微调如果应用场景垂直如医疗、法律可以考虑用领域内的对话数据对开源的Embedding模型如BGE, text-embedding-3进行微调使其在该领域的语义空间更准确。6.3 事实提取L0的准确性与一致性问题从对话中自动提取高确定性事实本身就是一个难题提取错误会导致L0缓存污染。高阈值与人工验证回路我们为事实提取模型设置非常高的置信度阈值例如0.95。只有模型极其确定的事实才会进入L0。同时系统提供界面允许人工审核和修正被提取的事实这些修正会反馈给模型进行持续优化。多模型投票对于关键事实如价格、日期、关键决策采用多个不同的提取模型基于规则、基于微调LLM、基于Prompt的通用LLM进行提取取它们的共识结果可以大幅降低错误率。事实溯源L0中存储的每一条事实都必须明确记录其来源指向L2的具体语句。当智能体引用该事实时可以附带来源增加可信度也便于在发现错误时进行溯源和修正。6.4 系统整体复杂性带来的运维挑战三层架构听起来比单一图谱方案更复杂。清晰的接口抽象我们为记忆系统设计了简洁清晰的API例如recall(context, query)和memorize(session_id, dialogue_turn)。内部的三层实现细节对上层应用透明。这降低了使用和集成的复杂度。可观测性Observability我们在系统的关键路径埋点监控每一层的缓存命中率、查询延迟、存储增长、事实提取准确率等指标。通过仪表盘可以清晰了解系统状态快速定位瓶颈。渐进式采用对于资源有限或场景简单的团队不一定需要完整实现三层。可以从L2 L1开始放弃L0缓存用向量搜索直接服务所有查询。或者从L1 L0开始只保存片段摘要放弃无限期的原始文本存储L2直到确有需要。放弃知识图谱作为智能体记忆的“银弹”转向一个以原始信息为基石、分层索引的架构对我们来说不是一个轻易的决定而是一次被实际问题“逼”出来的架构演进。这个方案承认了对话的复杂性和不可预测性不再试图用一把固定的“结构之梳”去梳理所有信息流而是选择“全量保存智能索引”。它带来的最大改变是心理上的解放我们不再需要为“该记住什么、该扔掉什么”而焦虑。所有决策都可以推迟到查询发生时基于当时最完整的信息来做。这使智能体的记忆行为更贴近人类——我们并非只记住结构化的事实而是保留着鲜活的经历片段并在需要时从中提取和重构信息。如果你也在构建需要长期记忆的AI智能体并且受困于图谱方案的僵化或信息丢失我强烈建议你重新思考存储与检索的范式。我们的代码和设计已在GitHub上开源Vektori它可能不是所有场景的最优解但它为我们打开了一扇新的门。至少在下次看到又一个“革命性”的智能体记忆方案时你可以多问一句它在摄入阶段扔掉了什么
AI智能体记忆架构演进:放弃知识图谱,转向三层无损存储方案
发布时间:2026/5/26 8:51:32
1. 项目概述为什么我们放弃了知识图谱方案最近在AI智能体Agent的圈子里关于“记忆”的讨论热度一直居高不下。每隔几天你就能看到一个新的“记忆层”方案冒出来宣称能解决智能体健忘、上下文窗口有限的问题。作为一名长期在AI应用层摸爬滚打的开发者我和团队在构建我们自己的智能体平台Vektori时也深入研究了这个问题。我们发现市面上绝大多数方案都走向了同一条路将对话历史压缩成知识图谱Knowledge Graph。这听起来很酷对吧把非结构化的对话变成结构化的实体和关系网络似乎是一种优雅的“理解”和“记忆”方式。但经过一番实践和踩坑后我们得出了一个可能有些反直觉的结论对于动态、开放域的智能体对话记忆基于知识图谱的压缩方案本质上是一种“有损压缩”而且是在信息摄入阶段就做出的、不可逆的决策。这就像你在整理一个装满各种零碎物件的工具箱为了放进一个整齐的、有固定格子的收纳盒你不得不提前决定哪些螺丝刀、哪些扳手是“重要”的然后把那些形状不规则、或者你觉得暂时用不上的小零件直接扔掉。问题是你永远无法预知下一次维修任务具体需要哪个不起眼的小垫片。这正是我们在Vektori项目中遇到的困境。我们最初也尝试了图谱路线但很快发现为了将对话“塞”进预设的图谱模式Schema大量细微的上下文、语气、未明确表述的意图以及那些暂时看不出关联性的“边缘信息”都被丢弃了。这种“记忆”是僵化的它基于我们开发者对“什么信息重要”的假设而非智能体在后续交互中真实、动态的需求。因此我们彻底转向了一个不同的架构思路并决定将其开源。今天我就来详细拆解我们为什么“弃坑”知识图谱以及我们设计的“三层记忆”架构是如何工作的。2. 知识图谱作为记忆层的核心缺陷剖析在深入我们的方案之前有必要先彻底理解为什么主流的知识图谱KG方法在智能体记忆这个场景下会“水土不服”。这不仅仅是技术选型问题更是对智能体交互本质的理解偏差。2.1 “有损压缩”的不可逆性知识图谱构建的核心流程可以概括为信息抽取 - 实体/关系识别 - 图谱构建与存储。当应用于对话历史时这个流程的致命弱点在于其前置的、不可逆的决策点。假设一次用户与智能体的对话涉及购买一台笔记本电脑。信息抽取模型可能会识别出实体“用户”、“笔记本电脑”、“品牌A”、“预算8000元”、“编程用途”。关系可能是“用户-询问-笔记本电脑”、“笔记本电脑-品牌是-品牌A”、“用户-有预算-8000元”、“笔记本电脑-用于-编程”。这个过程已经发生了信息丢失上下文丢失用户可能说“我主要用来写Python和跑一些轻量级数据模型偶尔也剪剪视频”。图谱可能只留下“编程用途”而“轻量级数据模型”和“偶尔剪视频”这两个对平衡CPU、GPU、内存至关重要的限定词很可能因为不符合预设的“用途”关系模式而被忽略或者被模糊地归为“多媒体处理”。否定与不确定性丢失用户说“我不太喜欢品牌B的售后”。这句话在知识图谱中极难有效表达。它可能被完全丢弃或者被错误地简化为一个负面的“喜欢”关系但“不太喜欢”的程度和“售后”这个具体原因这些细微差别都消失了。时序与过程信息丢失对话是动态的。用户可能先问“品牌A的X型号如何”然后基于回答又问“那和品牌C的Y型号比呢”。图谱通常只记录最终状态用户考虑了品牌A和C但丢失了决策的思考路径先关注A再对比C。这对于理解用户偏好至关重要。关键在于在“摄入”Ingestion阶段我们就必须用一个固定的“模式之网”Schema去过滤流动的、开放的对话信息流。我们提前决定了“实体类型”人、组织、产品和“关系类型”购买、询问、属于的范畴。任何无法被这个模式捕获的信息在那一刻就被判定为“噪声”并丢弃。然而智能体在未来任务中需要回溯的很可能就是这些被丢弃的“噪声”。2.2 模式僵化与查询的局限性知识图谱的优势在于对已知模式的复杂查询例如“找出所有用户询问过的、用于编程且预算在5000-10000元的笔记本电脑品牌”。这建立在两个前提上1) 我们提前知道会关心“用途”和“预算”这类属性2) 这些属性已被正确、一致地抽取和填充。但在开放域的智能体对话中用户的需求天马行空。今天讨论编程电脑明天可能问旅游攻略后天聊哲学问题。为所有可能的话题预先定义一套完整的模式是不现实的。即使采用动态模式或开放信息抽取其抽取结果也是不稳定、不完整的并且依然受限于抽取模型本身的能力偏见。更关键的是智能体的记忆查询往往是模糊的、基于语义的、甚至是指代性的。用户可能会说“还记得我之前跟你提过的那台电脑吗你当时说它的显卡有点问题。” 这里的“那台电脑”和“有点问题”是强烈的上下文指代。基于图谱的查询需要先将这个自然语言问题解析成图谱查询语言如Cypher, SPARQL这本身就是一个NLP难题并且严重依赖于之前抽取的实体链接是否准确。如果当初“显卡有点问题”这个评论因为过于模糊未被抽取为结构化关系那么这次查询就会失败。实操心得模式定义的陷阱我们在早期尝试中曾为“产品推荐”场景精心设计了一个包含数十个实体和关系的模式。最初几天效果似乎不错直到用户开始和智能体闲聊起产品的颜色、手感、甚至包装盒设计。这些信息全部落入“其他”类别或直接丢失。当我们试图扩展模式来容纳“颜色”和“手感”时又发现不同品类的产品属性差异巨大手机的手感和沙发的手感完全不是一回事导致模式迅速膨胀且难以维护。我们意识到试图用一个静态的“模式篮子”去装下所有对话的“信息活水”是注定徒劳的。3. Vektori的三层记忆架构设计哲学基于对上述缺陷的深刻认识我们为Vektori设计了全新的记忆架构。其核心哲学是放弃在摄入阶段进行不可逆的、有损的结构化压缩转而采用一种“分层存储、按需回溯”的策略将原始信息作为记忆的“基石”完整保留。我们的架构包含三个层次自底向上分别是3.1 L2原始语句层——记忆的“源代码”这是整个架构的基石也是最关键的不同点。我们永久保存每一轮对话的原始文本Raw Sentences不做任何删除或概括。这些文本按会话Session和时序索引存储。你可以把它想象成数据库的“Write-Ahead Log”或源代码管理的完整提交历史。作用提供绝对的、无损的信息保真度。当需要验证一个事实、追溯一个观点的原始语境、或者理解一个模糊指代时L2是最终的权威来源。存储与开销是的这需要存储空间。但在云存储成本极低的今天文本数据的存储开销对于绝大多数应用而言是可接受的。更重要的是L2数据在常规查询中默认不加载它只在需要深度追溯时才被触发访问因此对日常查询性能几乎没有影响。设计考量我们为每条原始语句附加了丰富的元数据包括会话ID、时间戳、说话者用户/智能体、以及在前端渲染所需的定位信息。这确保了回溯时的精准定位。3.2 L1事件片段层——自动发现的“故事单元”如果说L2是连续的“数据流”那么L1就是从中自动识别出的、有意义的“段落”或“章节”。我们称之为“事件片段”Episodes。一个事件片段可能是一次完整的产品查询、一个故障排查过程、一段偏好的讨论。如何生成我们不依赖人工预定义的模式。而是采用无监督或自监督的对话分割与聚类算法结合语义相似度自动将连续的对话流切分并聚合到不同的事件片段中。例如连续多轮关于“选择笔记本电脑”的对话会被归入同一个“笔记本电脑选购”事件片段。优势动态性模式是自动从数据中发现的而非强加的。它能适应新的话题和对话风格。保真性事件片段本身可以包含指向L2原始语句的指针集合或者存储经过轻度、可逆的概括如生成一个摘要但核心是它保持了对话片段的连贯语义单元。高效检索相比在海量原始语句中搜索在数量少得多的“事件片段”层面进行语义检索效率要高得多。这构成了我们记忆系统的“主索引”。3.3 L0提取事实层——高频访问的“缓存”这是最上层也是访问速度最快的层面。它包含了从对话中提取出的、经过高质量过滤的确定性事实Extracted Facts。例如“用户偏好16GB内存”、“用户预算上限为8000元”、“用户排除了品牌B”。与知识图谱的区别关键区别在于L0的事实是扁平化、去模式化的。我们不强制要求它们构成一个连通的图。它们更像是一个个独立的“断言”Assertions或“键值对”附带置信度和来源指向L1和L2。查询时我们进行的是高效的向量相似度搜索或关键词搜索。作用服务于对延迟极度敏感的、简单的事实性问答。比如用户问“我的预算是多少”系统可以直接从L0层快速返回“8000元”而无需回溯整个对话历史。质量过滤并非所有提取的事实都会进入L0。我们通过一个质量过滤层只保留高置信度、高确定性的信息避免将模型的猜测或模糊表述作为事实存储。三层之间的关系L2是地基完整保存一切。L1是基于L2内容自动构建的语义索引层。L0是从L1/L2中蒸馏出的高价值信息缓存。当智能体需要记忆时查询首先快速扫描L0如果不够则深入L1进行语义搜索相关事件片段如果需要核实或获取完整上下文则最终定位到L2的原始语句。图谱结构如果我们需要可以构建在L1或L0之上作为特定视图而不是取代它们。4. 架构实现与核心环节解析理解了设计哲学我们来看看具体如何实现这个三层架构。这里会涉及一些工程上的关键决策。4.1 数据存储方案选型存储设计必须满足分层、高效检索和成本可控的要求。L2原始语句存储选择对象存储如AWS S3、MinIO或高性能的文档数据库如MongoDB。理由L2数据量大但访问模式是“低频、大批量读取”按会话读取或“极低频、单点读取”追溯某句话。对象存储成本极低且吞吐量高非常适合这种场景。我们按{session_id}/{turn_index}.txt的格式存储原始文本和元数据JSON格式。文档数据库则提供了更灵活的查询能力如按时间范围、说话者过滤适合对回溯查询有更复杂需求的场景。实操配置示例伪代码# 存储原始语句 def save_raw_turn(session_id, turn_index, speaker, text): object_key fsessions/{session_id}/{turn_index:06d}.json data { text: text, speaker: speaker, timestamp: time.time(), session_id: session_id, turn_index: turn_index } s3_client.put_object(BucketRAW_BUCKET, Keyobject_key, Bodyjson.dumps(data))L1事件片段存储选择向量数据库如Pinecone, Weaviate, Qdrant结合元数据数据库如PostgreSQL。理由L1的核心操作是基于语义的相似性搜索。向量数据库为此进行了优化。我们将每个事件片段的语义摘要或关键语句编码成向量Embedding存入向量库。同时在PostgreSQL中存储该片段的元数据唯一ID、所属会话、起止轮次指针、创建时间、以及指向L2原始语句的指针列表。索引策略向量索引我们选择HNSWHierarchical Navigable Small World它在精度和召回率之间取得了很好的平衡且支持动态增量插入非常适合对话这种流式数据。L0提取事实存储选择内存缓存如Redis 向量数据库/关系型数据库。理由L0要求极快的读取速度。我们将最热、最确定的事实例如用户姓名、当前核心任务目标放在Redis中。更多的事实则存储在向量数据库用于语义搜索如“和预算相关的事实”或关系型数据库用于精确键值查询如“user_preference_budget: 8000”中。定期根据访问频率和新鲜度更新缓存。4.2 事件片段的自动发现算法这是L1层的核心技术。我们的目标是无需人工标注自动从对话流中切分并聚类出有意义的事件片段。切分Segmentation方法结合多种信号。语义转折计算相邻对话轮次之间的语义向量余弦相似度。如果相似度低于某个自适应阈值则可能是一个话题边界。时间间隔长时间停顿可能表示一个话题的结束。对话行为识别用户或智能体的“重启性”话语如“好了我们换个话题”、“再问一下...”、“另外...”。实现我们采用一个轻量级模型如基于BERT的句子编码器计算每轮对话的向量然后通过一个滑动窗口计算局部相似度变化结合规则进行切分。聚类Clustering与片段形成方法在线聚类算法。流程当一个新的对话轮次或一个小片段产生后计算其语义向量并与现有的所有事件片段的核心向量进行相似度比较。如果与某个现有片段的相似度高于阈值则将其归入该片段并更新该片段的核心向量如取均值。否则创建一个新的事件片段。关键参数相似度阈值需要动态调整。我们根据片段内对话的紧密程度内部相似度方差来微调该阈值避免片段过大或过小。注意事项处理模糊边界对话话题的转换常常是渐进的而非一刀切。我们的算法会允许一个对话轮次以一定概率属于多个片段软聚类并在元数据中记录这种关联强度。这在处理“承上启下”的对话时非常有用。4.3 查询路由与信息融合当智能体需要“回忆”时例如处理用户输入“像我之前说的...”记忆系统按以下流程工作查询解析首先解析当前用户查询和对话上下文生成一个搜索查询向量和一组关键词。L0快速查找用关键词在L0的事实缓存中进行精确匹配和向量相似度搜索。如果找到高置信度、完全匹配的答案如“预算8000”直接返回。L1语义搜索如果L0结果不充分使用查询向量在L1的向量数据库中搜索最相关的K个事件片段例如K3。上下文获取与融合从向量数据库返回的片段ID到元数据库中找到对应的起止轮次指针。根据指针从L2存储中读取对应的原始对话文本。将L0的事实、L1的片段摘要/关键句、以及L2的原始文本片段一起组合成一份丰富的“记忆上下文”。提供给智能体将这份融合了多层次信息的上下文作为系统提示System Prompt的一部分注入给大语言模型LLM由LLM来最终理解和利用这些记忆进行回复。这种“路由-融合”机制确保了智能体既能快速获取高度提炼的事实又能根据需要深入到最原始的对话细节中实现了效率与保真度的平衡。5. 性能基准与效果评估理论再好也需要数据验证。我们设计了一套评估体系并与典型的基于知识图谱的记忆方法进行了对比。5.1 评估数据集与指标我们采用了公开的智能体长期记忆评估基准例如LongMemEval数据集。这个数据集包含多轮、多话题的扩展对话并在后续对话中设置了需要依赖长期记忆才能正确回答的问题。核心指标记忆召回率Memory Recall智能体能否正确回忆起之前对话中提及的事实、观点或承诺。上下文保真度Context Fidelity当需要追溯时智能体提供的细节是否准确有无扭曲或混淆。查询延迟Query Latency从触发记忆查询到获得记忆上下文的时间特别是P95和P99延迟。存储开销Storage Overhead记忆系统占用的磁盘/内存空间。5.2 Vektori架构的基准测试结果在我们的内部测试和针对LongMemEval-S数据集的评估中我们的三层架构表现如下记忆召回率达到了73%的综合得分。这是一个显著的提升。分析发现提升主要来自两个方面对模糊指代和隐含信息的处理当问题涉及“你之前提到的那个有点贵但性能好的选项”时基于图谱的系统往往失败因为“有点贵但性能好”很难被预先抽取为结构化属性。而我们的系统通过L1的语义搜索能找到相关事件片段并通过L2原始文本确认具体指代。对否定和条件信息的保留用户说“如果超过9000我就不考虑了”。图谱可能只记录“预算9000”而丢失了“超过...就不考虑”这个条件逻辑。我们的原始文本层完整保留了这一信息。上下文保真度在需要提供引用或细节的问题上我们的系统能够精确指向原始对话的轮次和语句而基于图谱的系统通常只能提供抽取后的“事实”无法追溯到具体表述有时甚至会因抽取错误而提供失真信息。性能与开销查询延迟得益于L0缓存对于简单事实查询延迟与图谱方案相当毫秒级。对于复杂的语义查询由于L1层向量检索的高效性整体延迟仍控制在可接受范围百毫秒级且P99延迟更稳定因为避免了复杂图谱查询可能出现的性能抖动。存储开销L2原始文本存储使总存储空间比纯图谱方案增加了约2-5倍取决于对话长度和压缩率。然而考虑到文本存储的廉价性以及L2数据冷存储的成本总拥有成本TCO的增加远低于性能收益。L1和L0的存储开销与图谱方案处于同一量级。5.3 与知识图谱方案的对比分析我们将两种方案的核心差异总结如下表特性维度传统知识图谱记忆方案Vektori 三层记忆架构信息摄入有损、不可逆压缩。依赖预设模式丢弃模式外信息。无损存储。原始对话完整保留L2。结构化/提取是后续的、可逆的视图。记忆保真度低。信息被抽象和简化丢失细节、语境和模糊表述。高。可通过L2追溯到任何一句话的原始语境信息零失真。模式灵活性低。需要预先定义或不断扩展模式难以适应开放域对话。高。L1事件片段自动发现无需预定义模式。可适应任意新话题。查询能力擅长对已知模式的复杂关系查询。不擅长处理模糊语义、指代和自然语言问题。擅长语义相似性搜索和精确原文回溯。更贴合人类自然提问方式。实现复杂度高。需要维护图谱模式、实体链接、关系抽取管道以及图数据库。中。核心是向量检索和文本存储技术栈更现代、更统一。适用场景领域高度固定、数据结构化明确的场景如企业知识库、特定产品客服。开放域、动态性强的智能体对话需求不可预知需要高保真记忆。6. 常见问题、挑战与实战调优在实际部署和开发Vektori的过程中我们遇到了不少挑战也积累了一些调优经验。6.1 如何处理超长对话和存储膨胀这是最常被问到的问题。完整保存所有原始对话会不会最终拖垮系统分层存储与生命周期管理我们对L2数据实施生命周期策略。例如热数据最近7天的会话原始数据存储在高速存储如SSB上。温数据7天前至90天内的数据转移到成本更低的标准对象存储。冷数据90天前的数据可以进行压缩归档甚至转移到冰川存储。当需要追溯时虽然有一定延迟但仍可获取。关键点即使转移到冷存储数据依然存在未被删除。这与图谱方案丢弃信息有本质区别。事件片段的归纳与摘要L1层的事件片段并非一成不变。对于非常古老或庞大的片段可以运行一个后台任务用LLM生成一个更精炼的摘要同时保留指向关键原始语句的指针。这样可以在不丢失溯源能力的前提下压缩L1层的存储和检索负担。选择性保存在极端情况下可以对L2数据实施基于策略的清理。例如只永久保存标记为“重要”的会话或用户明确要求保存的会话。但这需要谨慎因为“重要性”难以自动判断。6.2 向量搜索的“语义漂移”问题L1层依赖向量相似度搜索如果编码模型Embedding Model不够好或者对话话题非常发散可能导致搜索不准确。混合检索Hybrid Search我们不单纯依赖向量搜索。采用“向量搜索 关键词搜索BM25”的混合模式。首先进行向量搜索得到语义相关候选集再用关键词搜索进行重排序Re-ranking。这结合了语义匹配和精确词汇匹配的优点显著提高了召回率和准确率。查询扩展Query Expansion在将用户查询转换为搜索向量前先用LLM对查询进行小幅重写或扩展生成多个同义或相关的查询表述分别进行搜索后再合并结果。这有助于捕捉查询的不同侧面。领域自适应微调如果应用场景垂直如医疗、法律可以考虑用领域内的对话数据对开源的Embedding模型如BGE, text-embedding-3进行微调使其在该领域的语义空间更准确。6.3 事实提取L0的准确性与一致性问题从对话中自动提取高确定性事实本身就是一个难题提取错误会导致L0缓存污染。高阈值与人工验证回路我们为事实提取模型设置非常高的置信度阈值例如0.95。只有模型极其确定的事实才会进入L0。同时系统提供界面允许人工审核和修正被提取的事实这些修正会反馈给模型进行持续优化。多模型投票对于关键事实如价格、日期、关键决策采用多个不同的提取模型基于规则、基于微调LLM、基于Prompt的通用LLM进行提取取它们的共识结果可以大幅降低错误率。事实溯源L0中存储的每一条事实都必须明确记录其来源指向L2的具体语句。当智能体引用该事实时可以附带来源增加可信度也便于在发现错误时进行溯源和修正。6.4 系统整体复杂性带来的运维挑战三层架构听起来比单一图谱方案更复杂。清晰的接口抽象我们为记忆系统设计了简洁清晰的API例如recall(context, query)和memorize(session_id, dialogue_turn)。内部的三层实现细节对上层应用透明。这降低了使用和集成的复杂度。可观测性Observability我们在系统的关键路径埋点监控每一层的缓存命中率、查询延迟、存储增长、事实提取准确率等指标。通过仪表盘可以清晰了解系统状态快速定位瓶颈。渐进式采用对于资源有限或场景简单的团队不一定需要完整实现三层。可以从L2 L1开始放弃L0缓存用向量搜索直接服务所有查询。或者从L1 L0开始只保存片段摘要放弃无限期的原始文本存储L2直到确有需要。放弃知识图谱作为智能体记忆的“银弹”转向一个以原始信息为基石、分层索引的架构对我们来说不是一个轻易的决定而是一次被实际问题“逼”出来的架构演进。这个方案承认了对话的复杂性和不可预测性不再试图用一把固定的“结构之梳”去梳理所有信息流而是选择“全量保存智能索引”。它带来的最大改变是心理上的解放我们不再需要为“该记住什么、该扔掉什么”而焦虑。所有决策都可以推迟到查询发生时基于当时最完整的信息来做。这使智能体的记忆行为更贴近人类——我们并非只记住结构化的事实而是保留着鲜活的经历片段并在需要时从中提取和重构信息。如果你也在构建需要长期记忆的AI智能体并且受困于图谱方案的僵化或信息丢失我强烈建议你重新思考存储与检索的范式。我们的代码和设计已在GitHub上开源Vektori它可能不是所有场景的最优解但它为我们打开了一扇新的门。至少在下次看到又一个“革命性”的智能体记忆方案时你可以多问一句它在摄入阶段扔掉了什么