既然是机器人,就得有有脑袋,有身体,要想变得聪明就得有思想。
现在我们给机器人的大脑(也就是计算机)里注入思想,也就是编写程序。通过编写程序来使机器人变得聪明一点。
首先计算机熟悉的是文本内容,我们就从文本开始,然后加入语音识别的功能,把我们的讲话识别成文本,这样机器人就能够听懂我们讲话,但是还只能以文本的形式显示出来,再接着把回答的文本转换成语音,机器人就能发声说话。而其中涉及到的技术主要是语音识别和语音合成。到时候我们可以调用大厂的API,或者自己开发相应的程序算法库。
首先我们从文本开始,想要跟计算机进行一问一答的交互,最初的问题和答案都需要我们人类进行设定,就好比表演中的台词都需要一个编剧。现在我们需要下面的程序:V0.0版本
input("请开始对话:(询问名字)")
print("你好,我是瓦力,我是一个机器人")
input("请继续:(年龄)")
print("我5岁了~")
input("请继续:(性别)")
print("我当然使男生了,伊娃才是女生呢")
现在我们已经有了一个能够顺序回答问题的初级机器人了,按照这样的方式可以试着写一段相声文稿。也就是问答的顺序是固定的,回答的内容也是固定的,不论问什么都是同样的回答。所以我们现在进行第一次升级:V0.1版本,解决了答非所问的问题,只有问正确,才回答正确否则沉默,跳过该问题。
ask = input("请开始对话:(你叫什么名字?)")
if ask==("你叫什么名字"):
print("你好,我是瓦力,我是一个机器人")
ask = input("请开始对话:(你几岁了?)")
if ask==("你几岁了"):
print("我5岁了~")
ask = input("请开始对话:(你是男生还是女生?)")
if ask==("你是男生还是女生"):
print("我当然使男生了,伊娃才是女生呢")
第二次升级:V0.2,在V.0.1基础上,不许跳过该问题,直到问出正确问题
ask = input("请开始对话:(请问你叫什么名字?)")
a = 0
while a==0:
if ask==("你叫什么名字"):
print("你好,我是瓦力,我是一个机器人")
a = 1
else:
ask = input("请开始对话:(请问你叫什么名字?)")
a = 0
ask = input("请开始对话:(你几岁了?)")
a = 0
while a==0:
if ask==("你几岁了"):
print("我5岁了~")
a = 1
else:
ask = input("请开始对话:(你几岁了?)")
a = 0
ask = input("请开始对话:(你是男生还是女生?)")
a = 0
while a==0:
if ask==("你是男生还是女生"):
print("我当然使男生了,伊娃才是女生呢")
a = 1
else:
ask = input("请开始对话:(你是男生还是女生?)")
a = 0
第三次升级:V0.3,程序优化,代码重构。
RightAsk = ("问题库:","你叫什么名字","你几岁了","你是男生还是女生")
print(RightAsk)
while True:
ask = input("请开始对话:")
a = 0
while a==0:
if ask==("你叫什么名字"):
print("你好,我是瓦力,我是一个机器人")
a = 1
elif ask==("你是男生还是女生"):
print("我当然使男生了,伊娃才是女生呢")
a = 1
elif ask==("你几岁了"):
print("我5岁了~")
a = 1
else:
print("你问的问题太深奥,我还没学会呢,换个问题吧")
ask = input("请开始对话:")
a = 0
这样就可以三个问题一直问下去了,并且可以随机顺序。
可是这样的问法太僵硬了,只能固定的问题,一个字都不能错,如果想要换个方式问名字,应该怎么办?
第四次升级:V1.0,重大升级,开始变的聪明一点了。
RightAsk = ("问题库:","你叫什么名字","你几岁了","你是男生还是女生")
print(RightAsk)
while True:
ask = input("请开始对话:")
a = 0
while a==0:
if ask.find("名字")!=-1:
print("你好,我是瓦力,我是一个机器人")
a = 1
elif ask.find("男生")!=-1 or ask.find("女生")!=-1:
print("我当然使男生了,伊娃才是女生呢")
a = 1
elif ask.find("几岁")!=-1:
print("我5岁了~")
a = 1
else:
print("你问的问题太深奥,我还没学会呢,换个问题吧")
ask = input("请开始对话:")
a = 0
这里引入了一个python种find()的方法.
>>>info = 'abca'
>>> print info.find('a') # 从下标0开始,查找在字符串里第一个出现的子串,返回结果:0
0
>>> print info.find('a',1) # 从下标1开始,查找在字符串里第一个出现的子串:返回结果3
3
>>> print info.find('3') # 查找不到返回-1
-1
>>>
现在我们有了一个只会三句的稍稍有些聪明的机器人了。现在我想问他天气,他应该怎么回答?
当然可以直接在添加第四句问答:问天气怎么样,回答晴。但显然天气不止是只有一个晴字,而是什么时候什么地点的天气状况。
Q:你叫什么名字 A:你好,我是瓦力,我是一个机器人 Q:你几岁了 A:我5岁了~ Q:你是男生还是女生 A:我当然是男生了,伊娃才是女生呢 Q:最近天气怎么样 A:你想问哪里天气 Q:你不会定位吗 A:你还没给我添加自动定位的功能 Q:郑州天气怎么样 A:你想问郑州哪一天的天气 Q:你不会自己看时间吗,当然是明天啦 A:郑州明天天气,阴,有短时雷暴,空气质量良。
我们把上面的对话存成一个文件,然后进行调用,需要哪一句调用哪一句。
我们这里存成txt文件格式“语料库.txt”,在以后还会遇到别的文件格式,像json。那么python该如何读取到该文件呢?这里就需要一种新的方法with open()
:
with open("语料库.txt","r",encoding="utf-8") as lib:
lists = lib.read()
print(lists)
但是read()
得到的是完整的文本,想要从其中把问题和回答分开的话,就需要每遇到一次换行就存成一个数据,所以我们使用readlines()
;奇数行是问题,偶数行是回答。从零开始计数的话就是偶数行是问题,奇数行是回答。
注意这里新建的“语料库.txt”文件的路径问题,如果是直接open("语料库")
,那么该文件应该放在程序运行的目录下面。否则应该改成open("文件夹1/文件夹2/语料库.txt")
,或者open("../../语料库.txt")
第五次升级:V1.1,能够读取文件
with open("语料库.txt","r",encoding="utf-8") as lib:
lists = lib.readlines()
print(lists)
while True:
ask = input("请开始对话:")
a = 0
while a==0:
if ask.find("名字")!=-1:
print(lists[1])
a = 1
elif ask.find("几岁")!=-1:
print(lists[3])
a = 1
elif ask.find("男生")!=-1:
print(lists[5])
a = 1
else:
print("你问的问题太深奥,我还没学会呢,换个问题吧")
ask = input("请开始对话:")
a = 0
再观察上面程序,发现每一次回答都是基本类似的,即从文本文件中输出对应的行号内容。既然有相似那么就可以继续优化。
我们询问名字的时候,不是我们自己去指定回答哪一句,而是让程序自己确定回答哪一句,即从回答中自己去挑选应该回答的那一行内容。
第六次升级:V1.2 测试
with open("语料库.txt","r",encoding="utf-8") as lib:
lists = lib.readlines()
print(lists)
while True:
ask = input("请开始对话:")
a = 0
while a==0:
if ask.find("名字")!=-1:
for i in range(len(lists)):
if lists[i].find("名字")!=-1:
print(lists[i+1])
a = 1
else:
print("你问的问题太深奥,我还没学会呢,换个问题吧")
ask = input("请开始对话:")
a = 0
完整程序如下:V1.2.1
with open("语料库.txt","r",encoding="utf-8") as lib:
lists = lib.readlines()
print(lists)
print(len(lists))
while True:
ask = input("请开始对话:")
a = 0
while a==0:
if ask.find("名字")!=-1:
for i in range(len(lists)):
if lists[i].find("名字")!=-1:
print(lists[i+1])
a = 1
elif ask.find("几岁")!=-1:
for i in range(len(lists)):
if lists[i].find("几岁")!=-1:
print(lists[i+1])
a = 1
elif ask.find("男生")!=-1:
for i in range(len(lists)):
if lists[i].find("男生")!=-1:
print(lists[i+1])
a = 1
elif ask.find("时间")!=-1:
for i in range(len(lists)):
if lists[i].find("时间")!=-1:
print(lists[i+1])
a = 1
else:
print("你问的问题太深奥,我还没学会呢,换个问题吧")
ask = input("请开始对话:")
a = 0
这样一来,就是程序自己去找对应的回答内容了。接下来问题也不再指定,问什么,对应的回答什么,找不到就说问题太深奥。
第七次升级:V1.2.2
with open("语料库.txt","r",encoding="utf-8") as lib:
lists = lib.readlines()
print(lists)
print(len(lists))
while True:
ask = input("请开始对话:")
a = 0
b = 0
while a==0:
for i in range(len(lists)):
if lists[i].find(ask)!=-1:
print(lists[i+1])
b =1
a = 1
if b==0:
print("你问的问题太深奥,我还没学会呢,换个问题吧")
ask = input("请开始对话:")
a = 0
但是现在这个程序还包含至少三个问题:首先就是我们只能问我们准备的语料库里面的那些问题,一个字、一个标点符号都不能错,否则就会找不到对应的问题,也就没法做出对应的回答,当然也可以问语料库里面问题的关键字,但该关键字必须在语料库里的问题中是连贯的,并且可以少不能多,不能任意在关键词中添加无关的内容。举个粒子就是,比如语料库里面第一行的问题(你叫什么名字),可以问(你、你叫、你叫什、你叫什么、名字、什么名字、你叫什么名字)等等,但是不能问(你叫什么名字呢、名字是什么、名字名字)等。
程序里第二个问题是每次根据问题去找寻答案时,都是一行一行的把语料库里面的内容全部遍历一遍,这样是很浪费的,一个是浪费时间,另一个是浪费计算机运算资源。
程序里面第三个问题是当询问到语料库中最后的一段对话时,也就是:
我们可以问(当然时明天啦),但不能问(明天),因为回答的内容里面也有“明天”这个关键词,当程序在第二个问题的基础上会遍历到最后一句,但最后一句的是没有下一句的,也就是[i+1]
会超出范围而报错。还有就是问题和回答里面有同样关键词的时候程序会把所有包含该关键词的下一句给运行输出出来。如果在最后一句,也就是我们提问的时候问到了最后一句里面出现的关键词,那么就会超出范围而报错。
所以需要再进行程序升级以解决上述问题。首先我们让程序只遍历问题所在的行号,就是步长设为2:这样我们把问题和回答分开就解决了第3.1的问题程序不会遍历到最后一行,也就不会超出范围报错了。
with open("语料库.txt","r",encoding="utf-8") as lib:
lists = lib.readlines()
print(lists)
print(len(lists))
while True:
ask = input("请开始对话:")
a = 0
b = 0
while a==0:
for i in range(0,len(lists),2):
if lists[i].find(ask)!=-1:
print(lists[i+1])
b =1
a = 1
if b==0:
print("你问的问题太深奥,我还没学会呢,换个问题吧")
ask = input("请开始对话:")
a = 0
但是如果问题内容里有同样的关键词怎么办?就像几乎每一句里面都有“你”字,这个第3.2的问题我们给它归进问题1中,先解决第二个问题,也就是想要遇到问题对应的答案就会停止遍历,跳出循环。要用到的break
命令:
第8次升级:V1.2.3
with open("语料库.txt","r",encoding="utf-8") as lib:
lists = lib.readlines()
print(lists)
print(len(lists))
while True:
ask = input("请开始对话:")
a = 0
b = 0
while a==0:
for i in range(0,len(lists),2):
if lists[i].find(ask)!=-1:
print(lists[i+1])
b =1
break
a = 1
if b==0:
print("你问的问题太深奥,我还没学会呢,换个问题吧")
ask = input("请开始对话:")
a = 0
遇到对应的问题就及时中断,然后输出对应的答案。这样一来问题中同样的关键词也只会遇到一次。
现在就剩第一个问题了,也就是程序改如何判断所问的问题是一个有效的问题,或者从问题中提取有效的信息呢?这就要涉及算法和人工智能,在后面会具体讲到。