📜  使用 Python-NLTK 创建一个基本的硬编码 ChatBot(1)

📅  最后修改于: 2023-12-03 15:06:50.560000             🧑  作者: Mango

创建一个基本的 ChatBot

在本教程中,我们将使用 Python NLTK 创建一个基本的硬编码聊天机器人。这个聊天机器人将能够回答有关自己的问题,以及与它交谈的人的问题。我们将使用 NLTK 中的正则表达式和分类器来实现我们的聊天机器人。

步骤

以下是实现 ChatBot 的步骤:

  1. 导入必要的库和数据集
  2. 定义用于聊天的函数
  3. 构建分类器
  4. 构建聊天方法
  5. 测试 ChatBot

让我们逐一了解这些步骤。

导入必要的库和数据集

首先,我们需要导入 python 的一些库,包括 NLTK,以及一些数据集,如语料库、停用词列表等,我们可以通过以下代码来导入这些库和数据集:

import nltk
nltk.download('punkt')
nltk.download('wordnet')
nltk.download('stopwords')
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize, sent_tokenize
import string
import random

#我们还需要一些硬编码的回答,如下所示:
GREETING_INPUTS = ("hello", "hi", "greetings", "sup", "what's up", "hey",)
GREETING_RESPONSES = ["hi", "hey", "hi there", "hello", "I am glad! You are talking to me"]
定义用于聊天的函数

接下来,我们定义一个聊天机器人函数,该函数将在后面的步骤中使用。该函数使用 NLTK 中的 tokenizer 包将对话分成单独的句子和单词,然后使用词性还原器将每个单词转换为其基本形式。通过比较输入文本与预定义列表中的词汇,该函数可以回答一些简单的问题。以下是我们的聊天机器人代码:

def chatbot_response(user_response):
  # 定义 ChatBot 的回应
  bot_response = ''
  # 添加输入文本的拷贝,将其添加到 sent_tokens 列表中:
  sent_tokens.append(user_response)
  # 创建基于 TfidfVectorizer 的 tf-idf 特征矩阵:
  TfidfVec = TfidfVectorizer(tokenizer=LemNormalize, stop_words='english')
  tfidf = TfidfVec.fit_transform(sent_tokens)
  # 计算给定文本的相似度分数
  vals = cosine_similarity(tfidf[-1], tfidf)
  # 获取最相关的向量的索引
  idx = vals.argsort()[0][-2]
  # 计算 cosine 相似度
  flat = vals.flatten()
  flat.sort()
  score = flat[-2]
  # 如果没有找到相似的文本,则 bot 以没有理解的方式回复:
  if score == 0:
    bot_response = bot_response + "I apologize, I don't understand."
    return bot_response
  else:
    bot_response = bot_response + sent_tokens[idx]
    return bot_response
构建分类器

下一步是构建分类器。我们将使用 NLTK 中的 NaiveBayesClassifier,它将训练和分类文本。在此之前,我们将需要准备一些数据。以下代码片段显示了一些硬编码的对话,我们将使用这些数据来训练我们的分类器。

# 训练数据集
training_data = []
training_data.append({"class":"greeting", "sentence":"Hello, how are you?"})
training_data.append({"class":"greeting", "sentence":"What's up?"})
training_data.append({"class":"greeting", "sentence":"Hey there!"})
training_data.append({"class":"greeting", "sentence":"Hi, can I help you?"})
training_data.append({"class":"goodbye", "sentence":"Bye, take care"})
training_data.append({"class":"goodbye", "sentence":"Goodbye and have a nice day"})
training_data.append({"class":"goodbye", "sentence":"See you soon!"})
training_data.append({"class":"goodbye", "sentence":"See you later"})

接下来,我们将进行一些预处理,将这些数据转换为可以使用的格式。这涉及将每个句子拆分为单词,并将每个单词标记为与分类相关的单词。以下代码片段显示了该转换的代码:

