返回介绍

9.4 打造一个聊天机器人

发布于 2024-01-26 22:17:31 字数 10399 浏览 0 评论 0 收藏 0

现在,了解了聊天机器人有哪些可能性,你很可能想打造一个最好的、最先进的、Google级别的机器人,对吧?好吧,现在不要想着那些了,因为我们会做相反的事情!我们将建立史上最糟糕的机器人!

让我告诉你为什么。要创建一个与Google所造的机器人相媲美的聊天机器人,需要大量的硬件和时间。在你的MacBook Pro上,无论使用何种真实训练集进行学习,模型通常都要耗费一个月或两个月的时间,你是无法速成它的。这意味着你不得不在Amazon的AWS上租用一些时间,而且也不是随随便便什么机器都能满足需求的。这类机器需要有一些强力的性能规格,最好是GPU。尝试这些当然是好事情。但是,如果你的目标只是建立一些酷炫、吸引人的东西,那么下面的内容就可以帮助到你。

我也应该提前警告你,虽然Cleverbot不是微软的Tay,但对话的口味可能还是会有点重。如果你很容易被冒犯,那你可能需要另一个不同的训练集。

好,让我们开始吧!

首先,和往常一样,我们需要训练数据。一如既往,这是整个过程中最具挑战性的一步。幸运的是,我找到了一个超赞的会话数据库。网站notsocleverbot.com让人们提交他们与Cleverbot之间最荒谬的对话。有了这个训练集,夫复何求?

让我们来看看Cleverbot和该站点用户之间的对话示例,如图9-9所示。

图9-9

所以,我们将从这里开始。首先,我们需要从这个网站下载对话脚本。为此,我们将使用和第2章相同的工具import.io,如图9-10所示。

图9-10

你只需将链接粘贴到页面上的表单中即可。输入的格式就像这样:http://www.notsoc leverbot.com/index.php?page=1。

一旦提交,网站import.io就将处理请求并返回一个页面,就像图9-11这样。

图9-11

如果从这里看一切正常,请单击右上角附近的粉色“Done”按钮。

网站import.io将处理该页面,然后将带你到图9-12这样的界面。

图9-12

接下来,单击中间的Show URL Generator按钮,如图9-13所示。

图9-13

接下来,你可以设置要下载的数字范围。例如,1~20,每次1个。显然,你抓取的页面越多,这个模型就会越好。但是,请记住,你的请求会对服务器造成压力,所以使用时请体贴一些[3]

完成后,单击Add to List并在文本框中单击Return,然后你应该能够单击Save。它将开始运行,完成之后,你可以将数据下载为CSV文件。

接下来,我们将使用Jupyter记事本来检查和处理数据。首先导入 pandas和Python正则表达式的库re。我们还要设置pandas的选项来加宽列,以便我们可以更好地看清数据。

import pandas as pd 
import re 
pd.set_option('display.max_colwidth',200)

现在,我们将加载数据。

df = pd.read_csv('/Users/alexcombs/Downloads/nscb.csv') 
df

上述代码生成图9-14所示的输出。

图9-14

由于我们只对第一列的对话数据感兴趣,将其拆解出来。

convo = df.iloc[:,0] 
convo

上述代码生成图9-15所示的输出。

图9-15

从图9-15,我们可以看到用户和Cleverbot之间的交互,以及对话的启动。为了获取我们所需的格式,需要将数据解析成问题和答复的配对。我们不一定关心谁说了什么,但我们关心将每个答复和问题对应起来。稍后我们将理解这是为什么。现在让我们在文本上执行一些正则表达式。

clist = [] 
def qa_pairs(x): 
     cpairs = re.findall(": (.*?)(?:$|\n)", x) 
     clist.extend(list(zip(cpairs, cpairs[1:]))) 
convo.map(qa_pairs); 
convo_frame = pd.Series(dict(clist)).to_frame().reset_index() 
convo_frame.columns = ['q', 'a']

上述代码将产生图9-16所示的输出。

图9-16

好吧,这里有很多代码。刚刚发生了什么?我们首先创建了一个列表来保存问题和答复的元组。然后我们通过一个函数来切分对话,使用正则表达式将它们变为匹配的对。

最后,我们将列标记为q和a,并将所有的数据放入一个pandas的DataFrame。

我们现在将应用一点算法的魔术,为用户的输入匹配最接近的问题。

from sklearn.feature_extraction.text import TfidfVectorizer 
from sklearn.metrics.pairwise import cosine_similarity 
vectorizer = TfidfVectorizer(ngram_range=(1,3)) 
vec = vectorizer.fit_transform(convo_frame['q'])

我们在上面的代码中所做的是,导入TfidfVectorization库和余弦相似度的库。然后我们使用训练数据来创建tf-idf矩阵。现在可以使用这个来转换我们自己的新问题,并测量该问题与训练集中现有问题间的相似度。

  

我们在第5章详细讨论了余弦相似度和tf-idf算法,所以如果你想了解它们运作的细节,请参考第5章。

让我们现在获取相似度分数。

my_q = vectorizer.transform(['Hi. My name is Alex.']) 
cs = cosine_similarity(my_q, vec) 
rs = pd.Series(cs[0]).sort_values(ascending=0) 
top5 = rs.iloc[0:5] 
top5

