哔哩哔哩客服坐席调度系统的演进

文章导读

本文详细探讨了哔哩哔哩客服坐席调度系统的演进,特别是在线客服和工单客服的调度策略。随着客户需求的增加,尤其是在大型活动期间,客服系统面临着突发的高流量和复杂的客户问题。为了提高服务效率和客户满意度,系统引入了多种调度策略,包括均衡分配、熟客优先和虚拟排队等。

同时也对工单系统的调度也做了详细的技术分析。

01 背景

客服系统作为企业与客户沟通的重要桥梁,其中坐席调度作为客服系统的核心组成部分,发挥着重要的作用。本文我们就来介绍坐席在客服系统中的作用,以及如何通过科学的坐席分配和管理。

先说一些概念和遇到的问题,让大家有更直接的认知。

坐席是指什么

"坐席"一词,在客服体系的语境中,指那些致力于卓越客户服务的专业人员。他们不仅是企业与客户间沟通的桥梁,更是解决在线咨询疑惑、高效处理工单反馈的关键角色。在技术上,坐席也可以理解为同时在线的客服账户数量,或者正在接待访客的客服人员数量。

此外,借助先进的人工智能技术与自然语言处理能力,智能坐席也能够与客户展开及时、准确、个性化的解决方案。但是这个更多属于客服智能问答范畴,本文不做过多阐述。

为什么需要调度

在我们的客户服务生态中,广大客户通过各个渠道来寻求解决各类问题,每天的进线量较大,且不时伴随着突发性进线。特别是当诸如BML/BW等大型活动售票环节遭遇障碍时,短短数分钟内即可激增数千次的在线咨询请求。

如,今年的某售票活动部分技能组排队达到千人级别,总体排队达到几千人。

面对这种突发的客户问题,我们既有的服务能力往往难以支撑,进而引发用户排队等候的现象,排队过长会引发很多严重的问题,比如:

  • 因为排队过长,很多用户等待过久,会放弃咨询,但是客服人员还是要接待众多的无效会话,因而浪费了大量的客服人力
  • 在出现排队的情况下,往往客服人力也是紧张的,这样真正有问题咨询的客户反而得不到及时的咨询,进而影响满意度,甚至引发舆情

鉴于此,一套高效、灵活的调度体系是我们亟待构建的。

客服调度的目标与挑战

核心目标是:用较少的客服资源获得更佳的用户体验,提升客服服务效能与用户满意度。如果我们招聘大量的客服,也能让用户获得更好的体验,但是容易造成人力浪费,更多的人手意味着更多的培训成本、管理成本和人力成本。

相较于机器调度的直接性与高效性,客服调度面临着更为错综复杂的挑战:

  • 资源差异的挑战:新增物理服务器经虚拟化后,能迅速投入使用,直接高效。反观客服人员的招募,需历经长时间的培训和熟悉,方能确保其具备上线服务的能力。
  • 技能区别的挑战:每个客服人员归属不同业务,不同业务的技能有区别,难以实现跨业务的灵活调配。即便同属一业务,客服人员的服务能力亦存在差异,而机器差别不大,很多业务可以使用相同类型的机器。
  • 应对突发事件的挑战:新业务需求的上线/变更、系统故障,舆情等不可预见事件的出现,导致进线波动剧烈,为精准预测与安排日常人力带来了极大难度,远非机械调度所能轻易应对的静态环境可比。
  • 作为人类,客服人员享有工作与休息的自主权,同时客服人员出了投入在接线上,还有其他很多工作,比如开会,吃饭,上厕所以及其他临时的工作,而机器调度则无需此类考量。

02 在线坐席调度

2.1 在线坐席调度的基础规则

基于上述的背景和核心问题,我们在设计坐席调度系统时会遵循一些基础规则

  1. 以下红框内的每一个tab在后台会对应一个技能组,技能组是客服人员提供服务的基本业务单位,一个业务下往往有多个技能组。

