LinkedIn 工程团队为招聘助手构建了四层认知记忆架构,实现 Agent 状态持久化与个性化;详细拆解各层设计权衡与实现思路。
Praveen 解释了为什么他的团队放弃 GraphRAG,转而采用树状结构记忆以实现更快的增量更新,以及他们如何在 LinkedIn 的规模下平衡检索新鲜度、延迟预算和访问控制。
通过 LinkedIn 与 Praveen 交流。
恭喜 Populist 徽章获得者 Luka Ganić,他回答的《SVG image as button in Flutter》非常出色,评分甚至超过了被采纳的答案!
大家好,欢迎来到 Stack Overflow Podcast,这里是讨论所有软件和技术话题的地方。我是你们的主持人 Ryan Donovan,今天我们要讨论的是 LinkedIn 那边构建的一个非常、非常大的 AI 智能体记忆系统。我今天的嘉宾是 Praveen Badagutla,他是 LinkedIn 的一位首席 AI 研究员。
他是 LinkedIn 的一位首席 AI 研究员。欢迎来到节目,Praveen。
Praveen Bodigutla(00:35)
谢谢你,很高兴认识你,Ryan。
是的,很高兴你能来。在开始今天的话题之前,给我们讲讲你是怎么进入软件和技术领域的吧。
Praveen Bodigutla(00:47)
我刚才说了,我是 LinkedIn 的首席 AI 研究员,领导一些基础性工作,包括记忆智能体,同时我也是创始工程师,领导了一些 AI 产品的开发,包括企业端和消费端。我走到今天这个位置的旅程是相当非线性的。我实际上
Praveen Bodigutla(01:09)
很久以前在雅虎担任平台工程师,那是在我完成计算机科学和经济学本科学习之后。后来我在斯坦福大学和纽约大学分别攻读了金融数学以及数据科学的两个硕士学位,在那里我有机会与一些知名教授合作,如 Andrew Ng、Kyun Kyoon Chou 和 Jeffrey Ullman。在上一段职业生涯中,我是纽约投资银行的量化开发人员。之后我加入了 Alexa,从事对话模型研究。
所以职业生涯的核心主题一直是
Praveen Bodigutla(01:52)
在 AI 方面进行创新,并构建平台
以便将创新转化为对最终用户有用的产品。
是的。我认为,你知道,我们今天讨论的东西,在这个很多人都关注的领域——AI 智能体记忆和上下文层——感觉是一个很大的创新。现在你们构建了一个完整的认知记忆智能体,服务于某些场景。你们能给我们讲讲这个项目的概况吗?
Praveen Bodigutla(02:25)
好的,让我们先从为什么我们要构建认知记忆智能体开始。
好的,这是一个很好的开始。
Praveen Bodigutla(02:32)
LinkedIn 开发并成功推出了招聘代理或招聘助手,帮助招聘人员管理他们的招聘工作流程。我们观察到的是,通过招聘人员与这些智能体的互动,他们表达了一些招聘偏好,同时也完善了他们正在招聘的职位。
他们不仅提到了在哪里招聘以及他们感兴趣的是什么技能,还对展示给他们的候选人给出了直接反馈。我们观察到,这些偏好具有粘性性,实际上会转化为他们如何定义类似职位的以及其他正在招聘的职位的定义。所以,为了给招聘人员提供真正的 AI 智能体体验,
我们想要提供这一层个性化,这就是认知记忆智能体的起源,它为我们的
Praveen Bodigutla(03:33)
我们的智能体提供了这种状态概念,这些用户——在这种情况下是招聘人员——正在与智能体互动。为什么需要记忆智能体,因为我们不仅仅想获取上下文,还想管理记忆的整个生命周期,或者整个记忆飞轮,从
理解什么被摄取,什么被检索,
Praveen Bodigutla(03:55)
它如何上下文相关,如何组织,如何更新。所以记忆智能体基本上管理整个飞轮,并为我们的最终用户提供深度个性化。这就是我们开发记忆智能体的原因。
是的。我觉得你提到状态很有意思,它不仅仅是某种会话状态。它不仅仅是某种偏好状态。就像这是一个完整的四层状态结构。你能谈谈这四层是什么吗,为什么你需要四层?
Praveen Bodigutla(04:37)
好的,我们记忆智能体中使用的四层记忆是:其中之一是会话记忆,比如说,你和我现在正在互动,我们正在表达我们在不同方面的偏好,我们正在尝试完成的任务。这是最新的,也是最新的,这是我们拥有的信息。然后我们在另一端有语义记忆层,这是
基于用户跨会话的互动和表达偏好聚合的用户信息。正如你所知道的,在 LinkedIn 我们有不同的产品和服务,以及用户互动的不同界面,招聘人员不仅使用招聘助手智能体,还使用搜索平台来寻找候选人。他们在那里表达这些偏好。所以我们想确保
用户获得的体验是,我们知道他们在寻找什么,我们正在为他们个性化整个体验。所以语义层不仅聚合了用户与智能体不同互动的信息,还基于他们在相关产品服务上的活动。现在,在这两者之间,我们还有情景记忆存储,它提供了这种时序查询层,在
这里我们可以识别,这个用户执行的最新相关活动是什么。所以它不仅提供了信号的特异性,还提供了溯源能力。比如说,我们聚合了信息,现在我们可以追溯回去,是哪些活动帮助我们得出结论,这是最终用户的偏好。最后但同样重要的是程序记忆层。每个用户,每个招聘人员如果他们实际上在与
智能体互动,即使他们正在招聘类似的职位,他们互动的方式、做出的权衡和表达的偏好都非常不同。有些人可能
Praveen Bodigutla(06:35)
实际上更看重地点和工作场所类型,而其他人可能更看重资历和职位的特定方面。所以用户实际完成这些任务的方式——在这种情况下是招聘工作——被捕获在程序记忆中。所以
记忆就是这个分层蛋糕,包括会话、情景、程序和语义记忆,在不同粒度和特异性层面捕获信息。
嗯,你知道,这里有三个或四个最终状态桶。但它们都来自一个单一的数据流,对吧?基本上是网站上的讨论、互动。提取这些不同的行为状态标记有什么挑战?
Praveen Bodigutla(07:38)
好的,如果你看对话流,有两个不同的数据源集合。一个是,假设招聘人员或用户与智能体的互动。如果我们具体谈论这个,你的上下文会随着你在一段时间内积累这些互动而膨胀。比如想想招聘过程涉及多个步骤。首先,你从职位描述开始,然后完善职位描述。
然后你会看到某些候选人,然后你对此给出某些反馈,然后你联系某些候选人,你喜欢一些并归档其他的。所以所有这些信息都会积累。所以在运行时,我们要确保这些被正确压缩。我们有这个摄取服务,当它实际实时、近实时地查看这些互动时,试图 consolidation 这些。在固定工作流智能体中,这相对较容易,因为你
知道工作流中每一步的边界。但当我们走向更深入的智能体和高级互动时,这些步骤可能是相互关联的。用户可以首先,比如说,招聘人员可以首先从校准候选人开始,然后回去完善它,然后在这之间来回。所以识别正确的会话边界、识别正确的互动子主题,然后组织记忆并确保它是
可被发现。所以这条数据流本身也很有挑战性,因为你必须确保已经完成了压缩、没有丢失信息,然后还要准确地呈现那些被持久化的信息。而最后同样重要的一点是:我们还需要能够检索这些信息。
Praveen Bodigutla (09:24)
因为在交互进行的过程中,用户可能会改变偏好。比如他们可能会说,你知道吗,我不想在这个特定地点招聘了。或者让我们实际去找一个不同的技能方向,去找具有互补技能的人。所以当某些偏好在对话过程中被表达出来时,就引出了这样一个问题:我们如何确保最新鲜、最新的信息能够获得优先权?以及如果在检索记忆并回答用户在应用智能体端提出的查询时,
Praveen Bodigutla (09:50)
出现了任何冲突,如何确保这些信息是准确的、新鲜的,冲突被正确处理,而且最重要的是——以低延迟的方式完成。
是的。我想对于这样的系统,一个招聘人员可能同时在为多个职位进行招聘。在多个职位、多个偏好集的情况下,是否存在什么困难或复杂性?
Praveen Bodigutla (10:25)
确实有困难,但同时也有一种很好的偏好迁移效应——从一个相似的职位集迁移到另一个招聘人员正在招聘的相似职位集。现在,当我们谈论这个挑战时,我们首先要理解的是:我们的数据或者这些偏好或者说记忆在这种情况下是如何组织的。在招聘助理的场景中,我们有一个自然的树状结构。
对于某些被招聘的偏好。例如,一个招聘人员有多个他们正在招聘的项目,每个项目都可以有各自的偏好。这就是细粒度的叶子级别节点。然后你可以在招聘人员级别聚合这些偏好。再往上,你有同侪群组(cohort)的概念,比如多个招聘人员。假设他们属于同一家公司,正在招聘相似的职位。那么信息就可以在这些属于同一群组的不同招聘人员之间共享。所以
当我们挖掘这些信息并按其固有的结构进行组织时——既与数据中固有的结构对齐,也与交互的结构对齐——这实际上可以成为一种超能力,帮助我们为新入职的招聘人员引导一些对话,他们现在不需要从零开始,已经有了一个蓝图,知道他们的公司在职位优先级和招聘流程中的偏好是如何表达的
通过同一群组不同成员的招聘流程和工作流。
嗯。这是一个很好的过渡。你刚才提到这些是作为树结构存储的。那其他层是如何处理的?是有一种通用的存储结构,还是每个层都是不同的工程问题?
Praveen Bodigutla (12:14)
对,让我们看看什么是最基本 construct 能适用于所有人,因为我们是在构建一个平台。我们并不是要为一个又一个不同的应用重新设计和重新发明整个平台、记忆平台。是什么让每个应用独特的?那么如果记忆设计本身——我们的记忆智能体是语言图智能体(land graph agent),它使用某些工具来访问这些记忆层。这些工具非常通用。
从某种意义上说,我们实际上是在读取和写入情景存储(episodic stores),而用于访问这些记忆层的签名或 API 是固定的。然而,因为我们使用的是工具,你可以覆盖其中一些描述,并针对特定的应用偏好和逻辑以及他们实际想要存储数据的方式进行定制。所以这是记忆编排层(memory orchestration layer),涉及你如何规划、如何推理。
所以这一层是标准化的,它是一个固定的工作流,涉及到如何在回应之前获取记忆、对其进行推理。现在,从记忆结构本身的角度,在招聘人员的案例中,我们有一个清晰的、漂亮的偏好层级树结构,基于项目和同侪群组。然而,对于不同的应用,可能并不适用同样的结构——他们可能想组织
更像图结构的东西。比如说,我与个人有联系,但这不是一个清晰的层级结构。然后他们设计自己的长期记忆结构和偏好结构,并使其可用。但现在你已经通过一个标准接口或工具暴露了那个结构,现在它就可以被查询了。现在它变得可发现了,因为我们大致知道如何查询它。现在编排层、推理层以及综合层保持不变。
但个体的表征,比如说长期记忆,通常是会变化的。情景边界可能不同。例如,在某些情况下,就像招聘人员的情况,它是单一活动(single activity),因为它有高信号。我们
Praveen Bodigutla (14:24)
想要减少噪音,想要提高信噪比。但在某些情况下,那个活动是跨越多个词(terms)展开的。所以那成为情景边界,而什么被持久化以及保守记忆(conservation memory)或多或少保持不变
其结构大体相同,因为这是我们正在综合的交互。而程序记忆(procedural memory)是推理记忆(inferred memory)。所以其中一些是被挖掘出来的结构,基于与应用相关的内容被提取出来。所以这是你在应用层面想要提供的自定义化程度,与此同时在平台层面你提供了基本的原则,涉及整体设计,这些原则是非常
稳定且可泛化的,同时可以扩展到不同的应用和解决方案。
好的。如果我理解正确的话,你是说你所有的记忆层首先都会经过一个记忆编排组件,然后才到达最终的应用,对吗?
Praveen Bodigutla (15:24)
对。所以我们有专门的摄入服务(ingestion service),然后有检索服务,还有离线整合作业(offline consolidation job),它整合所有这些信息,去除重复,与外部资源连接和补充,用补充信息进行增强,去除过时和重复的信息以及冲突的偏好片段。然而,整个记忆片段——受管理的记忆片段——会经过这个摄入、
组织和检索的过程。
所以很长一段时间,显然人们获取上下文和 AI 及智能体的参考信息的方式是 RAG,即检索增强生成(retrieval augmented generation),或者某种向量数据库。这看起来你是在从多个来源提取、整合、聚合、决定什么是好的
什么是相关的——这个想法是什么?你如何确定什么是相关的,既从每个单独的记忆存储中,又从这个聚合的记忆 blob 或其他什么东西中?
Praveen Bodigutla (16:42)
对。所以我认为当我们谈论相关性时,我们实际上是在谈论相关性的两个不同方面。一个是你从哪里同步所有信息?你怎么知道这些信息是相关的,需要摄入并使其成为你记忆的一部分?第二个是你如何检索相关信息?这与传统 RAG 有什么典型区别?在 RAG 中
我提取所有东西,然后只是将其作为应用智能体的上下文提供给它来管理。从摄入的角度来看,这里有领域专业知识在发挥作用,因为这个应用智能体是为解决某些难题而定制的。在这个案例中,招聘人员正在招聘并寻找候选人来填补他们的职位。现在,我们关注的点是:招聘人员表达了偏好的不同信号有哪些?
最终目标是什么?我们如何衡量我们实际上提供了正确的记忆抽象,而且它是一个高效的堆栈,同时也减少了摩擦,并使他们在招聘时更加高效和富有成效?所以这是我们使用的关键原则之一。比如我在哪里可以找到招聘人员正在交互的不同产品界面?他们在那里提供了什么样的偏好?
我们如何实际综合这些信息?现在我们也希望这变得透明。我们不想只是因为他们可能表达了偏好,然后就聚合了,然后他们会说,我实际上没有说过这个。所以
这就是显著性空间发挥作用的地方,也是可追溯性
Praveen Bodigutla (18:21)
方面。当我们将特定的细粒度信息摄入情景记忆时,我们所做的任何综合、任何提供的结论,都会形成你的偏好档案,以及你的偏好图谱。这些偏好以及你的领域智能——个性化领域智能——每一项都是一种引用类型,也就是实际记录,你可以从中看到你做了什么,以及我们为什么认为这是你的特定偏好。在未来,我们还在努力为用户提供更多控制权,让他们能够明确地说:嘿,我不再认为这是我的正确偏好了,比如"忘记这个"。也可能他们希望记住比我实际表达出的更多的额外偏好,他们可以提供帮助。
他们可以在那里添加这些键值对或信息。这是摄入端的情况。我们也有评估场景,我们有三级评估。当我们将信息持久化到记忆中时,我们确保信息不会丢失。无论你的输入信息中有哪些实体,在持久化时都会被保留,并配有证据和引用。
因此,确保我们对持久化的记忆有高质量的评估器,这给了我们信心——这确实是我们需要聚合、积累和综合的正确信息,以帮助招聘人员在他们试图完成的任务中表现更好。透明性方面也帮助他们看清我们如何以及为何做出某些决定。现在,从检索的角度来看,这就变得有趣了。
应用智能体有一些标准模式来查询记忆。例如,每当招聘人员登录时,第一步是获取所有信息。我们知道这一点。我们可以预聚合、创建缓存,并使其可用。但也有一些非标准的模式,这些模式更加动态。例如,招聘人员——正如我之前所说——会从一个阶段或工作流移动到不同步骤,然后交错、表达偏好,覆盖之前的偏好。因此,从检索的角度来看,现在需要根据他们表达的偏好来提取正确的信息。例如,如果他们说,嘿,我是否给出过类似的反馈?有没有我确实给出过类似反馈的候选人?当时我在技能方面表达的是什么偏好?
这些查询我们无法预知。但由于我们有这种分层记忆,而且还有
Praveen Bodigutla (21:06)
某种时间查询和 EBR 检索的方式。现在我们知道,在工作流中招聘人员处于特定步骤。这是他们提供的上下文。基于这个上下文,获取最相关的信息,减少噪音、增加信号,然后返回给应用智能体,这样应用智能体就可以做出更加深思熟虑的决策,并为招聘人员提供更有价值的信息,而不是仅仅提取他们的所有活动——那会导致上下文膨胀。
是的。你们有没有做某种双重计数——如果有人多次表达同一偏好,你们是否会说这是一个更可靠的偏好?还是说只是……是的,和我们档案里的一样?
Praveen Bodigutla (21:57)
就目前而言,即使没有对偏好进行内部优先级排序,仅仅回忆这些信息也展现出巨大的价值,即使在偏好本身的具体值方面,一个偏好比另一个更有价值。我们有优先级和冲突解决策略,来优先考虑某一层记忆而不是其他层。
然而,我们正在研究的是,权重方案如何根据他们多次表达的偏好动态演化。我的意思是,首先,我们不希望他们反复表达相同的偏好。这意味着我们引入了摩擦。如果我们没有正确地综合这些信息并提供了错误的信息,他们就会说,不,不,不是那个地方。
Praveen Bodigutla (22:47)
所以下游指标之一——
我们称之为三级指标,它衡量帮助程度和对产品的影响,也衡量摩擦。它关注的是——我们是否真的减少了对话轮数?是否增加了条款数?所以这是一个我们必须做出的权衡。即便是同等权重地recall和提供信息,而不进行优先级排序和提供额外的认知层权重,这实际上是否有帮助——而额外的认知层权重可能会给用户带来更多认知负担,最终他们需要说,我认为这个优先级更高,这个更低。
嗯。你谈到了提取和转换,听起来越来越像是某种面向智能体时代的 ETL 管道。这是准确的吗?还是说有什么额外的复杂性?
Praveen Bodigutla (23:48)
我认为额外的复杂性正是让它成为智能体时代 ETL 的原因,与
Praveen Bodigutla (23:54)
仅仅存储所有内容不同,我们必须非常谨慎,确保我们捕获的是信号而不是噪音。
Praveen Bodigutla (24:07)
正是这些方面使得某些东西从摄入和
检索的角度来看都具有智能体特性——我们捕获正确的信号,并将其组织成易于发现、易于维护的形式,同时提供所有必要的治理和访问控制,然后提供这种记忆的安全检索和管理,这样就不会有上下文污染,也不会有不应当泄露的信息从不同地方泄露出去。
Praveen Bodigutla (24:40)
是的。