怎样让程序更好地理解一句话的意思,是我最近一直在思考的问题。
尝试做语音助手最大的难题是,怎么理解用户说话的意图?用户说,我要打电话给张三。你得先让程序明白用户是想打电话,然后你才知道该让程序做什么。
因为要做的不是通用语音助手,要结合产品的业务和使用场景来解决问题。但不同行业之间业务相差很大,市面上很难有提供基于行业的解决文案。
语义分析
语音识别技术相对成熟,可以直接采用第三方解决方案。自己要做的是,在识别出语音后分析用户说的话,知道用户想要干什么?然后再让程序执行相关的业务。从语音业务流程来看,完整的业务过程有三段:
这个筛选器的设计逻辑是,列出用户可能会说的话语,当用户说的话与预设完全匹配时,就知道精准地知道用户的意图。利用 ABNF 语法可以尽可能多地涵盖用户可能说的话。
$main 变量定义了说话的内容,在 $main 变量右边有很多不同的变量,$want, $query等。不同变量之间有各种符号,|,[],()。不同符号表达了变量之间的不同的组合关系。
符号 | 表示或的意思。$weather = 天气 | 气候。意思说该变量可以为天气
,也可以是气候
。
符号 [] 表示可有可无的意思。$main 中的 [我] 意思是当用户说话的内容有我
,没有我
时都是可以的。
$main 就代表了多种变量不同关系的组合结果,当用户说不同的内容时,都能被匹配到,比如:
- 我想要查北京今天的天气。
- 查询广州后天天气情况。
- 查一下上海明天的气候怎么样。
第二个方案的好处是能通过完全匹配来精准了解用户说话内容的意思。不好的地方正好跟第一个方案是相对的,不够灵活。因为完全匹配,要想涵盖尽可能多的说法,就得尽可能地想到用户会说的方式,然后再将其转换成 ABNF 语法文件。
如何使用 ABNF 语法文件来定义筛选器成了一件棘手的工作。定义业务是类似编辑类的工作,属于管理员做的事情,但管理员不懂 ABNF 语法,做不了这个事情。
因为这个,我还设计一个GUI,希望让普通的人能通过界面的操作即可定义筛选器,后台会自动生成对应的 ABNF 文件,而不用直接编写复杂的 ABNF 源文件。
如上图,句式语法
是对说话内容的参数设置。管理员正常录入一句话,然后选中其中的某个字或词语即可指定它在句子中的对应同义词,以及与其它词语的组合关系。
选中「我要」,界面即自动会生成参数1,如果你指定「我要」是非必选,即表示,用户说的话语可包含或不包含「我要」这个字。选中「手机」,界面会自动生成参数2, 你可以指定参数2可引用一组词:手机,电视,空调,冰箱。当用户不说手机,说电视或空调,同样会识到。
在方案评估过程中还是放弃了这个方案:
- GUI 的配置降低了 ABNF 语法文件的编写门槛,但对没有编程基础的操作人员,理解起来并不简单。
- 完全匹配要求录入的语法得兼顾尽可能多的说法,否则系统无法识别用户说话的内容。这对任何人来说,都是一个巨大的挑战。
三、基于 Frame semantic 的语义框架
「关键词匹配」方案过于开放,「ABNF 语法」方案过于局限。如果在两者之间能求得一个平衡,就能找到一个更为合适的方案。我们的思考的思路:
- 一个正常人在表达自己的意图时,都会有业务对象。我想发短信给张三,短信是其中的业务对象。
- 业务对象包含很多细节信息。短信有发送人,内容,短信类型。
近一步探索,用户说,发短信,查看天气,打电话,都是典型的动宾短语,能基本表达出用户的意图。至于天气,电话,信息相关细节都是与宾语相关的,属于宾语的属性。
如果我们提前定义了信息的属性,以及每个属性可能对应的值。当用户提到的时候我们就能知道用户在说什么。(图)对短信来说,短信属性有,内容,发送人,消息类型等发。
语义框架
像上面的短信,
- 我们认为它是一个领域,包含业务对象,以及与业务对象想关的数据和业务。比如「网购」,「酒店」,「智能家居」等。
- 对领域内的数据操作,能够表达了用户意图,一般是是动宾结构的形式。比如查询短信,发送短信。
- 领域内的对象都有自己的属性。短信有短信的属性,天气有天气的属性。
按照上面的分析可以建立一个简单的语义框架:
语义结构
基于上面的语义框架就可以做更好的筛选器。
- 筛选器的核心就是意图的结构,一般是
动作
+业务
对象。不同筛选器因为业务的不同分属于不同的领域。 - 用户正常说完一句话后,使用自然语言处理对句子进行分词,句法分析,词性标。
- 对处理后的结果进行分析,识别出说话内容所属领域,提取其中的业务对象以及属性信息。
- 找到匹配的筛选器。
相对前两种方案,该方案在原理上能够更精准地理解语义,但在实践过程中也遇到了一些困难:
1)知识库的积累与丰富
语义的框架的基础是建立在已有的知识体系之上的。如果知识库里的苹果只是一种水果,当用户说想要一部苹果手机时,系统并不知道这里苹果不是水果,而是一个品牌。这意味着,要让系统能够知道某个词是什么意思,就是先要录入相关的信息。要想让系统理解用户说的尽可能多的词,并且能正常理解相应的意思,就得构建一个庞大的知识库。这个知识库里的信息,如何整理,归类,都是巨大的任务。
如果知识库的内容要靠人工来主动添加完善,这来速度相对于用户的需求来说,是非常慢。能不能让机器学习,爬取其它渠道的知识,然后进行清洗,筛选,加入到我们的库里面,这同样是个挑战,也是一件很有意思的思情。
2)领域的识别
前期的时候,领域不多,语义的识别困难不大。随着领域的增加,语义的理解可以会因为多个领域的存在产生干扰。每一次领域内容的丰富都要考虑对其它领域可能产生的干扰。
3)上下文的支持。
说深圳的天气怎么样,系统可以知道用户是想问深圳的天气。当用户接着说,那么东莞呢,系统就不一定知道了。系统只有在关联前一句话的情况下才能明白用户想问的内容,这要求系统要有关联上下文的能力。具有上下文的对话更符合正常人与人之间的自然沟通方式,不需要在每次表达意思的时候,都得完整地说出一句话。
语义分析对我来说是一个全新知识领域,之前没有过触,前段时间在摸过的过程中遇到了很多问题。特别感谢网友 @unbuilt 提供了很多的帮助,才有最后一套方案的构思。
网友评论