2)一个客服人员归属于一个或者多个技能组,一个技能组也可以有多个客服

  • 在客服接线前,管理员会给客服分配一个或者多个技能组

  • 每个技能组有对应的上下班时间

  • 客服有接待上限(或者说是饱和度),一般不允许同时接待的用户数超过上限

  • 客服有各种工作状态,如:在线,下线,忙碌(开会,吃饭等)。处于下线或者忙碌状态,一般不会再主动给客服分配用户。

2.2 在线坐席调度系统-第一期

第一期主要是从0到1搭建系统的阶段,比较注重的是分配策略,就是把用户分给对应的客服,因此我们调研了多种策略:

  • 均衡分配策略:这种策略将用户请求平均分配给各个坐席,从而平衡工作负荷,提高整体服务效率。它的优点在于保证了所有坐席的工作量公平分配,防止了某些坐席过度劳累,也防止了某些坐席空闲的情况。
  • 熟客优先策略:根据用户的历史服务记录和需求,将用户优先分配给曾经提供过优质服务的坐席。这种策略的优点在于提高了用户的服务体验,因为熟客通常能够得到更快速、更准确的服务。
  • 上次服务优先策略:将用户分配给上一次为其提供服务的坐席,以提高用户满意度和连续服务效率。这种策略的优点在于可以维持用户对特定坐席的信任,有利于提供持续、一致的服务。
  • 指定分配策略:根据特定条件或需求,将用户请求分配给指定的坐席。这种策略的优点在于可以满足某些特殊需求,或者处理复杂问题。

在进行了深入研究后,我们发现均衡分配策略是业内使用最广泛和最常用的策略,也被广泛应用于各种客户服务系统。这是因为均衡分配策略可以确保所有坐席的工作量公平分配,防止过度劳累,防止坐席空闲,从而提高整体服务效率。同时,我们也发现,熟客优先策略、上次服务优先策略和指定分配策略都有其特定的适用场景,可以在需要的时候作为均衡分配策略的补充。因此,我们的选择是采用均衡分配策略作为基础的坐席调度策略,同时在代码上,我们使用了策略模式(Strategy Pattern),可以根据业务需要灵活的拓展到使用其他策略。

均衡分配

在介绍均衡分配前,有几个名词需要提前解释一下:

  • 饱和度:客服可以服务的最大用户数,在客服被邀请进入系统时会被设置
  • 均衡分配:本系统会在不超过饱和度的情况下,客服均衡获取用户分配

如何实现均衡分配

**

**

以下是我们客服系统中均衡分配的实现逻辑:

注意,分配是以技能组为单位进行分配。假设一个技能组有两个客服,A客服的饱和度为5,B客服的饱和度为10。

  1. 如果A客服当前服务的用户数少于B客服当前服务的用户数,并且都低于各自的饱和度,那么如果有用户进线,系统会优先分配给A客服。

  2. 如果A客服和B客服当前服务的用户数相等,并且都低于各自的饱和度,那么如果有用户进线,系统会随机均衡分配给A或B客服。

  3. 如果A客服已经达到了自己的饱和度,那么如果有用户进线,A客服将不会被分配到该用户进线,该用户将被分配给还没有达到饱和度的客服,并根据上述1和2的原则进行分配。

  4. 如果A客服和B客服都已经达到了各自的饱和度,那么系统将进入排队状态。

排队

这里可以用Redis的Zset数据结构,可以方便的根据用户排队时间进行先后次序排队:

  • ZADD:用于添加元素,Key使用技能组id,每个技能组id关联一个有序集,有序集Member是用户id,Score是用户进入排队的时间戳,这里可以用于添加排队的用户。
  • ZRANK:返回有序集中成员的排名,可用于展示当前排名
  • ZREM:移除有序集中的一个或多个成员,可用于退出排队
  • ZRANGE:返回有序集中指定区间内的成员,可用于客服工作台会话邀请场景
  • ZPOPMIN:返回最低得分的成员,也就是最早排队的成员,可以用于自动进线场景
  • ZCOUNT:返回计算有序集合中指定分数区间的成员数量,可用于计算排队长度
  • ZSCORE:返回有序集中,成员的分数值,可用于查看用户排队时间

