贝壳找房 | 面向 AI 技术的贝壳智能推荐平台建设实践
作者: 袁彬@贝壳找房
本文根据贝壳找房资深工程师袁彬老师在2020年"面向AI技术的工程架构实践"大会上的演讲速记整理而成。
1 开场
大家好,很荣幸在这里给大家分享一下我们贝壳找房,在智能推荐平台建设方面的一些实践经验。今天的分享,主要分为以下四个部分:
- 贝壳智能推荐平台简介
- 贝壳智能推荐平台的演进之路
- 贝壳智能推荐平台的架构设计
- 未来规划与展望
2 贝壳智能推荐平台简介
在贝壳找房这个科技驱动的新居住服务大平台上,我们的服务是多元化的,包括二手、新房、租赁、装修、商业地产、海外等多个业务线。智能推荐平台在公司的使命,是承接所有的推荐业务相关的策略工作,目前已有300余个推荐场景,图1右下角这张图展示的是我们承接服务所属业务线的分布,可以看到二手、新房、租赁是比较大的三块,还有内容类是包括百科、问答、咨询、导购、视频、直播等贝壳内部产生的信息类物料,帮助用户更好地学习居住相关的基础知识以及了解当前的市场行情动向。
图1-贝壳智能推荐平台介绍
贝壳智能推荐平台的核心用户包括两个群体,一个是C端用户,另一个则是B端经纪人。那么大家先来看一下对于C端用户,智能推荐平台都做了哪些事情。
一个客户在我们平台的购房流程一般都会经历从初步萌生购房想法、找房、咨询经纪人、带看、成交、售后这6个主要阶段。我们智能推荐平台就是在用户"找房"这个阶段切入的,在这个阶段我们能够帮助用户提升找房效率,辅助用户进行决策。
图2-用户购房流程
接下来,介绍一下在经纪人这一侧,我们智能推荐平台是如何体现价值的。一个经纪人在我们平台的服务流程大致包括获得商机、录客、维护营销、线下带看、成交、提供售后几个阶段。我们智能推荐平台就是在维护营销这个阶段切入的,在这个阶段我们能够帮助经纪人提升作业效率。
图3-经纪人服务流程
对于C端用户的使用场景,我们在App的大首页,让大家一打开App就能看到自己心仪的房子,还会推荐一些导购咨询,指导用户进行购房决策。在房源详情页场景,能帮助用户快速找到和自己当前所看房子最相似的其他房子,实现货比三家,帮助用户找到最心仪的家。另外,推荐和搜索也会产生联动,由于搜索要求的精确匹配的结果,而二手房在某种程度上也算作稀缺商品,在用户筛选比较苛刻的情况下,还是会出现少结果甚至无结果的情况。这个时候就需要推荐来进行一些补充,就需要找到用户直击内心深处的需求来进行推荐。此外,还有内容发现的Feed流,推荐给用户一些购房相关的信息,帮助用户实时掌握市场动态。贝壳自己也会生产一些小视频,通过视听的双重刺激来给用户介绍购房知识。
图4-toC场景
再来看一下B端经纪人使用的场景。我们会在经纪人与用户线上沟通过程中,根据用户的购房需求,提供聊天素材,提高经纪人与用户的沟通效率。以及在转委托和带看后,我们也会根据用户的购房需求以及基于实际的带看行为记录来给出用户可能感兴趣的房源推荐。
图5-toB场景
不难发现,我们智能推荐平台所面临的问题可以用两个"多"来概括,一个是场景种类多变,另一个就是物料类型多样。那么如何去解决这个问题呢?我们通过策略和架构两个方面来入手,解决场景问题时,不断尝试新的策略,并将这些策略中的共性提取出来,指导架构的升级改造。而在架构升级的过程中,需要提高策略的开发效率、降低策略的优化成本,从而实现策略驱动架构,架构赋能策略的螺旋式迭代。
图6-策略与架构的关系
那么我们下面先来看看策略是如何驱动架构升级的,也就是我们的第二部分,贝壳智能推荐平台的演进之路。
3 贝壳智能推荐平台的演进之路
贝壳智能推荐平台架构的演进过程可以大致分为四个阶段:
- V1.0:从无到有,快速搭建
- V2.0:行为收集,离线重构
- V3.0:服务分层,策略配置化
- V4.0:策略扩充,复杂模型预测
图7-贝壳智能推荐平台演进阶段
3.1 V1.0-从无到有,快速搭建
可以看到在1.0阶段,我们的架构在主要分为在线和离线两大部分。由于策略主要以基于规则、热度、CB等简单策略,为了快速开发,离线部分是针对各场景独立产生推荐候选集。而在线部分是每个服务各自为战,一个场景一个服务。
图8-V1.0架构示意图
V1.0小结:
- 从0 -> 1快速搭建
- 推荐策略简单,以规则和基于内容的为主
- 离线生成推荐结果,在线直接获取
3.2 V2.0-行为收集,离线重构
那么在2.0阶段,我们首先要解决下面几个问题:
- 问题1:推荐策略单一,未实现个性化,容易引起马太效应
- 问题2:业务方需求越来越多
- 问题3:需要对推荐效果负责
图9-V2.0架构示意图
3.2.1 用户行为收集
对于第一个问题,我们通过收集前端上报的dig埋点,通过实时处理通道,落地到行为日志中。然后,基于这些行为数据,构建用户画像以及用户-物料的评分矩阵,进而实现基于画像和协同的个性化推荐策略。
3.2.2 离线策略流程化
对于第二个问题,业务需求增多需要我们进一步提升业务的接入效率。我们把离线任务进行了规范,拆分成了5个模块:
- 基础数据层。将底层数据进行汇总,生成不同业务和物料的行为数据、属性宽表等。
- 特征工程层。对基础数据进行聚合,得到房源特征、用户互相等。
- 策略算法层。通用的itemcf、热度计算等算法逻辑实现
- 离线评估层。对召回、排序策略进行离线评估,召回包括准确率、召回率、F1-score、覆盖率等;排序包括AUC、TopN准确率等(后续还增加了mAP和group-AUC等指标)
- 数据输出层。将候选集发布到Redis、ES、Hbase等存储介质,供在线服务查询使用。
通过流程的规范与模块化划分,提高策略开发效率。
3.2.3 指标体系,效果闭环
对于第三个问题,我们在这个阶段主要关心推荐的点击转化率,包括CTR和ROI指标,计算公式如下:
CTR = 卡片点击次数 / 卡片曝光次数
ROI = 卡片点击次数 / 模块曝光次数
我们利用公司提供的指标平台建立看板,来观测天级和小时级的指标变化。并接入了流量实验平台,进行不同策略的线上AB实验。根据线上的AB实验结果,对策略以及离线评估方式进行优化。
V2.0小结:
- 前端日志收集用户行为,为策略优化积累数据
- 离线挖掘模块重构,规范流程提高策略开发效率
- 为效果负责,建立指标的同时,服务支持线上AB实验
3.3 V3.0服务分层,策略配置化
3.3.1 背景与挑战
2.0到3.0阶段的转变有一个很重要的契机是,公司由直营模式到加盟模式的转变。这种模式的转变也给我们带来了很多挑战。首先,平台整体流量突增,需要针对服务的稳定性进行优化来抗住线上压力。其次,加盟模式带来了更多的新业务,推荐需求也与日俱增,亟需提高业务的接入效率。最后,我们需要对已有推荐场景的效果进行持续优化。
图10-V3.0架构示意图
3.3.2 业务层面拆分与稳定性优化
我们根据功能模块和业务的相关性,由强到弱拆分为了应用层、计算层和数据层。
- 应用层。负责对外提供统一接口、根据ab实验分流获取策略配置以及根据场景定制的业务规则对推荐结果进行微调
- 计算层。负责实现各种推荐策略,并对策略进行一定的抽象,增强策略的复用能力
- 数据层。负责数据查询以及数据过滤,使得上层服务不需要感知底层数据的存储逻辑和存储方式
图11-基于业务相关性的服务拆分
我们服务稳定性方面的优化包括以下几点:
- 三层服务可独立定向扩充。应用层和计算层是CPU密集型,数据层是IO密集型,这样可以针对不同功能的瓶颈进行定向扩容。
- 可快速配置策略降级。我们为流量较大的场景都设置了降级的策略方案,遇到流量突增或其他极端情况,可快速修改配置来达到缓解服务压力的目的。
- 支持智能熔断机制。由于数据层要频繁访问外部接口,为了避免个别接口超时拖垮整个服务的情况,我们增加了熔断机制。当一个接口超时严重时,服务会在一段时间内暂时不访问该接口。
- 静态数据返回。我们定时将线上的推荐结果在Redis中缓存,当个别请求即将超时时,我们会获取缓存结果返回,以保证服务接口的正常。
- 其他优化。包括各环节运行时间动态调整、完善的服务监控机制等。
图12-服务稳定性优化
3.3.3 策略拆分与配置化
我们将推荐策略拆分为召回策略、融合策略、排序策略、过滤策略4个策略阶段(后面还增加了理由策略),并通过策略ID唯一标识一个策略。这样一个场景的推荐策略就可以用一个json表示(如图13所示)。
图13-策略拆分与配置化
为了提高策略优化和业务接入的效率,我们开发了一个推荐策略的后端管理系统,用来记录不同策略的详细描述。一个策略的描述提炼了一些关键的信息,形成一种半结构化的存储形式,方便查看目前已有策略的现状,尽量复用已经存在的策略。而在多人协作开发时,我们会要求先在管理后台录入再进入开发,以避免ID冲突问题。
图14-策略管理后台
这样,场景的接入可以通过已有策略的组合快速实现,极大地提高了业务接入的效率。
图15-场景策略配置
3.3.4 提升时效性
V2.0时我们的候选集都是每天更新,并且数据是存在一天延时的。为了提高推荐系统的时效性,我们通过Spark Streaming来实时处理用户产生的行为以及房源信息的变更情况。
我们还开发了一套实时流通用框架,来提高实时策略的开发效率。开发策略时只需要修改数据处理部分,其他的步骤都通过框架封装,减少了代码冗余的同时,也降低了后续的维护成本。
图16-实时流通用框架
V3.0小结:
- 三层服务架构,实现功能解耦
- 实现业务的快速接入,推荐策略灵活可配
- 服务稳定性大幅度提升,拥有应对突发状况的能力
- 引入实时挖掘模块,提高推荐系统的策略时效性
3.4 V4.0 策略扩充,复杂模型预测
我们在3.0之前面临的主要还是公司内部的挑战,从4.0开始,我们迎接的将是整个行业来带的挑战。在当今深度模型大行其道的背景下,我们也需要跟上推荐技术的前沿队伍。采用深度模型、增强推荐可解释性便成了4.0的架构升级所要处理的问题。
图17-V4.0架构示意图
复杂模型线上化流程
我们在在线服务中新增了一个模型层,专门用于处理复杂模型的在线预测问题。模型层实现的功能主要包括在线特征计算与模型服务的调用。离线我们使用的常规的模型训练流程,包括构建样本标签、样本特征等。这里值得一提的是中间的同步层,在特征处理与模型发布时,会根据当前使用的model version来区分存储信息。当特征与模型都ready后,我们在更新线上的model version,实现特征处理预模型同步切换,避免特征处理参数与模型不一致导致的预测异常问题。
图18-复杂模型线上化流程
V4.0小结:
- 新增模型层服务,支持复杂模型的在线预测
- 扩充策略阶段,通过优化推荐理由提升推荐解释性
4 贝壳智能推荐平台的架构设计
在看完了策略是如何驱动架构升级的,接下来我们看看如何做到架构赋能策略。架构对策略的核心价值,是降本提效。智能推荐平台的架构在设计时的原则也围绕着降本提效来进行,可大致概括为阶段拆分、适当预留和配置编程3个基本原则。
图19-架构设计原则
4.1 阶段拆分
阶段拆分是为了提高架构中策略的复用性。之前也提到了,我们把推荐策略分为了过滤策略、召回策略、融合策略、排序策略以及理由策略:
- 黑名单(过滤)策略。主要是对物料的过滤策略
- 召回策略。可以理解为与搜索技术中的匹配(match)一样,负责快速获取与此次推荐有关联的物料
- 融合策略。对多路召回结果的一次合并(或理解为粗排),减少排序压力
- 排序策略。就是通常理解意义上的精准排序
- 理由策略。主要是为推荐物料生成展示给用户的推荐理由,增强推荐的可解释性,包括理由的召回和排序
通过这样的阶段拆分,使得各阶段要解决的问题相对明确,并且可以通过组合不同阶段的策略来实现特定的优化需求。
图20-策略阶段设计
4.2 召回策略配置设计
下面我们来看一下,在策略配置的设计中,我们如何使用"阶段拆分"这一原则的。
召回策略的任务是获取到与用户相关的候选物料,可以将其看成一个用手拿东西的过程。这个过程中需要经过前、中、后三个阶段,每个阶段分别要回答想要获取什么、从哪儿获取以及获取之后做什么三个问题。除此之外,在开始召回前我们还要获取额外信息(通常理解的trigger)。这样,召回策略的主要流程可以分为额外信息、构建查询、实施查询、解析查询结果这4个阶段。
图21-召回策略的设计
我们以房源详情页推荐和大首页推荐为例,这两个场景可以共用相同的候选集,而他们的区别主要是上下文特征的不同。房源详情页场景中的上下文是当前页面浏览的房源(又叫种子物料),而大首页推荐的上下文特征为用户。
图22-候选集和上下文特征
我们将不同的上下文特征用不同的ID表示,并且为了候选集的复用性更强,我们会增加一个字段映射的步骤。具体配置如图23所示:
图23-额外信息配置
在构建查询时,我们设计了一套简单的查询语法来支持"and"、"or"、加权求和等基础运算,避免配置过长。
图24-构建查询配置
我们也为每一个候选集加上了ID标识,在实施查询时,需要配置获取方式以及候选集ID。
为了支持更加丰富的召回策略,我们在解析查询结果也支持通过反射方式来实现不同的解析方法。
图26-不同的解析方式
图27-解析查询结果配置
4.3 适当预留
我们在设计推荐策略ID时,预留了自定义分组部分。自定义分组可以用来当做用户分群、场景分类等,在设计的每一环节都考虑预留一些额外的字段,能够进一步提高了架构的扩展性。
4.4 配置编程
配置编程就是通过将所要实现的功能提取成配置,后续的开发都是基于事先定义的配置格式进行,而不是直接修改程序的代码来实现。比如开发一个itemcf策略,在之前需要写158行代码来完成开发。而现在通过配置化的编程方式,只需要16行配置就可以实现完全一样的功能,大大减少了冗余代码。并且这种方式易于规范,可读性也更强。配置化编程还有一个好处就是可以规避风险。在策略的开发中,如果只需要修改配置,服务的主要逻辑代码很少需要变动,避免了服务上线带来的各种风险。
通过运用"阶段拆分"、"适当预留"以及"配置编程"的设计原则,我们智能推荐平台上的开发效率得到了很大的提升。目前,智能推荐平台已经承接了319个场景,支持了多种推荐策略,包括815种召回策略、68种黑名单策略、26种融合策略、86种排序策略以及133个理由策略等。日均请求量也达到了2.5亿,并且保持优异的服务稳定性,SLA达到99.999%。
图30-策略总量与增长趋势
5 未来规划与展望
最后,我们来聊一下未来规划与展望。接下来我们的工作重心依然会放在降本提效上,主要工作包括搜索推荐架构融合以及核心策略沉淀通用架构两大块。
图31-未来规划##
5.1 搜索推荐架构融合
首先,我们来看一下搜索和推荐的架构融合。搜索和推荐的架构之所以可以融合,主要有两方面原因,一是两者的主要策略都包括召回和排序两大阶段,并且其他一些阶段的策略也能共用,两者策略的复用度很高。二是因为搜索和推荐使用的底层技术类似,比如查询引擎都是ES(ElasticSearch)、向量索引(Milvus)等,并且后端日志的设计也非常相似类似,两者采用同一个架构方便进行统一维护。
融合之后的架构如下图所示,结合了搜索中控-策略服务的微服务架构和推荐高度策略配置化的特点,各取所长。
图32-融合架构示意图##
5.2 核心策略沉淀通用架构
相比于V2.0时我们针对流程通用进行的离线重构,这次的策略通用架构,核心目的是将策略与业务解耦,实现策略在业务间的快速复用。
5.2.1 通用召回策略框架
先来看一下召回部分。其中,橘色部分是我们接下来要做的,会把召回策略分为排行榜类、协同类、表征向量类以及匹配加权类这四大类。
图33-通用召回策略框架
5.2.2 通用排序策略框架
而排序部分会将样本构建、特征工程、模训练中的流程配置化、模块化,降低模型开发的门槛,提高模型的迭代效率。
图34-通用排序策略框架
在设计的过程中,我们会对输入数据进行规范,只要满足格式的数据就能够快速利用这些框架,从而实现公司内各业务能够快速复用策略。后续还可能对公司外部进行开放,打造行业、领域级别的策略平台。
我的分享到此结束,谢谢大家。