干货 | 信息图谱在携程酒店的应用
作者简介
Kuan、Pengfei,主要从事携程酒店知识图谱、问一问智能查询助手、内容信息挖掘平台的建设运维工作,热衷于各类大数据和分布式相关技术的研究和实践。
“对于用户的每一次查询,都能根据其意图做到相应的场景和产品的匹配”,是携程酒店技术团队希望给用户带来的良好体验。为此需要解决三大问题:场景与信息关系缺失、信息丰富度不足以及运维和系统效率不够。
本文主要介绍携程酒店技术团队是如何通过信息图谱的项目一一解决这些问题的,包括:通过将场景与数据抽象为图数据库中的点边,做到关系维护的直观化、维护效率的高效化;结合NLP数据挖掘模块,做到数据来源的丰富化、数据类型的可拓展化;结合信息中台对各数据来源逻辑的整合,做到场景逻辑的可配置化、运维的高效化。
本文将从该项目的项目背景、项目框架、技术框架三个方面,结合Nebula图数据库在项目中的使用与探索,详细介绍信息图谱在携程酒店的应用。
一、背景
目前,在酒店排序方面,携程酒店已经做到了针对不同的用户群体和使用场景给出定制化服务:在不同的场景下,酒店列表页面会有不同的排序,获得了用户价值的提升。相应的,前端展示的各类信息根据场景进行调整和匹配,也可以帮助降低用户决策的费力度。
如当前用户场景是滑雪度假,自然期望前端的展示都能与滑雪相关联,如上图酒店列表页中,酒店的短标签位展示`滑雪套餐`,酒店的榜单位展示当前酒店在当地的滑雪榜排名,以及酒店图片展示雪景下的酒店。
酒店详情页中,酒店相册排序第一的分类为【滑雪精选】,而酒店的其他短标签、榜单同列表页的逻辑一致,展示与滑雪有关的内容。在地理信息位则展示酒店与最近滑雪场间的距离。
酒店和房型的详情信息页,在酒店设施、房型氛围图内容呈现上,也根据滑雪度假场景做出相应的调整。
以上 4 张图简单地描述了携程酒店对于前端各个展示位通过与场景相关联所能达到的展示效果。
而要实现上述功能,首先要把各种场景与内容信息之间建立关联,通过场景就能快速地检索到相关信息进行展示。为此需要考虑以下问题:
缺乏场景和信息的 mapping 关系
信息的丰富性不够,无法支撑场景化
运营和系统不够高效
第一个问题的原因是:在信息图谱项目前,携程酒店前端展示内容相互独立,没有统一的整合体系。如前文提到特色标签中的“带娃爱住”标签,设施标签中的“亲子乐园”标签,尽管从语义上能很直接地将它们同亲子场景关联,但它们一个是特色,一个是设施,除了使用同一个展示位之外,标签间并没有其他的共同点。
另一个比较典型的例子是点评,上图是武汉东湖宾馆的三条点评,内容中分别讲到亲子出行、赏樱和旅游建议,这三条内容目前仅作为酒店点评的展示,并无更多的作用。
而在信息图谱项目中,如果定义了三个场景:亲子、赏樱、旅游,将内容与场景相关联,那么可以实现的事情就更多了。比如一家酒店,其中有 30% 点评提到了亲子,可能可以判断酒店有亲子特色;再如,从提到樱花的点评中,抽取出简短、优美的语句同赏樱场景关联,当传入樱花场景时,这个短句子作为展示补充就可以展示在前端位置…诸如此类的用途可以天马行空的拓展,但实现的关键点是建立场景与信息之间的关联。
第二个问题是信息丰富度不够,无法支撑场景化需求。比如在列表页筛选了滑雪后,没有滑雪相关的图片,也没有相关地理位置信息;在详情页没有滑雪相关的相册信息,也没有滑雪的氛围图,虽然酒店的设施包含滑雪设施,但它没有根据滑雪这一场景做出更高优先级的展示,滑雪设施也没有相关的图片展示,导致酒店推荐生动性不足。
第三个问题是系统和运营不够高效。比如:
新场景&新数据开发成本很大,每个场景上线,需要根据联动位置逐个开发
每个位置接入新信息,需要跟版本发布
数据时效性:无统一标准,时效性不足,存在多个 job 串行的情况:T+x 生效
数据排序:无统一收口方,如一些标签在前后端均有逻辑+运营后台
排查链路长,日常维护效率低
数据标准:有多套标准存在,如怎么定义亲子相关内容?
具体来说,携程酒店前端展示位数据来源于多个服务,如图中标出的展示位,包含了点评、榜单、标签等一系列服务。如果这些服务的联动逻辑没有统一收口方,那么每新增一个场景,相应的展示位都需要进行开发,开发成本就会提升。第二,目前更新 job 存在部分串行,部分数据运营修改可能在 t+x 后才能生效,实时性存在问题。
第三,数据排序、展示逻辑没有统一的收口,前后端都有维护逻辑的地方,造成冗余信息、排查链路变长、维护效率低。最后是缺少统一数据标准,比如判断酒店是否符合亲子特色,需要制定何种标准?酒店有三个特色标签提到亲子,酒店点评中有 20% 内容提到了亲子,这些条件能否判断其符合亲子特性呢?诸如此类的标准,需要准确的定义,场景化的规则才能得以实施。
总结来说,要达到前端各个展示位内容的场景化,需要解决三个问题,一是场景与信息之间缺少关联;二是目前的信息丰富度没有办法支撑场景化;三是系统的运营效率在原有的架构下不够高效。为了解决以上的问题,信息图谱项目应运而生。
二、信息图谱项目:用户预订全流程信息场景化
下图为信息图谱项目的总体框架。
2.1 项目框架
项目涉及到多个系统的提升:
统一的意图识别
展示位置逻辑下沉
关系匹配
信息挖掘
数据源丰富
信息图谱项目主要分为上述 5 部分内容,自上而下第一部分是意图识别,主要通过历史和实时数据来识别当前的具体场景,比如当前的入住筛选项中包含儿童筛选项,那么可以判断当前场景有一定概率是亲子旅游。
第二部分是信息展示逻辑下沉,前文提到前端有十多个展示位,其展示逻辑分别由不同的信息服务维护,这个模块将这些展示位的逻辑统一收口,信息之间便能做到联动。此外,还能起到去重、去冲突等作用,也可以整体地对排序召回等逻辑进行规划。
第三部分是关系匹配,即建立场景与数据之间的匹配关系,这里的数据涉及存量的基础信息数据和通过挖掘得到的增量数据。前期主要通过人工运维的方式将其与场景建立关联,后续则会使用 NLP 手段来自动建立联系。数据与数据之间、数据与场景之间的关系则会使用 NebulaGraph 作为存储和检索的媒介。
第四部分是信息挖掘,即从各类数据源中抽取出与场景相关联的信息或酒店的亮点信息。前文提到过点评的例子:在点评中找到与场景相关联的句子,从中抽取出通顺、优美的短句,把它们作为场景化关联的数据源,在前端进行展示,从而丰富数据源。在信息挖掘模块,总体的流程会涉及 NLP 相关的数据标注、模型训练、badcase 反馈、标注再训练。
最后是数据源,首先要从尽可能多的数据来源中获取信息,加入图谱中。同时要尽可能保证数据的准确性,直接从源头而非第三方来获取数据。为保证准确性,可以加入反查机制,如某个酒店有游泳池的设施展示信息,通过挖掘数据发现其泳池设施早已关闭,那么可以将相关信息同步至运营人员,以此验证数据的准确性。
上述5部分内容中,展示位置逻辑的下沉和关系匹配的建立可以看作项目的地基,其他的模块则是在地基上建起的高楼。
下面具体介绍展示位置逻辑的下沉和关系匹配如何搭建。
前端信息展示逻辑下沉 & 关系匹配
模块的重点是收口前端多个展示位逻辑的数据召回逻辑,建立展示位与场景之间的关联关系。
具体来说,当一个场景进来,系统需要知道哪些展示位要与它联动,相应的展示位的数据召回逻辑也会随之变化。如亲子场景下,诸如“亲子游”、“亲子乐园”的短标签可以很好表达亲子含义,短标签位就适合直接与亲子场景建立关联。而对于美食场景,某酒店在美食榜中名列前茅更有说服力,美食场景则更适合同美食榜单进行关联。建立关联关系后,每个展示位是否需要根据场景变化,就有了统一的标准,进而数据召回逻辑也就得到了统一。
坑位编号 | 名称 | 联动等级 | 页面 |
1 | 列表页快筛 | S | 列表页 |
2 | 短标签 | S | 列表页 |
3 | 列表页图片 | S | 列表页 |
4 | 点评一句话 | S | 列表页 |
5 | 场景房型外露 | B | 列表页 |
6 | 榜单 | S | 列表页 |
7 | 专属推荐 | A | 列表页 |
8 | 头图 | S | 酒店详情页 |
9 | 短标签 | S | 酒店详情页 |
10 | 房型快筛 | A | 酒店详情页 |
… |
上表和图标注了 10+ 个前端展示位和它们的联动等级,联动等级越高代表它越需要贴合场景化,从而也能找到其更多与场景相关联的信息。
场景与展示位建立关系后,场景与数据之间又如何建立关系。上图比较直观,首先要挖掘场景,找到凸显酒店特色或吸引用户的点,接着以场景为基础,找到与场景相联动的展示位,如前文提到的不同展示位可以突出的特点不一,场景与合适的展示位关联可以达到更好的展示效果。最后,通过展示位拓展到相应的展示数据,相应数据可以是已存在的或是为特定场景新增的。
举例说明关系的配置过程,如定义一个滑雪场景,首先判断前端哪些展示位可以与之建立关联,如酒店列表页中快筛短标签、酒店详情页中酒店的头图点评等这些展示位,都可以与其建立联动。接着只需要通过这些展示位找到相应的数据源和数据类型,配置关系即可。
以短标签为例,短标签包含主题标签、设施标签等,这些数据源中可能已经存在与滑雪相关的内容,可以直接在配置后台关联场景关系。如不存在相关内容,也可由运营人员进行添加,又或者通过数据挖掘产生新的数据源,再进行关联。关联过程简单直观,配置完成后,数据会实时地写入到 Nebula Graph 中,前端就可以直接通过滑雪场景筛选到相关的展示内容了。
三、支撑信息场景化的技术架构
先从 Nebula 的架构和集群部署讲起,
Nebula 服务包含 graph 服务、meta 服务和 storage 这三个服务。其中,graph 服务用于处理客户端的请求,meta 服务用于存储分片、schema、用户账号等元数据,storage 则用于存储图中的点边、索引数据。在 Nebula 集群中,数据一致性依赖于 raft 协议,其中 meta 服务和 storage 服务都是基于 raft 协议的集群。而storage 服务相较于 meta 服务结构更为复杂。
具体来说,storage 服务中每一个分片的所有副本共同构成了一个 raft 集群,即 storage 并不是一个 raft 集群,而是存在多少个分片即存在多少个 raft 集群。raft 集群中,由集群的 leader 来处理请求,follower 用来投票、选举、同步日志,并为 leader 提供候补。leader 会定时发送心跳,如一段时间内follower 没有收到 leader 发来的心跳,就会自动开始选举并产生新 leader,来自 graph 的请求无论是读还是写,基本上由 leader 来响应。
由于 raft 协议特点,leader 的投票需要超过半数以上 follower 投票才能选出,一般集群的部署策略是 2n+1 台机器,这样可以容忍 n 台机器产生的问题。
3.1 机器部署
携程酒店的部署方式是三机房分散比例部署,5n 台 Storage Service,将它们分散为 1n:2n:2n,这样任意一个机房出问题,另外两个机房都可以继续使用。但这样部署也存在一定的问题,因其总体而言其实是一个单独集群,读取时必然存在跨机房访问读取带来的时延问题。此外,单集群部署的模式无法支持蓝绿发布方式,也无法基于就近访问来分配流量。
未来对于部署方式的规划是每个机房都能部署独立集群,做到按集群进行流量控制和支持就近访问。当一边集群故障可直接通过域名流量切换到另一边的单边集群,不需要耗费太多的切换成本,而写数据的时候也可以支持蓝绿模式的写入部署。这个模式也让服务出海变得更为切实可行,比如在海外直接部署一个独立集群,可大大减少国内海外读取的时延问题。
raft 让 Nebula 有效地应对由机器本身不可用产生的问题,上述新的集群部署方式则是在 raft 基础上让整个集群具有更高可用性,对于线上应用这样的部署也更符合实际的需求。
讲完集群的部署问题,接下介绍项目的具体架构。
3.2 技术架构
先比较下项目架构的前后变化,上图显示在原来的架构中,客户端请求的每一种数据来源都有其独立的场景化配置,部分数据源由于没有明确的语义则无法支持场景化,这就会导致三个主要的问题:
开发繁琐
实现难度高
信息孤岛
第一点,由于信息展示的逻辑离散、存在多个独立服务,无法形成统一的场景化标准和数据召回逻辑,每个场景化模块需要单独的配置文件和实现逻辑。
第二点,类似酒店图片、酒店问答等类型内容无法与场景直接建立关联,只能单纯通过人工运营的方式建立关联,需要耗费很大的成本。
第三点,各个信息源的维护没有统一的标准,信息之间相互独立,容易造成不同信息源之间信息重复或冲突,比如酒店主题和酒店设施中包含语义十分相似的标签,如果这两个标签同时展示在前端,就会造成信息冗余的问题。
要解决这些问题,则需要搭建一套可以存储各类信息与信息之间、信息与场景之间关系,以及将信息召回的逻辑进行统一收口的系统,称之为信息中台系统。
上图与之前架构的区别,在于把每种数据独立的场景化配置替换成知识图谱模块跟语义标注模块:知识图谱模块用于存储信息与信息之间、信息场景之间的关系,这里会用到 Nebula:通过 Nebula 建立合适 schema 跟映射关系,大部分数据能在两度以内完成查找。语义标注模块则对语义不明确的信息进行挖掘、标注,再与场景建立联系,最终补充进知识图谱。
接下来具体地讲讲中台系统中每一个模块的构成和功能。
信息中台的整体架构从右往左可以分成 4 个模块,分别是信息中台 API 模块、信息图谱模块、知识标注模块和数据模块。
其中,信息中台 API 模块是信息中台对客户端的服务,这个模块起到的作用包含场景获取、数据查询、数据包装,整合数据展示逻辑等。信息中台 API 让相册、标签、设施这些服务由各自包含独立的展示逻辑转化为从统一的来源获取展示逻辑。
知识图谱模块主要整合了数据的召回逻辑,使用 Nebula 作为信息关系的存储引擎。对于基础数据,如设施标签数据,将它们与酒店、场景抽象成点,将它们之间的关系抽象成边。对于挖掘数据,将挖掘产生的短语标签等抽象成点,将它们与酒店、场景之间的关系则抽象成边。这样,在输入场景和酒店 ID 时,即可通过 Nebula 查询语句快速地检索到该酒店下符合场景的所有点的索引信息。另外,通过读取实时消息更新 Nebula 数据,可实现即时更新,而不是 t+x 生效,实时性也得到了很大的增强。
信息标注模块可大幅度地提升数据丰富度,对大量 UGC、酒店描述内容,在其中找到与场景相关联的信息是比较耗费资源的工作,使用 NLP 相关技术则能提高效率。上图中间部分主要画出了数据在整个信息标注模块中的流转过程。
首先预处理点评、图文秀等信息,得到子句、短句放入标注模块进行标注。标注时会使用语义标签(来源于热搜词或者人工定义等渠道,语义标签会直接与场景建立关系,一般情况下这种关系是一对一的,也会存在一对多的情况),标注好的数据会进行模型训练,同静态规则一起进入任务调度模块对数据批量地打标,最后产生的部分数据进行抽样人工 check 之后就可以使用。信息标注模块整合了数据产生的流程,大幅度提升了数据的丰富度和产生效率。
最后,数据模块负责数据的整合和传导,模块数据来源包含信息标注模块产生的各类信息,也包含其他从外部来源同步的数据。这些数据最终通过数据同步框架写入 Nebula Graph 数据库中。
接下来具体介绍数据在数据模块中的流转过程。基础数据如特色数据、设施数据、酒店数据等包含全量和增量数据,全量数据来源于 DB、消息队列、消息接口、Hive 表等,其中 Hive 表直接通过 Hive job 同步 Nebula,而 DB、消息队列、消息接口则通过 nebula-java 客户端同步。
携程酒店结合 Nebula Java 客户端实现了一套可配置化的同步框架,并搭建了信息同步的服务。当数据来源是接口、消息队列时,通过实现相应的接口组装数据,并配置消息字段与 Nebula 字段的映射关系即可实现同步。当数据来源是 DB 时,通过配置取数 SQL 语句和 DB 字段与Nebula 字段的映射关系即可实现同步。增量数据主要来源于消息队列,增量 job 与全量 job 使用相同映射关系,对于增量消息,只需实现组装数据的接口即可实现同步。
除数据同步外,该模块还包含数据运营平台,主要提供 4 个功能:
schema:收口 Nebula schema 操作,Nebula 本身有图形化界面,将 schema 操作收口至统一后台,可便于配置权限、记录操作日志。
监控:数据导入过程中,在 ClickHouse 看板中记录数据、来源、操作类型、主题信息,便于直观地查看数据统计信息。此外当有错误发生时,结合报错信息中日志及 ClickHouse 上的数据,可快速定位到具体点、边、报错的类型、数据来源、消息ID 等信息。
依赖配置:在数据组装时,将前文提到的数据源和 Nebula 字段的映射关系配置在统一后台, job 每次启动会实时读取后台的映射配置,从而实现实时配置实时生效。
重试机制:在数据传输错误发生时,加入重试机制。消息队列这类数据本身有重传机制,只需在数据异常时给出相应标识。而接口、DB 这类数据则会在后续加入重试机制。
3.3 schema 定义和压测
最后介绍数据在Nebula存储的 schema 定义和压测结果。
图谱数据模型分为 4 个大块,分别是标签信息、基础信息、UGC 信息和 GEO 信息。
标签信息中包含设施标签、特色标签、长标签、UGC 标签等点;
基础信息中包含了房型信息、设施信息、政策信息等点;
UGC 信息中包含挖掘出的子句、内容点等;
GEO 信息包含 POI 、省份、城市点等。酒店作为中心点被这 4 块区域所包含,同时与上述每个点都有相关联的边。
此外,最上层抽象了语义标签点,所有与场景建立关联的点都会与语义标签直接建立相应的边关系。这样,当输入酒店 ID、场景 ID,能很快地筛选出酒店到场景路径中所有点的信息。这样的 schema 定义比较符合业务逻辑,但在实际的上线过程中还是遇到了一些问题,比较典型的是热点数据问题。
举例来说,A 类型数据量是百万级,B 类型数据量是千级,每一对 A 与 B之间存在关联,那么关联边的量级可能在十万级或者百万级,查询时 B 可能会变成超级节点影响部分性能。
对此,考虑过几个解决方案。
一是增加分片数,用来解决热点数据集中在某一两台机器中的问题,但这样只是分散热点,并没有彻底地解决热点问题。
二是增加逻辑点,将某个热点分散成多个属性相同、但 VID 不同的点,这些点同中心点连接时,通过 Hash 等方法把边打散,但这样不仅增加了数据导入的逻辑复杂度,在某些情况下还会影响数据与数据之间边本来逻辑的准确性。
也考虑过 follower 读这个方案,由于 raft 协议的限制,只有 leader 能处理请求,在一致性要求不高的情况下,如支持 follower 处理读请求,再结合增加分片数,整个集群中的各个机器的负荷便能得到大幅度的均衡——这个问题需要 Nebula 研发团队提供技术支持。
最终,解决热点问题是在携程系统研发部团队的支持下,通过配置参数解决了个别机器由于热点数据产生的负载过高的问题——方案是分别开启前缀匹配布隆过滤器、加大blockcache。
上表为系统上线前的性能测试图,集群配置为 6 台 graph、5 台 meta、10 台 storage。对于 250+万点、2 亿多条边,在一度查找 1 万左右 QPS的情况下, 99百分位线在20ms左右;同时写入 10+ 万数据时,99百分位线在 40 ms 左右;两度查找 7,000 左右 QPS 时,99线在 32 ms 左右,同时写入10+ 万数据时,99线在 50 ms 左右…...总体来说,Nebula性能上的表现比较符合业务需求和预期。
此外 Nebula 采用天然的分布式架构、活跃的中文社区都是促成携程酒店最终选择其作为信息图谱搭建平台基础设施的原因之一。
四、总结
本文主要从项目背景、项目框架、技术框架三个方面,介绍了携程酒店信息图谱项目所要达到的目标、所带来的提升以及所使用的技术架构;此外还具体介绍了Nebula图数据库在该项目中的使用和遇到的问题。
目前项目已成功上线,在系统和业务层面均为前端内容场景化的搭建带来了不小的提升。未来项目将从Nebula部署方式优化、数据丰富度提升、场景丰富度提升等方面不断迭代和优化。我们也将持续与Nebula官方团队保持良好的交流合作,积极参与Nebula社区的发展与建设。
【推荐阅读】
“携程技术”公众号
分享,交流,成长