01GuideAI面试机器人利用灵犀智能语音语义平台的人机语音对话能力,模拟招聘人员与求职者之间的多轮语音交流,达到在线面试的效果。本文详细介绍了AI面试机器人的后端架构组成、对话引擎设计、资源需求预估策略、服务性能优化方法。AI面试机器人上线一年多来,已收到数百万次面试请求,大大提升了招聘人员的招聘效率和求职者的面试体验。02项目背景58同城生活服务平台包括房产、汽车、招聘、本地服务(黄页)四大老牌业务。平台连接了大量的C端用户和B端商户。来源、职位、生活服务等信息(我们称之为“帖子”),平台将这些帖子分发给C端用户供其浏览,帮助其获取所需信息,并帮助B端商户进行分发和发布。传播信息以获取目标客户,为提高B端商户获取目标客户的效率,提升C端用户体验,平台在个性化推荐、智能连接等方面不断进行产品创新。以招聘为例,由于2020年疫情的影响,传统的线下招聘面试方式受到了很大的冲击。在该平台上,求职者通过微信、视频等方式在线申请面试的人数激增。一次只能有一个求职者建立在线视频面试通道,导致求职者与招聘人员之间的链接成功率低。为提升求职者的用户体验,提高招聘人员的面试效率,58同城TEGAILab联合招聘业务线等部门打造了一款智能招聘面试工具:魔幻面试室。产品主要由客户端、音视频通信、AI面试机器人三部分组成(参见:人物|李忠:AI面试机器人打造智能招聘)。本文将主要关注AI面试机器人。AI面试机器人利用灵犀智能语音语义平台的人机语音对话能力,模拟招聘人员与求职者之间的多轮语音交流,达到在线面试的效果。一方面可以解决一个招聘人员只能响应一个求职者在线面试请求的问题,提高招聘人员的工作效率;另一方面可以满足求职者随时随地进行视频面试,同时可以将个人简历从传统的文字描述和介绍转换为更加直观生动的视频自我介绍.本文详细介绍了AI面试机器人后端架构的组成、人机语音对话引擎的设计、如何预估资源需求以应对流量膨胀、如何优化服务性能以保障AI面试机器人整体服务的稳定性和可用性。03AI面试机器人后端架构AI面试机器人架构如上图所示,包括:1.接入层:主要用于处理与上下游的交互,包括与音视频终端约定通信协议;提取面试中的用户画像,提取机器人用户交互时间线信息发送至招聘部门。2、逻辑层:主要用于处理机器人与用户的对话交互,包括将机器人的提问文本合成为语音数据发送给用户,向用户提问,使机器人能够“告诉它”;用户回复后,会通过VAD(VoiceActivityDetection)对用户的回复语音数据进行切分,将流式语音识别为文本,让机器人“听到”;对话引擎根据用户的回复文本和语音图确定回复内容,然后合成语音发送给用户。实现机器人与用户的“交流”。3、数据层:存储语音图谱、对话记录、标注信息等基础数据。4.Web系统:可视化配置演讲结构、对话策略、标注采访对话数据。04AI面试机器人与用户交互的整体流程一个完整的AI面试流程如上图所示,可以分为面试前、面试、面试后三个阶段。面试前:主要是建立通信链接,初始化资源。AI面试机器人与音视频终端之间的语音信号通过UDP传输。音视频与AI面试机器人通信所需的IP和端口需要动态维护。音视频端通过SCF(SCF是58自主研发的RPC框架)接口发起采访请求。一方面,请求实时动态获取AI面试机器人的IP和端口资源,用于后续面试过程的音视频采集。语音信号发送给AI机器人,另一方面AI机器人需要发送IP和端口来响应用户的语音信号。由于SCF支持负载均衡,音视频端发起的采访请求会随机打到AI采访机器人服务集群上的某台机器,此时这台机器上的AI采访机器人获取IP通过SCF透传的参数确定音视频终端的端口号。队列使用队列的数据结构来存储可用的端口对),轮询第一个可用的端口对(由发送端口和接收端口组成的对),如果获取成功,则服务将IP和本机端口通过SCF采访请求接口返回给音视频端,然后双方就可以进行UDP通信了。采访完成后,服务会将端口对推送到可用端口队列。如果获取端口对失败,服务会通过SCF接口向音视频端返回一个通信失败码,音视频端可以重试或放弃访问请求。建立通信过程:在语音信号传输过程中,我们使用RTP协议作为系统中的音频媒体协议。RTP协议即实时传输协议(Real-timeTransportProtocol),为网络上的语音、图像、传真等各种需要实时传输的多媒体数据提供端到端的实时传输服务。IP网络。RTP消息由两部分组成:标头和有效负载。RTP头:属性解释:该属性解释了VRTP协议版本的versionnumber,占2位,当前协议版本号为2Ppaddingflag,占1位,如果P=1,则报文尾部填充一个或多个附加的8位数组,它们不是payload的一部分X扩展标志,占用1位,如果X=1,则扩展头CC参与源号,CSRC计数器,4位,表示CSRC标识符的个数数字M标志,占1位,不同的payload有不同的含义,对于视频,它标志一帧的结束;对于音频,它标志着会话的开始。PTpayloadtype,占7位,用于指示RTP报文中的payload类型,如音频、图像等,多用于流媒体中区分音频流和视频流,方便客户端分析。序号占16位,用于标识发送方发送的RTP报文的序号。每发送一条消息,序号加1。当底层承载协议使用UDP时,该字段可用于在网络状况不佳时检查丢包。同时,可以利用网络中的抖动对数据进行重新排序。时间戳占32位,反映了RTP报文第一个八位字节的采样时间。接收端可以使用时间戳计算时延和时延抖动,进行同步控制。SSRC用于标识同步源。可以随机选择标识。参加同一视频会议的两个同步源不能有相同的SSRC。每个CSRC标识符占32位,可以是0到15。每个CSRC标识RTP消息载荷中包含的所有契约源。面试过程中:在此过程中,AI面试机器人首先发送开场白,开场白文本通过tts(TextToSpeech)合成语音数据,语音数据经过编码、压缩后发送至约定音视频终端的IP和端口,用户根据听到的问题做出相关回应;AI面试机器人对接收到的用户语音流进行解码,通过vad分句和流式语音识别,将其识别为文本。对话引擎根据用户回复文本和语音结构状态图确定回复内容。AI采访机器人与用户持续交流互动,直到演讲结束或用户挂断采访。面试结束后:一旦AI面试机器人接收到关于面试结束的音视频请求,AI面试机器人会回收在面试准备阶段申请的资源,如端口、线程等job、年龄等信息)提供给招聘方,方便商家对面试对话进行筛选、记录和存储。录音解决方案:05对话引擎的核心功能在整个面试过程中,AI面试机器人与用户的交互是基于语音过程由对话引擎驱动的,其中语音是一个有向无环图,且初始语音图为语音的两个分支(所有节点的边<=2),由于结构简单,机器人对话机械化,用户回答问题的意愿低,面试完成率(占比回答了机器人提出的所有问题的用户)只有20%。因此,为了提高用户说话的意愿,提高机器人的智能对话能力,我们重构了语音结构,设计了多分支语音(一个节点的边>=3)。如下所示,用户可以,以个性化的方式用不同的脚本回应用户。新剧本结构上线后,采访完成率超过50%。同时,为了更细粒度地设计对话策略,我们在策略链上设计了节点级策略链,可以为单个节点定制个性化的对话策略,满足个性化的对话需求。数据层面:为了实现多分支语音,我们重新设计了语音相关的数据结构,抽象出一些数据实体包括:语音表、语音节点、语音边等。Shushu节点通过Shushu节点绑定书书编号,同时维护书书文字等属性。Shushu边维护节点之间的拓扑关系。有开始节点和结束节点。书书边通过边号与此绑定。边上命中正则化、语料库等规则,并且可以使用边id为这条边自定义自己的规则。策略链通过策略链号绑定到不同的策略,单词和节点通过策略链号绑定到不同的策略链。代码层:抽象出边、节点、语音、语音状态的概念。边和节点是数据层的映射。边缘还维护命中逻辑,例如正则化和语料库。speech类维护了开节点和speechGraph等关键信息,speechgraph是整个speech拓扑的映射,它维护了从这个节点开始的节点到节点边集的映射,speechstate类维护语音的当前状态,包括语音的类别和当前的Node,系统可以根据语音的当前节点(类似于邻接表)获取图中从该节点开始的所有边,并进行规则匹配根据用户的当前回复在不同的边上。如果命中,则artgraph会流向命中边的结束节点,同时,机器人的回复内容会从该节点获取,语音结构会流转。语音图数据结构:通过上述数据结构,系统平台可以快速响应业务方的语音定制需求。例如,招聘人员可以为每个招聘职位定制问题。我们将这些问题抽象成演讲中的虚拟节点,利用Virtualedges连接虚拟节点,为不同职位提供个性化的面试问题,达到千人千面的效果。06服务性能优化实践魔幻面试间上线后效果不错,所以业务方希望快速扩容,AI面试机器人需要支持最大1000多人同时在线时间。因此,我们主要关注四个方面:资源管理、资源预估、性能测试和监控。以它为起点,AI面试机器人服务的性能得到有效提升。在实际在线使用中,优化服务可以同时接收到优化服务20倍的采访请求。资源管理方案:为了更好的管理服务中使用的资源,防止资源耗尽,我们设计了如下图的资源管理方案。首先,AI面试机器人和音视频通过SCF约定一个通信协议。由于SCF是负载均衡的,调用者的请求会随机发送到集群中的一台机器上。比如向服务实例1发送一个请求,通信协议可以将本次采访的交互绑定到这个实例上,接下来就是抽象出一个session的概念(代码层面是一个session类,并且每个session都是一个thread),本次面试申请的资源,比如发送接收端口,编程解码类和各种线程资源都注册到session上,代码保证注册到session上的资源会当会话被释放时被释放。这样不同的视频采访通过线程的隔离实现了资源隔离,方便了资源管理。同时,session实例通过sessionid(调用者通过通信协议约定,全局唯一)绑定到session容器。当用户挂机时,调用SCF释放资源。由于SCF的随机性,请求可能会到达服务实例3,实例3上没有这个面试会话。为了释放资源,我们使用WMB(58自研消息队列)广播资源释放消息,消息body中包含sessionid,所有服务实例都会消费这条消息,服务实例1包含sessionid,找到sessionid绑定的session,调用session的资源释放函数,使用Received资源释放(其他实例丢弃信息)。如果释放请求由于某种原因没有执行,session容器有一个session监控线程,可以扫描session容器中所有session的生命周期,为session设置一个最大生命周期(比如10分钟),以及session过期主动触发Session资源回收,释放session资源。同时,对于会话中申请的线程、端口等有限资源,我们采用集中式管理,使用线程池对线程进行集中管理,将所有可用的端口放入一个队列中,并监听队列中剩余的端口以保证服务的稳定性和可用性。机器资源预估:限制资源瓶颈,关注会话请求的临时资源能否及时回收,如端口、线程、编解码器等资源。本机网络带宽为1000MB/s>>2500*32KB/s。机器的硬盘资源由商家定制。LRU淘汰策略。线程池队列。实验方案如图所示:1.梳理系统架构,发现其中的有限资源,同时梳理压测方案。2.它使用多线程来模拟在线环境。3、是各种强度的力量测试。分析瓶颈资源,分析服务。4.定位瓶颈点,提高阈值报警,重新测试。5、是服务在实际场景中的稳定性表现。压力测试:接下来我们进行压力测试,尝试各种强度请求量实验。在使用2500requests/min对接口进行压力测试时,我们发现服务的主要瓶颈是服务的堆内存。从下图中可以看到,服务的堆内存很快就达到了100%,接口没有任何反应。我们转储堆内存后,发现堆内存中有数百个DialingInfo对象,每个对象占用18.75MB。看代码我们可以看到这个对象是用来存放AI面试机器人和用户的对话内容的,allRobotVoiceBuffer和allUserVoiceBuffer这两个对象各占一半内存大小,allRobotVoiceBuffer存放的是机器人的语音信息(存储格式:字节数组),allUserVoiceBuffer存储用户的语音信息。查看代码可以发现,allRobotVoiceBuffer和allUserVoiceBuffer在初始化服务的时候一共占用了18.75MB(这个值是因为存储了5分钟的音频数据),需要考虑初始化大小是否合理,分析一下神奇面试室的历史通话数据,可以看到有63%的用户没有回答机器人的第一道题直接挂断了面试,所以我们尝试降低这两个对象的初始内存大小,并且将allRobotVoiceBuffer改为0.47MB(这个值是机器人第一个问题的音频大小),allUserVoiceBuffer为0MB,由于allRobotVoiceBuffer和allUserVoiceBuffer这两个对象可以在ms级别进行扩展,如果对话内容超过对象大小,可以在不影响服务的情况下实现扩容。修改后,我们仍然使用2500min/request进行压力测试,服务可以实现稳定的垃圾回收。细粒度监控:指标类型概览请求量、成功量、失败量、无可用端口等关键服务指标13项指标资源指标可用端口队列长度小于阈值、缓存个性化问题超过阈值和其他5个指标process建言失败、关键信息传递失败、timeline传递失败等52个指标。线程池监控指标要求创建线程数、正在执行的任务数、任务平均耗时。异常、平均应答预热时间、ASR指标、自研语音识别平均时长、自研识别失败等9项指标18项指标、Vad指标调用次数、最大耗时等4项指标07总结本文主要介绍了AI面试机器人的后端架构,AI面试机器人与用户交互的全过程,对话引擎的核心功能,以及服务性能优化的实践。未来,我们将继续支持魔幻面试室项目的功能迭代和性能优化,进一步将AI面试机器人落地到不同的业务中。参考资料1.RTP:实时应用程序的传输协议。H.SchulzrinneR.FrederickS.CasnerV.Jacobson作者简介张驰,58同程AILab后端高级开发工程师,2019年12月加入58同程,目前主要从事语音交互相关的后端研发工作.2016年毕业于华北理工大学,获硕士学位。曾就职于便利蜂、中国电子,从事后端开发工作。
