Người dùng Apple, Microsoft, chắc hẳn đã rất quen thuộc với các cô nàng trợ lý ảo dễ thương như Siri, Cortana. Các ông lớn như Google, Facebook, Amazon…cũng đã có những trợ lý ảo riêng cho mình. Điều này làm cho khái niệm chatbot cũng trở lên quen thuộc hơn với người dùng. Vậy làm thế nào để tự xây dựng chatbot cho riêng mình, chúng ta hãy cũng theo dõi bài hướng dẫn này để có thể xây dựng một chatbot đơn giản nhé.
Bài viết này được dịch từ: Python Chatbot Project – Learn to build your first chatbot using NLTK & Keras
Giới Thiệu Về Project Xây Dựng Chatbot
Trong project này chúng ta sẽ xây dựng chatbot bằng cách sử dụng các kỹ thuật Deep learning. Chatbot sẽ được training trên tập dữ liệu chứa các mẫu đầu vào và các phản hồi tương ứng. Sử dụng mạng LSTM để phân loại thông điệp của người dùng thuộc danh mục nào và sau đó sẽ trả về phản hồi ngẫu nhiên từ danh sách các phản hồi.
Bây giờ, hãy tạo một chatbot sử dụng NLTK, Keras, python… NLTK (bộ công cụ ngôn ngữ tự nhiên) là một thư viện Python phổ biến được sử dụng cho NLP ( Natural Language Processing)
Bộ Dữ Liệu Sử Dụng
Bộ dữ liệu được sử dụng trong project này là intents.json. Đây là một tệp JSON chứa các mẫu đầu vào và các phản hồi tương ứng trả lại cho người dùng.
Tải xuống: Tại Đây
Yêu Cầu Cho Project
Project này yêu cầu bạn phải có kiến thức tốt về Python, Keras và Natural language processing (NLTK).
Hãy cài đặt các thư viện cần thiết bằng lệnh dưới đây
pip install tensorflow, keras, pickle, nltk
Nội Dung Chính
1. Chatbot Là Gì?
Chatbot là một phần mềm thông minh có khả năng giao tiếp và thực hiện các hành động tương tự như con người. Chatbots được sử dụng rất nhiều trong tương tác với khách hàng, tiếp thị trên các trang mạng xã hội và trả lời tin nhắn tự động với khách hàng… Có hai loại mô hình chatbot cơ bản là: Retrieval based và Generative based models.
1.1. Retrieval based Chatbots
Retrieval-based chatbot sử dụng các mẫu đầu vào và các phản hồi tương ứng đã được định nghĩa từ trước. Sau đó, nó sử dụng một số loại phương pháp tiếp cận heuristic để chọn câu trả lời thích hợp nhất với đầu vào (input) và bối cảnh (context). Heuristic ở đây có thể đơn giản là các kĩ thuật khớp luật (rule-based expression matching). Retrieval-based chatbot không thể tạo ra bất kỳ từ mới nào khác, chúng chỉ lấy một số câu trả lời từ một tập có sẵn.
1.2. Generative based Chatbots
Những mô hình như thế này không dựa vào tập phản hồi định nghĩa trước. Chúng dựa trên mạng nơ-ron Sequence to Sequence, được phát triển dựa trên bài toán Dịch Máy (Machine translation). Nhưng thay vì dịch từ ngôn ngữ này sang ngôn ngữ khác, mô hình này sẽ dịch từ input ra output, tức là chúng có thể truy xuất thông tin từ input và phản hồi lại một cách ấn tượng như bạn đang nói chuyện với con người. Generative based Chatbot sẽ cần một lượng lớn dữ liệu và training trên mạng Deep Neural.
2. Cấu Trúc Tệp Của Project
Trước tiên, chúng ta sẽ xem cấu trúc tệp và các loại tệp mà chúng ta cần tạo
- Intents.json – Tệp dữ liệu có các mẫu và phản hồi được xác định trước.
- train_chatbot.py – Xây dựng mô hình và đào tạo chatbot.
- Words.pkl – Đây là một tệp nhỏ trong đó lưu trữ các từ đối tượng Python chứa danh sách từ vựng.
- Classes.pkl – Tệp chọn lớp chứa danh sách các danh mục.
- Chatbot_model.h5 – Đây là mô hình đào tạo có chứa thông tin về mô hình và trọng số của các neurons.
- Chatgui.py – Giao diện GUI của chatbot, để người dùng có thể dễ dàng tương tác với bot.
3. Xây Dựng Chatbot Bằng NLTK và Keras
Dưới đây là 5 bước để tạo một chatbot bằng Python từ đầu
- Import và load tệp dữ liệu
- Tiền xử lý dữ liệu
- Tạo tập dữ liệu đào tạo và kiểm tra
- Xây dựng mô hình
- Kiểm tra kết quả
3.1. Import và load tệp dữ liệu
Đầu tiên, đặt tên tệp là train_chatbot.py. Import các thư viện cần thiết cho chatbot và khởi tạo các biến sẽ sử dụng trong project.
Tệp dữ liệu có dạng Json nên chúng ta sẽ import gói Json để phân tích.
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import json
import pickle
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from keras.optimizers import SGD
import random
words=[]
classes = []
documents = []
ignore_words = ['?', '!']
data_file = open('intents.json').read()
intents = json.loads(data_file)
Tệp intents.json có dạng như hình dưới đây:
3.2. Tiền xử lý dữ liệu
Khi làm việc với dữ liệu văn bản, chúng ta cần thực hiện tiền xử lý trên dữ liệu trước khi chúng ta tạo ra một mô hình ML hoặc DL. Tokenizing là điều cơ bản nhất và đầu tiên bạn có thể làm trên dữ liệu văn bản. Tokenizing là quá trình chia toàn bộ văn bản thành các phần nhỏ như các từ.
for intent in intents['intents']:
for pattern in intent['patterns']:
#tokenize each word
w = nltk.word_tokenize(pattern)
words.extend(w)
#add documents in the corpus
documents.append((w, intent['tag']))
# add to our classes list
if intent['tag'] not in classes:
classes.append(intent['tag'])
Bây giờ chúng ta sẽ bổ sung từng từ và xóa các từ trùng lặp khỏi danh sách.
# lemmatize, lower each word and remove duplicates
words = [lemmatizer.lemmatize(w.lower()) for w in words if w not in ignore_words]
words = sorted(list(set(words)))
# sort classes
classes = sorted(list(set(classes)))
# documents = combination between patterns and intents
print (len(documents), "documents")
# classes = intents
print (len(classes), "classes", classes)
# words = all words, vocabulary
print (len(words), "unique lemmatized words", words)
pickle.dump(words,open('words.pkl','wb'))
pickle.dump(classes,open('classes.pkl','wb'))
3.3. Tạo tập dữ liệu đào tạo và kiểm tra
Tiếp theo, chúng ta sẽ tạo tập training bao gồm các input và output, input là các mẫu còn output là các câu trả lời tương ứng. Tuy nhiên, máy tính không thể hiểu văn bản nên ta sẽ thực hiện chuyển văn bản dạng chữ về dạng số.
# create our training data
training = []
# create an empty array for our output
output_empty = [0] * len(classes)
# training set, bag of words for each sentence
for doc in documents:
# initialize our bag of words
bag = []
# list of tokenized words for the pattern
pattern_words = doc[0]
# lemmatize each word - create base word, in attempt to represent related words
pattern_words = [lemmatizer.lemmatize(word.lower()) for word in pattern_words]
# create our bag of words array with 1, if word match found in current pattern
for w in words:
bag.append(1) if w in pattern_words else bag.append(0)
# output is a '0' for each tag and '1' for current tag (for each pattern)
output_row = list(output_empty)
output_row[classes.index(doc[1])] = 1
training.append([bag, output_row])
# shuffle our features and turn into np.array
random.shuffle(training)
training = np.array(training)
# create train and test lists. X - patterns, Y - intents
train_x = list(training[:,0])
train_y = list(training[:,1])
print("Training data created")
3.4. Xây dựng mô hình
Sau khi có được bộ training set, chúng ta sẽ thực hiện xây dựng 1 mạng neural với 3 layers bằng cách sử dụng Keras sequential API. Sau khi training mô hình với 200 epochs, mô hình đã đạt độ chính xác lên đến 100%. Tiếp theo chúng ta sẽ lưu mô hình dưới dạng ‘chatbot_model.h5’.
# Create model - 3 layers. First layer 128 neurons, second layer 64 neurons and 3rd output layer contains number of neurons
# equal to number of intents to predict output intent with softmax
model = Sequential()
model.add(Dense(128, input_shape=(len(train_x[0]),), activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(len(train_y[0]), activation='softmax'))
# Compile model. Stochastic gradient descent with Nesterov accelerated gradient gives good results for this model
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
#fitting and saving the model
hist = model.fit(np.array(train_x), np.array(train_y), epochs=200, batch_size=5, verbose=1)
model.save('chatbot_model.h5', hist)
print("model created")
3.5. Dự đoán phản hồi (Giao diện người dùng)
Bây giờ để dự đoán các câu và nhận được phản hồi từ người dùng, chúng ta sẽ tạo một tệp mới là ‘chatapp.py’.
Chúng ta sẽ load mô hình được đào tạo và sau đó sử dụng giao diện người dùng đồ họa (GUI) để dự đoán phản hồi từ bot.
Mô hình sẽ chỉ cho chúng ta biết lớp mà nó thuộc về, vì vậy chúng ta sẽ triển khai một số hàm để xác định lớp và sau đó lấy cho chúng ta một phản hồi ngẫu nhiên từ danh sách các phản hồi.
Một lần nữa, chúng ta import các gói cần thiết và tải các tệp pickle ‘words.pkl’ và ‘class.pkl’ mà chúng ta đã tạo khi đào tạo mô hình của mình:
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import pickle
import numpy as np
from keras.models import load_model
model = load_model('chatbot_model.h5')
import json
import random
intents = json.loads(open('intents.json').read())
words = pickle.load(open('words.pkl','rb'))
classes = pickle.load(open('classes.pkl','rb'))
Để dự đoán lớp, chúng ta cần cung cấp thông tin đầu vào giống như cách chúng ta đã làm khi training. Vì vậy, chúng ta sẽ tạo một số hàm để thực hiện tiền xử lý văn bản và sau đó dự đoán lớp.
def clean_up_sentence(sentence):
# tokenize the pattern - split words into array
sentence_words = nltk.word_tokenize(sentence)
# stem each word - create short form for word
sentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words]
return sentence_words
# return bag of words array: 0 or 1 for each word in the bag that exists in the sentence
def bow(sentence, words, show_details=True):
# tokenize the pattern
sentence_words = clean_up_sentence(sentence)
# bag of words - matrix of N words, vocabulary matrix
bag = [0]*len(words)
for s in sentence_words:
for i,w in enumerate(words):
if w == s:
# assign 1 if current word is in the vocabulary position
bag[i] = 1
if show_details:
print ("found in bag: %s" % w)
return(np.array(bag))
def predict_class(sentence, model):
# filter out predictions below a threshold
p = bow(sentence, words,show_details=False)
res = model.predict(np.array([p]))[0]
ERROR_THRESHOLD = 0.25
results = [[i,r] for i,r in enumerate(res) if r>ERROR_THRESHOLD]
# sort by strength of probability
results.sort(key=lambda x: x[1], reverse=True)
return_list = []
for r in results:
return_list.append({"intent": classes[r[0]], "probability": str(r[1])})
return return_list
Sau khi dự đoán được lớp, ta sẽ nhận được phản hồi ngẫu nhiên từ danh sách intents.
def getResponse(ints, intents_json):
tag = ints[0]['intent']
list_of_intents = intents_json['intents']
for i in list_of_intents:
if(i['tag']== tag):
result = random.choice(i['responses'])
break
return result
def chatbot_response(text):
ints = predict_class(text, model)
res = getResponse(ints, intents)
return res
Bây giờ chúng ta sẽ code phần giao diện người dùng (GUI). Ta sẽ sử dụng thư viện Tkinter đã tích hợp sẵn trong python. Bằng cách lấy thông tin đầu vào từ người dùng và sau đó sử dụng các functions mà chúng ta đã tạo để nhận phản hồi từ bot và hiển thị nó trên GUI. Dưới đây là code của phần GUI:
#Creating GUI with tkinter
import tkinter
from tkinter import *
def send():
msg = EntryBox.get("1.0",'end-1c').strip()
EntryBox.delete("0.0",END)
if msg != '':
ChatLog.config(state=NORMAL)
ChatLog.insert(END, "You: " + msg + '\n\n')
ChatLog.config(foreground="#442265", font=("Verdana", 12 ))
res = chatbot_response(msg)
ChatLog.insert(END, "Bot: " + res + '\n\n')
ChatLog.config(state=DISABLED)
ChatLog.yview(END)
base = Tk()
base.title("Hello")
base.geometry("400x500")
base.resizable(width=FALSE, height=FALSE)
#Create Chat window
ChatLog = Text(base, bd=0, bg="white", height="8", width="50", font="Arial",)
ChatLog.config(state=DISABLED)
#Bind scrollbar to Chat window
scrollbar = Scrollbar(base, command=ChatLog.yview, cursor="heart")
ChatLog['yscrollcommand'] = scrollbar.set
#Create Button to send message
SendButton = Button(base, font=("Verdana",12,'bold'), text="Send", width="12", height=5,
bd=0, bg="#32de97", activebackground="#3c9d9b",fg='#ffffff',
command= send )
#Create the box to enter message
EntryBox = Text(base, bd=0, bg="white",width="29", height="5", font="Arial")
#EntryBox.bind("", send)
#Place all components on the screen
scrollbar.place(x=376,y=6, height=386)
ChatLog.place(x=6,y=6, height=386, width=370)
EntryBox.place(x=128, y=401, height=90, width=265)
SendButton.place(x=6, y=401, height=90)
base.mainloop()
4. Chạy thử chatbot
Chúng ta đã có 2 tệp chính là train_chatbot.py và chatapp.py.
Đầu tiên chúng ta cần train mô hình bằng cách chạy file train_chatbot.py với lệnh sau:
python train_chatbot.py
Nếu không thấy bất kỳ lỗi nào xảy ra trong quá trình training thì ta đã tạo mô hình thành công. Sau đó, để chạy ứng dụng ta sẽ chạy tiếp tệp chatapp.py bằng lệnh sau:
python chatgui.py
Chương trình sẽ mở ra cửa sổ GUI và ta có thể dễ dàng trò chuyện được với bot.
Kết Luận
Trong project này, chúng ta đã hiểu về chatbot và triển khai được phiên bản DL của chatbot bằng python. Bạn có thể tự điều chỉnh dữ liệu để training chatbot theo mục đích của mình. Chatbots được sử dụng ở mọi nơi và tất cả các doanh nghiệp đều mong muốn triển khai bot trong quy trình làm việc của họ.
Nguồn: Python Chatbot Project – Learn to build your first chatbot using NLTK & Keras