Skip to content

系统设计与实现

Hai Liang Wang edited this page Oct 3, 2020 · 21 revisions

需求分析

构建聊天机器人依赖于数据,这些数据可以由业务人员整理,或者从客户数据库分析,比如聚类分析等方法整理而来。这些对话之前通常是人工座席应答,随着客户业务的增长,人工座席呈现线性增长,这带来了不可控制的开销,成本急剧增加。为此,企业寻求替代方案:智能对话机器人,也称为聊天机器人,机器人客服,机器人等。

聊天机器人可以724365的工作,标准回复,立即响应。虽然一些棘手的问题,机器人还不能完成,但是很多咨询问题都是常见的,或话术都是固定的。先通过机器人应答或者由机器人收集信息,进一步再由人工座席处理棘手的问题已成为一种最佳实践。很多证券、电商、保险行业已经成功上线了机器人客服,这一趋势大约从2015年就迅速发展。这一趋势得益于技术的进步,甚至出现了一个新兴岗位:AI训练师。

那么,如何落地企业智能问答机器人呢?

Clause开源项目就是回答这个问题的。

幻灯片

为了方便概览,后文的内容同时也整理为幻灯片,参考下载地址。 幻灯片中的内容相对于后文是有所删减的,如需了解详情,请继续阅读后文。

数据库表结构

Clause使用关系型数据库存储对象,包括词典、意图、说法和槽位等,数据库表介绍:

描述
cl_dicts 词典,包括自定义词典和系统词典
cl_dictwords 自定义词典的词条
cl_intents 意图
cl_intent_slots 意图槽位
cl_intents_utters 意图说法
cl_chat_sessions 会话
cl_chat_msgs 对话消息
cl_bot_sysdict 机器人关联系统词典关系
cl_prod_vers 生产版本
cl_dev_vers 调试版本

目前,Clause的数据库表关联关系如下:

其中包括10个对象,7个约束外键,数据库的初始化SQL文件也在项目中(链接),查看该SQL获取详细信息。

微服务模块设计

设计原则

  • 高性能

核心代码使用C++,模块间调用以及暴露的接口主要采用RPC,RPC使用长连接,效率高。

  • 可拓展

支持不同容器的水平伸缩,尤其是计算量大的clause节点和intent节点之间使用消息服务,intent节点可以随意的横向扩张,clause通过activemq分发计算任务。

  • 自动化

支持聊天机器人的数据标注,训练,调试和上线的完整生命周期。

模块设计

clause服务通过docker-compose编排,各模块介绍如下:

模块名称 功能 依赖
clause 对外暴露RPC接口,管理关系型对象,会话管理,聊天管理,版本管理 sysdicts, redis, mysql, activemq
sysdicts 提供系统词典,标记系统词典的实体
intent 提供训练机器人的接口,包括分类模型、NER模型、自定义词典和分词器等 activemq
mysql 关系型数据的存储
redis 会话数据存储,版本数据,训练状态等需要快速读取和写入的数据
activemq clause服务和intent服务交换信息的消息服务中间件

其中,clause、sysdicts和intent是核心实现模块,实现均为C++,使用Apache Thrift框架和Protobuf;mysql、redis作为数据持久化数据库;activemq作为消息服务。

image

注意:在模块中有一个模块也命名为clause,其原因是该模块是最主要的模块,后文使用“clause模块”指代。“clause服务”则代表通过docker-compose运行起来的整个应用。“clause项目”代表Clause服务的开源码项目。

Clause 数据结构设计

为了灵活和更好的扩展性,Clause暴露的集成接口的输入和输出采用统一的数据类型:chatopera::bot::clause::Data,简称Data。再由Data数据类型包含其它对象的列表或单个对象,Data数据类型包含的数据很多,简要介绍主要字段:

Data字段 描述
rc 返回值的代码,成功返回则rc=0,否则为异常返回
error 异常返回值的原因,当成为返回值,error为空
msg 成功返回的消息
id 某个对象的ID
chatbotID 聊天机器人的唯一标识
customdicts 自定义词典列表
sysdicts 系统词典列表
botsysdicts 机器人引用的系统词典列表
dictwords 自定义词典的词条列表
messages 聊天消息列表
intents 意图列表
slots 意图槽位列表
utters 意图说法列表
devver 调试版本信息
prover 生产版本信息
session 聊天会话
message 聊天消息
currpage 翻页信息,当前页面
totalpage 翻页信息,页面总数
totalrows 翻页信息,全部数据条数
pagesize 翻页信息,页面大小
query 翻页信息,查询条件

完整的Data数据定义如下:

image

在查看Clause提供的具体接口前,可以通过server.dsl了解Clause对数据结构的定义和接口定义。

Clause接口设计

