16

轻量机器人框架 – Segnavi

 4 years ago
source link: https://www.infoq.cn/article/XfSBPkL3ulx7R1OJkVzb
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

这些是否困扰你?

当你想到智能客服问答的时候,你是否第一反应它一定要与人工智能有关?

你是否只是想要一个开箱即用,简答上手,无需复杂的人工智能知识和机器学习规则的智能客服系统?

你是否想让你的智能问答系统不单单满足于问答场景,还希望它可以执行更多的动作?

那么,从今天开始,我们开发的 Segnavi 框架将满足以上所说的这些全部内容,它并不需要你了解人工智能、机器学习方面的知识,就像写脚本一样快速轻松的构建属于你的智能问答系统。

化繁为简,开箱即用

当你不再重复性的为各业务的同学解答相同问题,不再被重复的问题所打扰,一杯咖啡,静下心来,去专心思考和研究更深入的问题时,不得不说这的确是最理想的工作方式了。

从今天开始,只需一杯咖啡的时间,即可立刻构造属于你的智能问答系统。Segnavi 本身的体积十分小巧,无需依赖任何数据库即可运行。基于 python 开发,就像些脚本一样的轻松使用。我们将知识库从常见的数据库存储,转换为本地代码文件存储,所以严格意义上来讲 Segnavi 是一个机器人对话的框架。我们将框架尽可能设计的足够简单、轻量、灵活且功能强大。

我们将传统机器人对话中的意图理解和槽概念转换为 Python 在面向对象状态下的两种可继承类,通过这个继承类生成的对象可以取得全部的对话与槽特性。简化在任务型对话中的槽类型、槽字段等相关概念,取而代之是对象内的属性和方法。你可以像写脚本一样简单快速的使用到框架的全部功能。

在进一步的介绍之前,先简单了解一下任务型对话中槽的概念:在任务型对话中,我们的要完成某一个动作,需要各种的条件满足一个任务的触发,这种对话就叫任务型对话,触发的条件就是槽。当然你可以把槽理解为传递触发条件的参数,我们所做的就是简化机器人中的逻辑。

通俗的讲,类似于 http 请求中传递的参数。这种参数是通过多轮问答的形式来实现的。

下面我将用“40 行代码”来举例说明。

强大的功能

最简化设计

我们设计了两种任务型对话,以满足不同场景的多轮对话需求,一种为 Question 类,一种为 Operation 类。为了简化结构和方便理解,我们将两种不同的任务型对话转换成树形结构,我们管这棵树叫“问题树“。

Question 的每一个问题就相当于树的每一个分支,树的子节点可以继续是 Question,也可以是 Operation 类。而 Operation 类是负责任务型对话中槽位的填充,其为树的最终子节点。可以理解成红黑树中的黑树,且不再有任何子节点。

除了为了满足不同多轮对话场景需求而设计的 Question 类和 Operation 类,我们还设计了一个 Word 类,改类的目的为注册不同的词或语句绑定在一个 Question 或 Operation 的子类中。

举个例子

【代码】

qyQBruZ.png!web

QuestionTree1 类为 Question 类,它是作为问题树的结构体,方便用户做出进一步的选择,也是一类在多轮对话中槽位的填充。这其中 Word.registe() 为注册的词,我们可以注册两个词 "hello" 和 "WelcomeList" 等任意个词,这其中 WelcomeList 为引导词,你也可以在配置文件里面随意设置你的引导词,当用户达到配置中连续未任何命中的时候,就会执行引导词。

Question.register() 用于注册任务型对话中负责询问的部分,在 Segnavi 展示中,为问题树的选项。为了方便使用,Segnavi 会将 Question.register() 注册的内容,通过 1,2,3,4…这类数字作为选项引导。对于超过 2 层的 Question(Question 的子节点还是 Question)Segnavi 会自动生成 “返回上一级” 的选项。q3 中的 handle='我是问题树 1’代表当用户选择 3 这个选项,实际 Segnavi 会内部执行 “我是问题树 1” 这个词。在 Segnavi 中,默认状态下,用户选择了哪个选项就相当于对系统说了哪个选项的 text 文本,当然这个也是可以改的。就像 q3 这样。

OperationHandle1、OperationHandle2 分别代表两个最终子节点,Operation.register() 相当于进入该对话时槽位的填充,这里的槽位我们可以限制指定词的类型,也可以不限制词的类型,词的类型我们在稍后会介绍。当槽位被填满(满足所有条件时),Segnavi 会触发 Operation 子类中定义的 _ handle _ 方法 ,这个方法内你可以执行任何代码,或者只是返回一句简单的 hello world。

【运行后的结果】

jMBjEvu.png!web

Y3ERf2n.png!web

超强的纠错能力

在传统的规则匹配型语义理解模块中,最难维护的是你词规则是否是唯一,且规则中是否存在互斥,死锁,循环等问题。在 Segnavi 中这些作为使用者无需考虑。因为我们在系统启动时会有全面的自检程序,防止此类情况的发生。当 Question.register() 中注册的 text 文本是一个不可被理解的词(其他类未注册的词),或者会被理解成两个不同的选项时(多个类同时注册一个词,或一个词指向了两个不同的类),系统此时是无法启动的。