上述代码生成图9-17的输出。

图9-17

我们在这里看什么?这里列出了和我提出的问题最接近的前五个问题,以及它们之间的余弦相似度。左边是索引编号,右边是余弦相似度。让我们来看看这些问题。

convo_frame.iloc[top5.index]['q']

这将产生图9-18所示的输出。

图9-18

我们可以看到,没有一个问题和我的输入是完全相同的,但肯定有一些相似之处。

再来看看答复。

rsi = rs.index[0] 
rsi 
convo_frame.iloc[rsi]['a']

上述代码将产生图9-19所示的输出。

图9-19

好吧,我们的机器人似乎已经表明了态度。让我们再进一步。

我们将创建一个方便的函数,这样可以轻松地测试一系列的语句。

def get_response(q): 
     my_q = vectorizer.transform([q]) 
     cs = cosine_similarity(my_q, vec) 
     rs = pd.Series(cs[0]).sort_values(ascending=0) 
     rsi = rs.index[0] 
     return convo_frame.iloc[rsi]['a'] 
get_response('Yes, I am clearly more clever than you will ever be!')

这将产生图9-20所示的输出。

图9-20

显然,我们创造了一个怪物,所以继续吧。

get_response('You are a stupid machine. Why must I prove anything to you?')

这将产生图9-21所示的输出。

图9-21

我很享受这个。让我们继续前进。

get_response('My spirit animal is a menacing cat. What is yours?')

图9-22

我回答说:

get_response('I mean I didn't actually name it.')

这将产生图9-23的输出。

图9-23

继续:

get_response('Do you have a name suggestion?')

这将产生图9-24所示的输出。

图9-24

我回答:

get_response('I think it might be a bit aggressive for a kitten')

这将产生图9-25所示的输出。

图9-25

我试图平息局面:

get_response('No need to involve the police.')

这将产生图9-26所示的输出。

图9-26

最后:

get_response('And I you, Cleverbot')

这将产生图9-27所示的输出。

图9-27

显然,这可能是我近期最好的对话之一了:包括机器人和真实的人。

现在我们已经创建了这个基于蛋糕[4]的智能,这里要设置一下,以便我们可以通过短信的方式与其聊天。

为了达到这个目的,我们还需要一些东西。第一个是twilio账户。他们将提供一个免费的账户,让我们发送和接收短信,如图9-28所示。

图9-28

跳转到http://www.twilio.com的网页,单击注册一个免费的开发者API密钥。你会设置一些登录凭据,然后他们将向你的手机发送短信以确认你的号码。设置完成后,你就可以在Quickstart文档中找到详细信息。请确保你在左上角的下拉菜单中选择了Python,如图9-29所示。

图9-29

从Python代码发送消息很简单,但是你需要请求一个twilio 的号码。在代码中,你将使用这个号码发送和接收消息。接收消息稍微有点复杂,因为它需要你运行一个Web服务器。文档很简洁,所以设置它不会让你太难熬。你需要一个公共Web能访问的Flask[5]服务器URL地址,并将其粘贴到你管理twilio号码的区域之下方。只需单击号码,它就会带你到粘贴网址的地方,如图9-30所示。

图9-30

一旦这些都设置完成,你只需要确保Flask Web服务器启动并运行。这里,我压缩了所有的代码,可以用于你的Flask应用程序。

from flask import Flask, request, redirect 
import twilio.twiml 
import pandas as pd 
import re 
from sklearn.feature_extraction.text import TfidfVectorizer 
from sklearn.metrics.pairwise import cosine_similarity 
app = Flask(__name__) 
PATH_TO_CSV = 'your/path/here.csv' 
df = pd.read_csv(PATH_TO_CSV) 
convo = df.iloc[:,0] 
clist = [] 
def qa_pairs(x): 
    cpairs = re.findall(": (.*?)(?:$|\n)", x) 
    clist.extend(list(zip(cpairs, cpairs[1:]))) 
convo.map(qa_pairs); 
convo_frame = pd.Series(dict(clist)).to_frame().reset_index() 
convo_frame.columns = ['q', 'a'] 
vectorizer = TfidfVectorizer(ngram_range=(1,3)) 
vec = vectorizer.fit_transform(convo_frame['q']) 
@app.route("/", methods=['GET', 'POST']) 
def get_response(): 
     input_str = request.values.get('Body') 
     def get_response(q): 
          my_q = vectorizer.transform([input_str]) 
          cs = cosine_similarity(my_q, vec) 
          rs = pd.Series(cs[0]).sort_values(ascending=0) 
          rsi = rs.index[0] 
          return convo_frame.iloc[rsi]['a'] 
    resp = twilio.twiml.Response() 
    if input_str: 
         resp.message(get_response(input_str)) 
         return str(resp) 
    else: 
         resp.message('Something bad happened here.') 
         return str(resp)

看起来有很多的事情,但实际上我们使用了和之前相同的代码,只是现在我们抓取了twilio发送的POST数据——消息正文——而不是之前手动输入get_request函数的数据。

如果所有都按计划进行,你应该已经拥有了自己的搞怪好友,你可以随时向它发送短消息,还有什么比这更棒的?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文