以上命令基本可以满足排队场景各项操作。

自动进线和会话邀请

当用户进入排队后,有两种方式可以获得人工服务:自动进线和会话邀请。

自动进线(定时调度):系统会持续扫描未达到饱和度的客服,如果发现有客服尚未达到饱和度,会自动将队列中的用户分配给该客服。

会话邀请:客服人员可以根据自身能力,即使已经超过饱和度,仍然可以邀请排队中的用户进入会话。可以一次性邀请一个或多个用户进入会话。

转接

客服人员在与用户沟通的过程中,发现用户咨询的问题不在此技能组的范畴内,自己无法解答,他可以将此用户转接给其他客服人员,将用户交给合适的客服人员来服务。

总体流程总结

此版本的系统基本解决了分配的问题,但是对于一些突发情况导致的大量进线没有很好的处理。下面一节将介绍大量突发进线的处理方案。

2.3 在线客服坐席调度系统-第二期

背景

在BW/BML售票期间,用户排队现象普遍,排队名次有时超过千人。根据现行业务逻辑,所有排队用户均会被客服接待。这导致用户在达到队列前端时,可能已等待两到三个小时,很多用户早已离线,而客服仍需接待,造成资源浪费。

虚拟进线

为了避免在大量进线时浪费一线客服人力,我们引入虚拟排队概念。将入队超过一定名次的用户引导至虚拟区,在虚拟区中试探用户是否依然在线,如果用户在规定时间内返回,则正常服务,否则关闭会话。该功能上线后过滤大量无效会话,特别是在BW/BML售票期间过滤了几千条无效会话,节约了大量客服人力,减轻了客服压力。

核心流程和设计

我们对比原来增加了虚拟等候区和虚拟排队区,在虚拟等候区如果用户在N分钟没有回应,说明用户已经离线了,此时可以退出队列,不会再进线。

核心流程图

下面我们对整个流程做详细解释

名词解释
详细分配逻辑

假设

当前客服X的最大饱和度为10,已接待9人,剩余1饱和度,客服X虚拟区无用户,某技能组中排队靠前的三名用户分别为A(入队名次33,当前名次1),B(入队名次22,当前名次2),C(入队名次10,当前名次3),系统的虚拟区比例为2,虚拟区名次为20,虚拟区等候时间为N分钟。

调度过程程描述

1)客服X在接受到调度时,由于用户A入队名次大于20,且客服X当前虚拟区比例为0/1=0小于系统的虚拟区比例2,所以用户A将由普通队列转移至虚拟等候区。并由机器人后台发送问候语试探用户是否在线。此时客服X最大饱和度为10,已接待9人,剩余0饱和度,虚拟饱和度为1,虚拟区内用户数量为1。

2)如果N分钟内用户A已就绪(例如回到聊天页面或者发送消息),则客服X将接起用户A处理客户问题。此时客服X最大饱和度为10,已接待10人,剩余0饱和度,虚拟饱和度为0,虚拟等候区内用户数量为0。

3)客服X再次接受调度时,如果用户A在N分钟内依旧未就绪则继续等待,客服X将获取客服B,由于其入队名次同样超过20,所以也会进入虚拟等候区。此时客服X最大饱和度为10,已接待9人,剩余0饱和度,虚拟饱和度为1,虚拟区内用户数量为2。后续客服X将不再接待用户,用户C将继续停留在普通队列等待。

4)如果用户B早于用户A就绪,则客服X优先服务用户B,用户A将进入虚拟排队区等候,直到有新的饱和度空余出来,客服X才能接待用户A。