比如我们将 q2 的 text 文本改成一个不存在的词时:

aaquMzJ.png!web

系统启动时的自检程序将会报错:

i6NFzei.png!web

将机器对话的复杂度降低至小学水平的知识

在传统机器对话模型中,会通常设置自然语言处理和语义处理模块,来处理用户的提问,并起到语义理解,与槽位的识别功能。通常情况下,自然语言处理和语义模块是在一起的。

Segnavi 也有自己的语义理解模块,和自然语言处理系统。但我们为了简化逻辑,将自然语言处理和语义理解模块拆开。对话过程只保留语义理解中的分词功能。将自然语言处理的逻辑由用户输入时的触发变为逆向的先行触发。

我们会在系统启动时,会预先对所有 Word.register(),Question.register(),Operation.register() 内所有的 text 文本进行自然语言处理,和切词操作。并构造一个大型词典的结构体,这个结构体内包含了词的 text 文本、自然语言处理后的切词、词的类型、词的动作、词的权重等等内部的参数。

当一个词未被理解时,我们会根据在系统启动时构造的 NLP 词典进行反查,达到联想和猜测的功能。然而这些操作都是作为使用者无需关心的,你只需维护一个简单的 text 知识库即可。

上面我们刚刚提到了在 Operation.register() 内可以设置槽位的类型为指定词的类型,我们采用了基于规则理解方法来解决槽提取以及槽填充的问题。我们将 程序主目录 /handle 作为所有词和知识库的存储。handle 目录下的 一级目录名 为词的类型,词的类型类似我们上小学时候学的动词、名词这种,它起到对词进行归类并打标识的作用。就好比我们说跑、跳、走这类词是动词,文具、铅笔、橡皮这类词是名词一样。在 Segnavi 中,槽填充和槽提取也会依赖对词类型的检测。

例如 num 目录下的所有文件,注册的词,它们的类型都是 num 类型。ip 目录下注册的所有词类型都是 ip。这个我们已经预先设置好,可以不用做任何的修改,开箱即用。

rQ7FVfi.png!web

我们预先设置好的词:

eIzaA3m.png!web

uYVVjyY.png!web

I7RjUfb.png!web

灵活的运用和极少的资源使用

Segnavi 可以应用在任何系统中,我们曾经接入过 Qtalk、微信、QQ,可以说只要是 IM 系统都可以接入 Segnavi 作为处理引擎调用方式仅为 http 的 post 请求而已。我们会在内部维护 session,无需调用方维护。

同时我们还会提供一个 webui 供测试使用。后台日志和分析功能,可以还原当时的会话场景,并按照指定日期进行词频、动作、理解程度等维度进行综合分析。还支持通过关键词在所有会话内进行查找,并支持导出至 excel。

经过我们测试,每 10,000 个 session,平均占用 100MB 内存。我们在高峰时可以同时处理超过 500 个对话,并且只用一台主机即可。因为是非 cpu 密集型程序,即使是 500 个对话,cpu 的使用水平依旧可以保持一个很低的水平。

写在最后

目前 Segnavi 已经在公司内部开源使用。现在 OPS 值班热线、CM 热线、JIRA 热线都已接入。我们在设计 Segnavi 之初,跟大家一样也曾尝试过别人的机器人框架,当初想法很简单,只是想做一个运维相关的机器人而已,我们的需求也很简单同时能满足有多轮问答的场景,和满足直接使用命令行操作,并且当用户不知道选项时最好能提供一个菜单。但调研了一圈框架后发现,要不就是框架过于复杂,要不就是功能不完全。最后不得已只能自己造轮子,其实早在 18 年 11 月的时 OPS 内部就已经将机器人切换至 Segnavi 框架了。从目前的状态来看 Segnavi 运行的还是比较稳定。

由于篇幅有限,其实在文章中只能介绍 Segnavi 框架的最基础功能,我们还支持例如转人工、层级索引、模糊猜测、命令式的直接槽位提取等等。我们没有为 Segnavi 配置机器学习的模块,但已经预留出插件接口。其实作为运维工程师来讲,目前的 Segnavi,已经能够满足 OPS 的全部需求了。接下来如果有精力,我们期望能将 Segnavi 的对话和 session 改造成中间件式的可插拔插槽。

我们始终期望创造一个开箱即用,简单逻辑的机器人应用,减轻学习成本,方便快速使用。最后,如果你希望使用 Segnavi 欢迎与我取得联系。

作者介绍:

王欣宇,2018 年加入去哪儿 OPS 团队,负责运维自动化相关的工作,保障了公司每日数十万的自动化任务执行,让海量服务器共舞。

本文转载自公众号 Qunar 技术沙龙(ID:QunarTL)。

原文链接:

https://mp.weixin.qq.com/s?__biz=MzA3NDcyMTQyNQ==&mid=2649263128&idx=1&sn=b616b27b85290e8c7d8008abd0efcd4b&chksm=87675de6b010d4f04ebc8e031646de7f4d1e702325ae355bca73142645b9981a87930b2213c7&token=2032634643&lang=zh_CN#rd


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK