阿里技术|详解闲鱼推荐系统(长文收藏)
作者:序玮 闲鱼技术 稿
在互联网信息爆炸的今天,推荐系统是我们身边一个无法躲避的存在。在淘宝上浏览商品,在抖音上刷视频,以及无处不在的广告等等。本文探讨闲鱼商品推荐系统的同时,结合所面临的多推荐场景工程维护任务重、算法模型优化难以自动辐射多场景的痛点,介绍如何构建通用的推荐中台。
背景
推荐系统
用户在网络上浏览时,如果能准确描述自己的需求,可以通过主动搜索来找到自己需要的信息。但是在不少情况下,用户并不一定能准确的描述自己的需求,或者用户就是来逛的,这个时候用户往往希望产品能主动把感兴趣的信息直接推送到自己面前。此时,推荐系统即发挥其中介作用,来连接用户与信息。
而在互联网信息蓬勃发展的今天,每时每刻都在生产大量的信息与内容。因此,推荐系统需要解决的问题,便是从海量的候选信息中,挑选出用户最感兴趣的信息。
为了完成这一挑选最优过程,典型的闲鱼商品推荐系统,涉及模块如下图所示。
- 数据
推荐系统本质是架构于数据之上的,这里的数据包括用户自身的年龄、性别、所属地域,用户所发布的商品、内容结构化数据,以及用户浏览过程中产生的曝光、点击、互动等行为数据。通过对海量的用户&商品&行为数据进行分析与计算处理,从而生成用户的trigger信息,生成样本数据辅助算法模型的训练,构建生成引擎索引数据表等。
- 用户信息
用户请求到来时,需要先识别出用户是谁,进而实现后续的个性化推荐。这里我们通常会根据用户的唯一id,查询用户中心服务系统,得到用户维度的基本信息。
- trigger
trigger,作为触发阶段,是推荐的源头,一般为用户历史浏览、点击、互动行为的商品,以及用户偏好等。在数据处理阶段,我们对这些trigger信息进行提炼。通过数据回流链路,最终将trigger信息存储于在线系统,在线请求服务时,根据用户唯一id实时查询出数据,参与后续的流程。
- 召回
上文有提到,全量的推荐候选集,数据量级往往突破千万,甚至级别。如果每一次的用户请求,我们均采用全局排序的思路,遍历整个推荐候选集,进行模式算分后,再找出topK个最佳预测的商品。这样的推荐效果可能很不错,但是对计算资源与性能要求过于苛刻,在生产环境中难以实现。因此,我们通过召回,来解决在候选集上进行全量排序的资源&性能问题。 在召回阶段,基于用户的特征与trigger信息,从全量的亿级别候选集中,挑选出万级别的商品,送入后续的算分排序阶段。而在召回手段上,主要有规则定义、协同过滤、向量召回等。
- 粗/精排
算分一般也分为粗排+精排两阶段。粗排针对召回的万级别商品进行模型算分,由于打分候选量级较大,这里模型网络结构上一般采用双塔结构,而不做复杂的交叉网络。有了粗排分,我们再挑选排在前面的千级别候选集,进行一轮精排模型算分。此时待打分的商品量级可控,因此这一环节通常采用更多的用户&商品&交叉特征与较为复杂的网络模型。
- 重排
前面的排序主要通过算法网络模型决定,而重排阶段,则会体现场景的业务诉求,做一下打散干预,比如类目打散、价格打散等。
- 结果返回
经过上面的链路后,推荐系统最终将topK个(一般为10~20个)最佳预测的商品,填充元信息后,返回给用户进行展示。
- 日志&埋点
对展现给用户的商品做日志记录与埋点,便于回收用户行为数据。
基于上面的分析,一条完整的推荐链路开发维护成本并不低,其中涉及离线数据分析处理、采集样本、算法模型训练、模型&内容表索引构建、在线查询&召回&算分引擎部署、在线推荐服务开发、日志&埋点回收等。
面临的问题
闲鱼目前推荐场景数10+,在过去四个月新增了4个新的场景(闲鱼币,新品推荐,购后推荐,新发tab),同时更多推荐场景正在规划中(省心卖,首页tab feeds流等),这么多的tpp场景背后是闲鱼对个性化推荐的大量需求。 从工程角度来看每个新业务接入都需要从0到1搭建完整的推荐链路,除了大量重复的工作之外还伴随着不小的维护成本,如何才能降低如此众多场景的边际成本提升边际效益。 从算法视角来看,这些推荐场的算法模型都需要case by case迭代优化,如何实现模型迭代优化自动辐射到更多的场景。
设计方案
设计目标
基于上文分析,如何在有限的成本之下快速从算法获取更多的红利是我们核心要解决的问题。因此我们期望构建这样一个推荐中台,通过一套推荐底坐支撑所有的中小推荐场,实现收敛推荐链路的同时让算法模型迭代形成规模效应。 显然,针对不同的业务场景,其对推荐策略存在不同的诉求。即使同一个场景内,也存在不同策略实验的述求。因此我们将推荐链路中的各个环节,进行了抽象,沉淀出内容池策略、特征策略、召回策略、粗排&精排&重排策略等,每一个推荐场景便可以认为是各环节策略的组合。
同时,我们将策略以配置化+插件的方式对外输出。这样,当我们有新的场景接入时,不再需要去搭建完整的推荐链路,而是通过少量的配置化工作完成。最终将新场景上线的周期,由周级别降低至天级别,同时算法模型的迭代优化也能更加专注,接入流程如下图所示。
整体架构
如下图,是推荐中台的整体架构。整体上,我们依赖特征中心,根据用户与商品维度的特征信息灵活组合,计算产出各个场景的推荐候选池,并构建底池索引至引擎中。算法结合数据样本与底池,进行模型训练与召回数据训练,并产出模型与内容表,也回流至引擎供在线部分使用。在引擎部分,我们针对召回与排序,提供了通用召回与算分模型的同时,也定义了标准的输入输出协议,以满足业务场景定制化接入的诉求。场景的所有策略抽象,都收敛至实验平台进行管理。
用户在线请求pv到来后,我们首先根据场景id路由,拉取到相关配置后,根据具体的策略内容,逐步执行推荐各环节,如下示意。
推荐候选池
推荐候选池作为推荐业务场景最大的区别之一,其直接决定了推荐中台的复用/通用能力。因此支持高效灵活的定义推荐候选池,是首先需要解决的问题, 而从实际来看,结合闲鱼众多推荐场景,推荐商品候选池可以看做是用户与商品维度特征的组合,如下示例。
因此,我们使用特征来定义推荐候选池,通过特征的自由组合与实时计算,实现推荐候选池的大规模定义与计算,生产链路如下图所示。 这里面,闲鱼特征中心收敛了用户维度与商品维度特征(包括离线统计计算与实时产生的特征),以如下格式对外输出。
有了基础特征信息,再搭配推荐候选池定义的特征表达式组合,使用数据ETL工具,将原始商品与用户特征、商品信息维表、推荐池定义维表等数据源,经过多层merge、join的操作,最终在商品维度打上场景唯一标识(这个标识是一个以逗号分隔的复合字段,便于单个商品同时满足多个候选池规则时打标),生成各场景的推荐候选池。
召回引擎
召回策略上,我们提供了三种索引方式,分别是i2i索引,x2i索引,深度召回,并标准化掉召回的输入与输出。对于输入,有两种通用的格式,第一种为trigger格式,引擎将以传入的trigger作为key,从i2i与x2i索引中执行kv检索与倒排检索。第二种则是针对深度召回,上游传入模型预测出的embedding向量,再经由向量引擎完成检索。输出则是召回检索得到的商品item_id与对应的召回recall_score。 目前三种方式共计10+路召回通道可供业务场景选择,每一路召回通道都枚举了一个标识。接入业务只需要配置选择用哪些召回通道即可。
- • i2i:根据商品积累的用户点击行为,计算item-item的用户共现点击得分,作为i2i的相似度。
- • x2i:这里的x可以是商品的tag、class、brand、query、pool_ids等,根据用户全域的行为构建用户偏好,对商品标题信息进行分词,以及用户的tag,class,品牌,搜索场景下对应query等,最终构建倒排索引进行检索。
- • 深度召回:主要通过深度网络模型,来预测用户与商品的相似性。模型分别计算出用户侧向量与商品侧向量,在线检索时,根据用户侧向量,通过向量引擎完成ANN检索出topK个商品。
算分引擎
算分引擎的作用,是将输入的待打分候选商品集,关联上商品特征,并结合用户的特征,通过深度网络模型的计算执行,完成候选商品集中每一个商品对该用户的个性化预测得分。这里我们提供了一个包含ctr、cvr与互动的多目标算分模型,满足了大多数场景的个性化需求。 此外,我们将算分排序模型的输入输出进行标准化,也提供了模型定制化的能力。有些场景不太适应通用的多目标模型,可遵循协议将模型接入,每一个模型具备一个唯一的标识biz_name,场景配置上选择该biz_name即可。
模型存在多个目标得分,比如ctr_score、cvr_score、car_score等。而最终的得分如何计算,场景内也支持配置运算表达式与加权&降权(有些场景倾向转化,有些场景则重成交,或者满足交易抵扣的商品需要提权),来满足不同的场景要求。
实验体系
推荐系统迭代极快,算法工程师通常会展开很多AB实验,需要能够灵活的支持实验策略与流量调整。此外,全量用户基本比较固定,用户在不同场景,以及场景内不同实验,均需要做到互不干扰,保证实验的独立性。 在实现上,每次注册场景时,我们会同步创建实验与流量模型,并跟场景id进行绑定,确保场景之间的流量模型独立。场景内部多实验的诉求,则通过在流量模型内进一步动态分层的方式。这样场景A对应流量模型A,场景B对应流量模型B。而场景A里面,实验1按照50% vs 50%运行在流量模型A的分层1,实验2也可以按照50% vs 50%运行在流量模型A的分层2。
稳定性
推荐中台,承载了闲鱼10+推荐场流量,因此对系统的稳定性和业务的高可用有极高的要求。在系统部署上,分别在中心机房(张北)和单元机房(南通)进行了异地多机房部署,确保线上单一机房故障异常时,能够通过紧急切流将流量转发至正常机房提供服务。
此外,我们对接入的业务场景,也做了逻辑隔离。分场景配置限流熔断,当某一个场景有异常或者突发流量时,能够对其快速降级&熔断,避免其余场景受到影响,保障整体的高可用。
结语
推荐是一项系统性工程,近年来在计算架构、模型网络结构等方面也不断演进。本文在介绍闲鱼商品推荐架构的基础上,围绕如何在有限的成本之下快速从算法获取更多的红利这一核心问题,提出通用推荐中台解决方案。
推荐中台的搭建,是工程和算法将自身能力进行沉淀的一次有效尝试,新场景只需要天级别就能完成接入,工程与算法的维护迭代也将更为专注与聚焦。目前已经接入10+场景,对比场景接入前后的效率指标,其中点击转化率提升8%以上,人均ipv提升10%以上。同时随着接入场景增多,也为平台沉淀有价值的数据标签。
此外,当前整体链路上也仍存在一些不足。在排序模型上,模型的精度还有一些欠缺,以及多场景联合建模尚未开展。在工程上,场景接入还需要开发同学介入干预,自动化程度有待提升。后续我们将持续迭代优质工程与算法能力。