5)如果客服X有会话结束,即多出剩余饱和度,此时即可接待用户C直接进线。

存在的问题

  • 不同技能组间平均会话时常差别较大,都用相同的入队名次和虚拟区比例来决定是否进入虚拟区等待效果难以保证

  • 在高峰和日常运营期间,固定参数设置可能无法满足需求

  • 虚拟等候区中如果有多个用户同时回来会造成客服爆线

  • 用户在虚拟等候区等待时间过长可能引发不满和投诉

2.4 第三期展望

  • 排队用户进入虚拟等待区的依据调整为排队时长,各个技能组间依照近期会话时长,客服人数等数据在后台实时调整进入虚拟等候区的时长标准与虚拟区比例

  • 进一步提高过滤效率避免虚拟区用户爆线

03 工单坐席调度

前述的都属于在线聊天业务的坐席调度。在客服领域,还有工单客服,他们也有坐席调度。他跟在线调度的区别在于,在线调度在进线那一刻一定要分配一个客服,而工单调度是用户可以先提交工单成功侯,然后再分配处理工单的客服人员。逻辑上就是把创建好的工单分配给对应工单客服人员,因此大家也会称为工单分配。

3.1工单坐席调度-第一期

工单只有在分配给客服后才真正开始处理,才可以和用户沟通、回复,最终解决用户问题。工单分配的效果好坏对工单系统的使用体验至关重要。

工单分配需要确保以下几点:

  • 实时性:工单分配的效率直接影响着工单处理的速度、用户的使用体验;
  • 准确性:某一类问题的工单只能分配给对应的工单组人员进行处理,比如用户针对会员购业务下单过程中的问题工单,只能分配给会员购工单组,不能分配给直播工单组;
  • 公平性:同一工单组的全部工单需要相对均衡的分配给所有空闲客服,分配不能出现明显倾斜,导致闲的闲死、忙的忙死。
  • 优先级分配:产品策略上要求,在保证公平性的基础上,要兼顾一定的优先级逻辑,针对待分配的工单和空闲客服分别为:
  1. 待分配的工单:待分配的工单有四种来源,分别为被释放、被转交到组、创建时指定分配到组、自动分配到组,优先级依次由高到低;
  2. 空闲客服:被释放和被转交到组的工单之前已经有过处理人,因此再次分配时,如果上次处理人在候选客服之列,优先分配给上次处理人;因此客服的分配优先级为:上次处理人 > 空闲客服(空闲客服间平均分配)。

其中,准确性依靠流转触发器模块实现,流转触发器是工单系统引入的规则配置,用来约束哪些业务的工单分配至哪个工单组,分配到组逻辑完全遵循流转触发器,配置正确则保证分配正确。公平性和优先级通过下述分配流程实现,并专门讲到实时性的设计要点。

分配逻辑

定时分配过程由Railgun定时任务触发,当前触发周期为1min。分配流程为每次从待分配队列获取前N个(数量可配置)工单,针对每一个工单,获取对应的客户队列,从前往后匹配客服,匹配到则将工单分配出去,并从待分配队列剔除,客服饱和度+1,未分配到的工单等待下次分配。

工单待分配队列

工单待分配队列基于 Redis-Zset 结构实现,存储所有处在待分配状态的工单,不同来源的待分配工单(释放的、转交到组的、创建是指定分配到组的、自动分配到组的)赋予不同的分配权重,保证释放的工单在前,自动分配到组的工单在后,相同类型的(比如两个工单都是释放的)根据时间顺序(比如释放时间)从前往后分配,分配时每次扫描窗口限定为对头的一定数量工单,从而实现优先级分配和抢占式分配。

之所以额外采用 Redis-Zset 实现待分配队列,是因为如果直接读取DB数据构建队列,同时涉及到工单信息表(筛选出待分配的工单)和工单操作记录表(工单是经过何种操作来到的待分配状态,从而确定分配优先级),数据量和计算量都很大,无法保证分配的效率。

  1. 待分配队列设计