子模块 接口 描述
词典相关
postCustomDict 创建自定义词典
putCustomDict 更新自定义词典
getCustomDicts 获得自定义词典列表
getCustomDict 获得自定义词典详情
delCustomDict 删除自定义词典
postSysDict 创建系统词典
putSysDict 更新系统词典
getSysDicts 获得系统词典列表
refSysDict 引用系统词典
unrefSysDict 取消引用系统词典
myDicts 获得指定机器人的所有自定义词典和引用词典
mySysDicts 只获得指定机器人的引用的系统词典列表
putDictWord 创建或更新自定义词条
getDictWords 获得自定词典的词条列表
delDictWord 删除词条
hasDictWord 检查一个词汇是否在自定义词典中
意图相关
postIntent 创建新的意图
putIntent 更新意图
getIntents 获得意图列表
delIntent 删除意图
postSlot 创建意图槽位
putSlot 更新意图槽位
getSlots 获得槽位列表
delSlot 删除槽位
postUtter 创建意图说法
putUtter 更新意图说法
delUtter 删除意图说法
getUtter 获得意图说法详情
训练机器人
train 训练机器人
status 获得机器人训练状态
版本管理
devver 获得最新调试版本信息
prover 获得最新生产版本信息
version 获得生产版本和调试版本信息
online 将指定调试版本升级为生产版本
对话相关
putSession 创建会话,会话的概念参考
getSession 获得会话详情
chat 和指定的机器人进行对话

关于服务端这些接口的定义,可以参考 API Docs

关于Clause客户端的使用,也有这些接口的描述,开发者在掌握了一个语言的客户端的使用,可以很容易的掌握其他语言的客户端,因为接口的设计是一致的。Clause客户端的使用请参考示例程序系统集成

模型训练的实现

  1. 分发训练任务
  2. 检查工作内容
  3. 构建词典
  4. 生成拓展的说法
  5. 基于说法构建索引
  6. 构建NER模型
  7. 返回训练执行结果

image

对话检索的实现

  1. 确认会话的有效
  2. 确认目标BOT存在
  3. 检查是否确定了意图
  4. 确认新的信息提取到了槽位信息

image

关键技术栈

clause服务使用了如下项目:

Apache Thrift

http://thrift.apache.org/ Apache Thrift提供了跨语言的RPC服务方案,通过一种服务定义语言,描述接口,Apache Thrift就可以生成兼容不同编程语言的服务端和客户端代码。这给用户集成Server端提供的服务带来极大方便。Clause暴露的服务的描述文件是server.dsl

Protobuf

https://developers.google.com/protocol-buffers/

Protobuf是Google发布的用于消息传递的库,可以用一种描述语言定义数据结构,然后Protobuf生成不同语言的类和管理方法。Protobuf的最大优点是减小了数据传输体积,加快了数据读取速度,因为其优良数据编码,使用Protobuf会比使用JSON数据格式快7倍。 在Clause中,Intent模块和Clause模块通过ActiveMQ交换数据,就使用Protobuf完成。

Crfsuite

http://www.chokkan.org/software/crfsuite/

CRFSuite是一个实现CRF算法的C++工具库,CRF算法是目前实现序列标注最好的实践,就算是基于深度学习的算法也是与CRF结合,因为CRF可以充分考虑一个字与周围的字组成的特征来标记一个类别。CRF算法本身可以在不依赖大量数据前提下取得比较好的准确率,而且训练速度快,CRFSuite又使用C++实现,在追求线上训练和预测时,以及在成本可控的前提下,成为了最好的选择。Clause服务中,在解决命名实体标识时,使用自定义词典、用户说法和槽位训练NER模型。

PaddlePaddle

https://www.paddlepaddle.org.cn/ 源于产业实践的开源深度学习平台

Clause的包含系统词典类型,系统词典极大的简化了用户使用Clause服务的难度,Clause目前版本中提供了人名(@PER),地名(@LOC),组织结构名(@ORG)和时间(@TIME)是基于中文词法分析(LAC)的,这个选择基于下面的原因:

  • 经测试,LAC的识别效果很不错

LAC发布的模型是基于亿级预料训练

  • LAC项目发布了训练脚本

这样,Chatopera团队或开发者可以增加训练语料,识别新的类。而且,训练脚本使用Python,这样减少了学习成本。

  • LAC预测使用C++

LAC的预测库使用C++,保证了线上使用的高性能。

  • LAC的算法和框架可靠

LAC在给出项目的代码,模型和训练脚本,同时也提供了算法的论文,以及PaddlePaddle的持续更新和开放,让我们相信LAC是一个很好的选择。

Xapian

https://xapian.org/

Xapian是使用C++实现的搜索引擎,Chatopera团队在32GB内存,8核CPU上测试Xapian的性能,测试条件为1500W条文档,平均每个文档~1000字,Xapian可以实现30QPS的超高性能。在Clause中,Xapian用于召回意图,由Xapian构建的索引以及其它排名算法,作为分类模型使用。

其它部分

Clause还使用了其它的技术,做更简单的介绍

  • gtest

单元测试

  • glog, gflags

日志以及启动参数

  • leveldb:快速检索自定义词表

https://github.com/google/leveldb

  • hat-trie: 高性能前缀树

https://github.com/Tessil/hat-trie

  • jieba: 中文分词器

https://github.com/yanyiwu/cppjieba

更多技术栈参考thirdparty

下一步

AI BootCamp 2019(北京站)主题演讲:Clause Overview

开发环境搭建