无意中对Siri说了一句“one plus one echo(1+1=)”,Siri很快回答“It’s 2(这是2)”。于是乎,灵光乍现——为什么不让树莓派语音助手也能做数学题?
要让语音助手做数学题,计算模块先不说,主要还是要让它能理解你的意图,既要能识别1+1。怎么识别?我用的是rasa,那就在nlu中新增一个intent吧!最开始,我定义了如下的意图。
可是,我忘了,我用的是MitieNLP,而且我已经在nlu中定义了三个标签了,果然,当增加这个equation标签后,我的rasa train又双叒叕陷入了无止尽……
关于这个问题,可以参看我的另一篇博文:
使用MitieEntityExtractor训练中文NLU速度慢的问题-CSDN博客
(这个问题一部分是我的系统性能问题,一部分是MitieNLP的锅))
Kill了rasa train的进程,重新定义nlu、domain和story,这次学乖了,我去掉了nlu中的新标签,在domain里增加了一个form,具体如下图。
OK,rasa train在预期的30分钟内完成模型训练。为什么是30分钟?因为我曾经拿着手机秒表测算过:一次RASA TRAIN的时间记录-CSDN博客。
意图识别部分告一段落,接下来就是要定义识别意图后的action动作了。Python中有什么可以直接识别数学公式的函数吗?还真有,它就是eval(code),这里的code就是一段完成的算式,比如1+1。
有了eval()函数,action动作的问题解决了一半,另外一半则是要对算式的有效性做检验。是的,就是要判断下它是不是合法公式,比如是不是包含+,-,*,/的运算符?运算符两边是不是数字?如果这两个条件都不满足?对不起,俺不会计算!
有人说,检测是否包含运算符不是很容易的事情吗?只要用find()函数就能ok。如果直接是这四个字符当然如此。不过,大家不要忘了,我是语音助手,输入的是中文!!所以,我要先判断输入的算式中是否包含四个运算符的对应中文单词(加、减、乘、除),如果包含了,那么就用+,-,*,/替换中文字。
之后,再将整个算式字符串以运算符为中心,进行split()分割,然后分别判断左右两边是否都是数字?还好,我以前写过一个is_int()函数。
(is_int()函数的写法请参看:《让自家的智能语音助手实现todo任务的添加》)
完成上述两步有效性检测后,最后才是导入eval(),完成算式计算并返回一个结果。
说了这么多,我把这一段代码贴上来:
cal = ['加', '减', '乘', '除', '家', '成']
sig = ['+', '-', '*', '/', '+', '*']
cflag = False
isNum = True
text = tracker.get_slot("equation")
n = 0
for i in cal:
index = text.find(i)
if index != -1:
text = text.replace(i, sig[n])
cflag = True
tp = text.split(sig[n])
for j in range(len(tp)):
r = is_int(tp[j])
if not r:
isNum = False
n += 1
if cflag and isNum:
a = eval(text)
msg = "答案是" + str(a)
else:
msg = "我不会做这道题"
至于action的其他不分代码,这次就不贴了,具体代码同上所提的is_int()函数所在博文。
好了,把rasa run actions跑起来,把rasa server跑起来,再启动语音助手的demo.py,对着snowboy说“我要做数学计算”。
这样的结果让我很无语。看来语音识别任重而道远……
打开actions.py,将运算符中文字符组中添加‘家’和‘成’,然后把他们和“+”和“*”做匹配,再重新启动rasa服务。这次,snowboy终于计算成功了!
我在个人公众号“天飓”上建了一个#语音助手的合集,有兴趣的朋友欢迎关注和订阅^_^
标签:rasa,算式,text,运算符,助手,语音,数学题,做道 From: https://blog.csdn.net/hydekong/article/details/143906715