字段 格式 描述
Key tobeallocated_ticket_list_{工单组id} 每个工单组独立一条待分配队列
Score {weight} 调度权重,值越小,优先级越高
Member {ticket_id} 待分配工单的工单id

因此,在调度权重的设计上,weight(释放的) < weight(转交到组的) < weight(创建是指定分配到组的) < weight(自动分配到组的)。权重计算逻辑如下:

  • 权重计算公式:weight = weight1 | weight2,高位weight1负责不同类型的待分配工单排序,低位weight负责相同类型的工单按时间排序;
  • 设定工单系统开始时间 startTime = "2023-01-01 00:00:00", 结束时间 endTime = "2060-06-16 00:00:00",逝去的总秒数,为1182038400(10位)
  • 因此可令 weight1 = type * 1e10, 其中释放的工单type为1,转交到组的工单type为2,创建是指定分配到组的工单type为3,自动分配到组的工单type为4
  • weight2 = time.Since(startTime) / time.Second,即从startTime开始逝去的秒数
  • 调整后的权重计算公式:weight = weight1 + weight2

效果:

不同类型的工单分段存储,可读性强,易调试。

  1. 待分配队列操作

添加待分配工单到队列:ZADD tobeallocated_ticket_list_{工单组id} {weight} {ticket_id}

从待分配队列取出工单:ZRANGE tobeallocated_ticket_list_{工单组id} 0 N

剔除已分配的工单:ZREM tobeallocated_ticket_list_{工单组id} {ticket_id}

判断工单在待分配队列是否存在(不存在则添加,加固逻辑):ZSCORE tobeallocated_ticket_list_{工单组id} {ticket_id}

3.2工单坐席调度-第二期

背景

上述工单分配策略通过周期性的获取一段待分配工单,并采用随机分配算法将每个工单分配给一位在线未饱和客服,直到所有客服饱和或者工单分配完毕。

这种基于当日配额贪心式分配的策略理论上非常公平,但在实际场景下也有不公平的一面,因为即使是同时间段提供服务的一批客服,上班(准确说是上线)时间错开个几分钟到几十分钟也是非常常见的,这样最先点击上线的客服就有长达几十分钟的时间"独享"前夜遗留的大量工单,待所有客服都上线后,当日增量的工单又是均匀分配,因此整体来看,早上班的客服会比晚上班的客服分配到更多的工单。

举个例子,假设前夜遗留1000个工单,每日工单新增4000单,总共有40位客服进行接单,其中4位客服上班时间第一时间比如9:00上线,其他客服晚半小时9:30上线。

则早上班的4位客服当日处理工单量为:1000 / 4 + 4000 / 40 = 350,其他36位客服处理工单量位:4000 / 40 = 100,于是不均衡出现了。

优化方案

针对第一期方案基于日配额进行顶格分配的策略存在的不公平问题,在和产品、运营同学齐力讨论下,引入瞬时饱和度概念,即每个客服同时能处理的工单数量。

新的分配方案是:首先给每一位客服配置对应的日饱和度和瞬时饱和度,分别限制该客服一天最多能处理的工单量上限和同时能够并发处理的工单量上线,然后在自动分配流程中,分别获取客服当前的饱和度以及当前处理工单数,分别与日饱和度和瞬时饱和度做比较,只有都不饱和时才可继续分配工单;如果因为瞬时饱和度超了,只能等客服至少处理完一单才可继续分配,如果因为日饱和度超了,则当日不可再继续分配工单。

通过引入瞬时饱和度,对工单的自动分配效果有两点提升。一是客服的日配额可以较为均匀的分散在一天的各个时间段,不至于短时间内被打满,然后在接下里的时间里无单可接,负荷更为平滑;二是前夜遗留的工单不会再集中分配给早上班的客服,因为在给他们分配对应瞬时饱和度的工单之后便停止分配,直到新的客服上线后再继续分配给新客服,不会再因为上班时间小时级差异而导致显著的分配不公平现象。

