rise 2018-05-15
本文主要分享整个淘宝客服平台架构演进的过程,以及当前服务如何结合 AI 赋能的实践。
本次峰会以软件开发为主题,阿里巴巴云零售事业部高级技术专家古墨在技术架构遇到业务架构专场带来了主题为“淘宝智能客服架构演进之路”的精彩演讲。
本文分为三块跟大家分享最近三年来淘宝在商家客服方面的架构演进:
阿里电商客服业务背景介绍
客服行业的历史由来已久,在近五到十年的时间里面,它经历了如下三个阶段:
对于阿里电商平台而言,每天在淘宝上会有数千万的消费者,他们每天的咨询量可达上亿次。相应地在商家端,也会有几百万次与消费者的互动。
每逢双十一等活动期间,该数字对于商家虽然变化不大,但是消费者的咨询量会有至少 10 倍至 20 倍的增长量级。
因此对于整个平台的客服工具而言,需要向着智能化和数据化的方向发展,以提高商家的能效和消费者的满意度,同时这也是我们解决问题的重点所在。
由于淘宝的服务绝大程度上来自于商家,因此提升商家客服的服务质量就能够提升整个平台的满意度。
淘宝智能客服架构演进之路
根据业务发展,我们的架构演进分为三个明确的阶段:
第一阶段:分流系统架构
举例而言:当买家登录手机淘宝,找到某个商家想咨询问题时,一旦他点击了旺旺头像,系统便触发了一次分流的操作。
像苏宁或小米之类的卖家,由于后台拥有十到上百位客户人员,因此系统需要通过分流来选取一位合适的客服提供服务,进而建立会话。由此可见,这是 IM 聊天过程中的一个关键节点。
在今年的双十一期间,整个分流系统面临着很大的流量压力。由于每一条聊天消息都要流经该系统,它们对于系统性能的挑战非常巨大。
一旦系统出现抖动或 RT 变慢,全网的服务都会受到影响。因此为了应对巨大的吞吐量,我们会尽一切可能缩短 RT。
基于上述需求,我们制定了如下不同的解决方案:
为了追求足够巨大的吞吐量和足够短的 RT 要求,同时还要兼顾特殊的业务规则、状态变化和用户设置,我们从外部将许多变量的信息同步到系统内部。
而在带有变化事件的变量进入系统之后,为了保证整个系统的稳定性和业务的合理性,我们搭建了一套读写分离的架构。
我们将整个查询的逻辑放置在一个系统之中,而将所有更新状态的变化放置在另一个系统里。两套系统之间通过缓存的方式进行对话。
因此对于读数据而言,我们能够利用缓存这种极佳的实时性技术,最大限度地提升 QPS、并降低 RT。
另外,为了进一步缩短 RT,我们将复杂的计算也放到了后面的更新操作中。通过提前预判下一次分流时应当分派给哪一位客服,我们就可以直接进行更新操作,从而简化了查询和整个计算的复杂度。
上图的右上方展示的是商家的接待端在双十一大促时的咨询状态。虽然系统实现了分流、并具有很快的 RT 和吞吐量,但是由于并行接入的咨询请求过多,就算系统能够承受,具体服务的客户人员也应接不暇。
鉴于商家能够招聘客服的人数有限,我们提出的相应解决方案是:以机器人和分流排队相结合的方式,帮助商家应对高发的流量。
上图的下方是排队功能的流程展示:所有进入服务咨询的买家会被分配一个虚拟账号→该虚拟账号对接后端阿里店小秘的服务机器人→机器人通过 AI 来对接买家,并对简单问题予以回答。
如果买家不满意答复,则可选择转到人工→转人工后,根据分流和分组的逻辑,将其纳入排队→进入排队之后,后台调度系统进行买家的出队和客服的分派→创建一个接待会话,由客服跟进后续的接待。
我们之所以引入会话的概念,是因为客服主管要为客服团队设定一个合理的接待上限,以控制同一时刻一次性接入的人数。
例如:耐克的淘宝网店,就严格地认为一个客服人员一次性最多只能同时接待 5 个顾客,倘若超过则会造成服务质量的下降。
另外,我们对整个链路还设置了一个完整数据的埋点,通过实时统计,来帮助各个商家完整地观察到当前店铺的接待情况。
其中包括:有多少人在被机器人服务、有多少人在排队等待、有多少人在被人工接待、每个人工接待的时长情况、以及响应的速度等。客服主管能够通过观察后台情况,来衡量整体的服务状态。
由于业务条件的限制,我们设计和采用的排队技术框架与业界不尽相同。
首先,由于旺旺集成在手淘的各个版本之中,且可以被直接用于聊天,因此在用户端上就会出现横跨多端、多版本的可能。
而我们的排队逻辑是做在前端页面里的,因此我们很难保证在老版本的客户端上能够具备新的能力。
其次,由于我们的旺旺、千牛等处于不同的系统之中,而阿里这个大型平台已将每个业务系统拆分得非常细。
因此要保证跨多个客户端、多个服务器的数据、规划和队列的一致性,我们所付出的成本会非常高。
所以我们需要做到如下方面:
在将买家的请求分配给合适的队列,并通过排队调度来管理客服时,我们曾对如下问题进行了不同尝试:
集中式会话管理的高并发处理:使每个客服的接待分发数不超过设定的上限。
由于在 Java 中我们通常倾向于用无状态的方式实现每一个应用,而各个客服却分布于不同的机器之上,因此我们设置了一个类分布式锁来进行实时查询,如果发现客服应对的人数超过上限,就停止服务。
对于由于机器无状态的竞争所引发的分布式锁的开销,我们通过采用 ZK(zookeeper)来管理商家的分片,并用单线程的机制予以处理。
我们让处于同一台机器上、同一个分片的所有商家都使用同一个线程来进行处理,从而避免了与竞争有关的锁问题。
此类带状态的分布式处理机制,带来的最大问题是 failover。即:由于每个用户只存在于单台机器上,而无任何备份,如果机器因大流量或其他问题而宕机时,我们如何才能做到在不丢失状态的情况下,快速地恢复这些用户呢?
我们采用了一种强壮的 failover 机制,保证在机器或队列出现问题时,能够在大约一至两分钟之内重新启动该设备,恢复整体状态。
队列存储的处理:由于商家的促销活动时间不一致,我们不可能做到全网调度,因此必须做成“开关”让商家自行设置。
同时在经常创建不同的队列时,由于我们的排队机制完全依赖于分组,而分组的力度和数量是不可控的。
因此我们采用了 MySQL 的方案,来设置这种开关,从而可以随时动态地大量创建或销毁分组。
关于“快入队,慢出队”的现象,由于买家的数量和咨询量会在活动高峰期出现骤增,客服则会因为能力有限,而“消化”速度缓慢。
因此我们采用了一种 pull 的方式,在保证流量能够快速进入的基础上,客服凭借分组、并依据自身能力的状况,不停地从同一个队列里面进行拉取。
排队数据的上帝视角:动态创建副本的能力、需要支持各个维度的查询、以及排队优先级和固定分组等方面因素,都会给 MySQL 的调度能力以及吞吐性能提出非常高的要求。
在双十一大促时,为了让 MySQL 具备支持 top1000 商家的能力,我们以分布分表的方式对 MySQL 进行了整体容量的规划,并且通过 MySQL 的复杂能力来快速地支撑业务。
当然我们也遇到了一些新的瓶颈,为了能够继续支撑下一轮双十一大促,我们正在考虑对性能进行进一步的优化。
第二阶段:客服业务系统架构升级
前面提到的是最为基础的、最为核心的服务分流与排队。但是随着业务的发展,我们发现客服接待可以从整体上分为三个角色:消费者、客服和主管。
只有这三种角色实现了互动或联动,才能形成最为合理的体验关系。根据统计,在我们的平台上约有近百万名职业的客服人员。
如果按照人均三千或五千元的月收入来计算的话,客服行业的一年总支出成本高达数百亿。因此我们亟待通过工具或自动化的方式,帮助他们节省此类成本的支出。
在产品能力上:
有过业务开发经验的程序员都知道:功能需求往往是一股脑被提出的,而留给我们开发的时间通常比较紧迫。
如上图右侧所示,为了能让业务“跑起来”,系统在整体上会呈现出“垂直”的基础架构:
因此如果对业务拆分得不合理的话,就会造成 C 端的业务和 B 端的业务共同被放置在同一模块里。那么只要出现过大的流量,商家的系统就可能会出现较大的风险。
面对上述情况,我们通过细致的梳理,围绕着交易关系这一核心本质,对整个接待过程进行了较为合理的拆分,在 IM 通道上面沿着用户的互动行为,可分为:买家端行为→千牛→商家端行为。
如上图所示,对于每一端的每一种角色,又可分为售前、售中和售后三种场景。
而对于客服则涉及到各种淘系业务的操作,并能与自己内部的 ERP、MS 以及后台自建系统相连接,最终实现各个场景的互通与联动。
我们在此提出了新想法:以场景作为切面,将消费者、客服和业务系统有机地结合起来。
如果在通道两端有行为发生时,我们可以将交易事件或是用户行为事件,加上 IM 聊天事件作为输入源,最终推动整个业务场景不断前行。
下面我们将上述过程抽象为一个业务描述:
例如:买家进来咨询了一种商品,商家给予推荐;在买家下单之后,商家要提醒买家尽快付款;或者在买家付款后修改送货地址。
而前面提到的“商品推荐”,则需要推荐团队的服务能力,实现基于内容的商品推荐。
在具体实现中:
基于上述场景,我们对业务平台进行了重新搭建。
首先将业务动态地进行了纵向连接,然后在此基础上对核心功能予以了抽取,并以卡片的形式在通道上进行交互。此外,通过对复杂场景的实时计算,我们也定义了各类事件。
对于前端,我们通过订阅系统来实现各种服务的注册、发布与订阅,而通过插件框架来负责第三方服务的接入。
消息通道的控制实现了前端框架与底层以及服务窗的交互。如前所述,通过事件将各个服务流程进行串联,我们形成了如上图所展示的核心业务架构。
对于前端遗留的一些需要写入核心系统的业务代码,我们将它们拆分成了买家端自助服务、分流服务、面向客服的工具和面向客服主管的工具四个业务层系统。而图中的下方是我们的后台底层大平台。
由上可见,在转变为基于事件模式之后,好处就在于:只需要按照我们所定义的标准对新进的服务人员予以接入,订阅其所关心的事件和处理的机制。通过识别出所涉及到的场景和与之对应的调用服务,最终实现标准化。
客服业务系统与 AI 能力的融合
由于我的团队是做平台的,而 AI 场景则是由另外一个算法团队来实现的,因此双方需要进行算法相关的对接。
我们提供了一整套服务注册、发现和订阅的关系。虽然同为商品推荐,但是应用于“航旅”方面的推荐算法会与带有图片和搜索功能的“女装”推荐模式截然不同。
当前我们主要运用的还是基于规则路由的机制,但是随着服务场景和服务提供者的增多,我们会更多地融入基于 AI 的决策机制。
在将 AI 与各个 IM 通道相结合的方面,我们基于会话的框架设计,完全可以对标 Facebook 的 Messenger 和微软做的 Bot Framework。所有接入的聊天场景,不管是机器人还是解决方案,都具有会话完成的机制。
系统籍此可以获悉某个传递过来的消息或请求,是由哪个用户在何种场景下触发的。
过去的单轮交互是:有一个请求进来,就给出一个答案。而如今 AI 所应对的复杂业务一般需要进行多轮交互。
如前面提到的航旅推荐的例子:在交互了是否要旅行之后;需要进一步询问是国内还是国外游;如果是国外游的话,还需询问目标地区。可见多轮交互需要 AI 具有语意匹配和意图识别等较强的交互能力。
为了让买家在使用 AI 时有更好的体验,我们在给出算法接入时,允许对方自定义菜单。他们通过沟通,将期望买家输入的答案设置到菜单中。
如此交互式的提醒,不但省去了买家的打字输入,又能固化其反馈的结果。这种友好的交互也提升了平台的整体处理能力。
由于我们本质上是通过基于消息驱动的逻辑来实现的,如上图从左至右所示:事件源接入→标准化→安全脱敏→事件中心与调度中心的控制。与此同时,外面的 AI 服务接入于此→注册授权→开放接口→整体监控。
我们之所以将 AI 的服务能力单独划分出来,是因为需要通过与其他团队合作,来实现外部的搜索、意图识别、知识库、多轮交互、情感分析等能力。
我们的 Bot 不仅可以与买家端交互,也可以与客服进行交互。类似于店小秘,作为认知服务的 API 可供各个业务方去调用。
对于用户的聊天数据、客服的绩效、其当天的状态、每个客户角色的数据、以及店铺的商品数据,我们通过底层数据的沉淀功能,可供不同场景进行调用,从而实现了快速开发和轻量级的服务提供。
总结
结合场景抽象出业务本质的模型来指导设计:根据前面所提及的基于事件驱动的概念,大量的事件都是由商品交易或聊天互动所触发产生,并形成了联动场景。
我们可以通过一层层的切片来构建一个个具象的场景。而从整体的角度来说,不同事件的组合又能形成不同的驱动模型。
跟随着业务的复杂性不断的调整和优化架构设计:我们没有必要一定采用所谓“最牛”的中间件方案。只有最适合自己的业务场景才是最好的架构设计。
团队成员统一架构上的认知:我常在团队里说,“架构只有适合与否,没有好坏之分。使用一个好的架构,你当然能够实现某个业务需求;而使用一个差的架构,你同样也能最终实现该业务需求。”
因此全部团队成员都应当有一致的架构认知。只有这样每个人才能在编写业务代码时,主动思考自己所实现的功能应该如何在整个架构体系里达到平衡与和谐处理,以及放置在何处才最为合适。
相反,如果团队成员对于架构的认知不一致,那么就有可能会导致组织内部的代码风格和运行方式出现不一致的情况。因此统一认识对于带领团队去满足需求和实现业务都是至关重要的。