#为分类器做准备: 首先,我们将准备分类器需要的数据集。对话数据集必须是一个字典列表,其中每个字典都包含一个“sentence”键和一个“class”键。
#“sentence”键存储对话句子,而“class”键存储与对话句子相关的类别,例如“greeting”或“goodbye”。
words = []
classes = []
documents = []
for pattern in training_data:
  # 将单词小写,并将它们添加到 words 列表中
  w = nltk.word_tokenize(pattern['sentence'].lower())
  words.extend(w)
  # 在 documents 列表中为每个模式添加船票
  documents.append((w, pattern['class']))
  # 添加到 classes 列表中
  if pattern['class'] not in classes:
    classes.append(pattern['class'])
# 将列表中的单词标准化和去重
words = [WordNetLemmatizer().lemmatize(word) for word in words if word not in stopwords.words('english')]
words = sorted(list(set(words)))
# 将类列表排序
classes = sorted(list(set(classes)))

现在,我们可以构建分类器了。我们将初始化一个空字典来存储每个单词在每个分类中出现的次数。我们将使用这些计数来训练我们的分类器。以下是分类器构建的代码:

#构建分类器: 现在,我们可以开始训练我们的分类器了。我们将使用NLTK的NaiveBayes分类器,它是一种简单而强大的分类器,可以训练和分类文本。
#首先,我们将初始化一个空字典,用于存储每个单词在每个类别中出现的次数。在此之后,我们将使用这些数字来训练我们的分类器。
training = []
output_empty = [0] * len(classes)
for doc in documents:
  # 初始化一个空的单词用于此文档
  bag = []
  # 获取单词列表并使用词性还原器将单词还原到它的基本形式。
  pattern_words = doc[0]
  pattern_words = [WordNetLemmatizer().lemmatize(word.lower()) for word in pattern_words]
  # 如果单词在当前的文档中出现,则将其添加到 bag 中
  for w in words:
    bag.append(1) if w in pattern_words else bag.append(0)
  # 输出是一个“0”或“1”列表,其中“0”表示目前所讨论的句子不属于该类,而“1”表示它属于该类
  output_row = list(output_empty)
  output_row[classes.index(doc[1])] = 1
  training.append([bag, output_row])
# 基于上面的训练数据,训练一个 nltk 的 classifier
random.shuffle(training)
training = np.array(training)
# train_X 是输入的词袋(bags)向量,train_y 是输出的向量(我们使用0或1表明训练数据中的类别)
train_x = list(training[:,0])
train_y = list(training[:,1])
classifier = nltk.NaiveBayesClassifier.train(train)
构建聊天方法

现在,我们已经准备好使用我们的分类器来构建一个聊天机器人了。我们将使用 input() 函数来接收用户输入,然后将其作为参数传递给我们的 chatbot_response() 函数。我们将不断调用此函数,直到用户输入“exit”为止。以下是我们的聊天方法:

def chat():
  # 打印机器人的欢迎消息
  print("Hello! I'm your personal ChatBot. How may I assist you today?")
  while True:
    # 获取输入文本
    user_response = input()
    # 如果用户输入“exit”,则跳出循环
    if user_response.lower() == 'exit':
      break
    # 如果用户输入无法理解的话,则 bot 将回复“我不理解”
    if chatbot_response(user_response) == None:
      print("I don't understand...")
    else:
      # 否则,机器人将返回其响应
      print(chatbot_response(user_response))
测试 ChatBot

好了,现在我们已经完成了所有的 coding 工作,现在是时候测试我们的 ChatBot 了。启动 ChatBot(运行聊天机器人函数),这个 chatbot 可以回答我们输入的任何问题。

chat()
结论

在本教程中,我们了解了如何使用 Python NLTK 构建一个聊天机器人。我们使用了正则表达式、分类器和 NLTK 中的一些数据集来完成这个任务。现在,你也可以基于本文尝试构建自己的 ChatBot。