效果

通过日饱和度和瞬时饱和度相结合的工单自动分配机制,从时间段(一天)和时间点(同时)上同时限制客服接单量,使得工单分配效果更公平,客服负荷更平滑。

04 总结

本文详细探讨了哔哩哔哩客服坐席调度系统的演进,特别是在线客服和工单客服的调度策略。随着客户需求的增加,尤其是在大型活动期间,客服系统面临着突发的高流量和复杂的客户问题。为了提高服务效率和客户满意度,系统引入了多种调度策略,包括均衡分配、熟客优先和虚拟排队等。

展望未来,客服坐席调度系统可以在以下几个方面进行进一步优化:

  • 流程优化:在用户进入排队前给出当前的排队长度和需要等待的时间,用户自主选择是否进入排队
  • 优化虚拟排队机制:进入虚拟等待区的依据调整为排队时长,让用户有直接的时间感知。各个技能组间依照近期会话时长,客服人数等数据在后台实时调整进入虚拟等候区的时长标准与虚拟区比例
  • 调度策略的多样性和灵活性:调度策略可以根据用户的信息、问题类型等因素来分配客服坐席,同时根据坐席的服务质量和服务水平进行评估和调整。这种灵活的分配策略有助于应对不同客户需求,提供专门服务
  • 工单分配更智能化:目前的分配校验因素涵盖了客服在线情况、日配额、瞬时饱和度这些,可以归类为分配的硬性阻碍因素,要么是客服无法处理工单(离线时),要么来不及处理工单(超过配额或并发度,超过处理能力),硬性阻碍因素需要被满足从而让工单能够被处理,在此基础上还可以考虑一些让工单更高效、更熟练的被处理,让客服更轻松、更专业处理工单的软性加成因素,比如结合客服历史的工单分配情况、工单处理时效等,考虑到客服之前处理过相同类型或类似诉求的工单,比如涉及大会员退款、用户账号找回等,已具备该领域知识或者熟悉操作流程,可以优先考虑分配本单给他从而优化效率,此外也可以支持客服主动打标签来表达对某类工单的偏好或厌恶处理、历史处理工单中的用户评价等等。

通过这些优化措施,哔哩哔哩客服坐席调度系统将能够更有效地应对未来的挑战,提升服务质量和用户体验,为公司创造更大的价值。

参考:
www.bilibili.com/opus/829931...

redis.io/docs/latest...

tech.meituan.com/2021/09/30/...

zhuanlan.zhihu.com/p/43795895

-End-

作者丨小雄,Jayce,四百块、xiulin

相关推荐
小李小李不讲道理21 小时前
行动+思考 | 2024年度总结
前端·程序员·年终总结
聪小陈2 天前
圣诞节:记一次掘友让我感动的时刻
前端·程序员
百万蹄蹄向前冲2 天前
2024不一样的VUE3期末考查
前端·javascript·程序员
陈哥聊测试3 天前
软件格局在变,谁能扛起国产替代的大旗?
安全·程序员·产品
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭4 天前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
少年姜太公4 天前
从零开始详解js中的this(下)
前端·javascript·程序员
凌虚4 天前
Kubernetes APF(API 优先级和公平调度)简介
后端·程序员·kubernetes
小华同学ai4 天前
ShowDoc:Star12.3k,福利项目,个人小团队的在线文档“简单、易用、轻量化”还专门针对API文档、技术文档做了优化
前端·程序员·github
小青鱼6 天前
AI编程-Cursor从入门到精通系列之常用概念及解释(二)
人工智能·程序员
捡田螺的小男孩7 天前
参数校验的十个建议!收藏好,别再给测试机会提bug~
java·后端·程序员