import json import pickle import random from tkinter import * import nltk import numpy as np import text2emotion as te from keras.models import load_model from nltk.stem import WordNetLemmatizer lemmatizer = WordNetLemmatizer() model = load_model('chatbot_model.h5') intents = json.loads(open('intents.json', encoding='utf-8').read()) intents = {i['tag']: (i['patterns'], i['responses']) for i in intents} words = pickle.load(open('words.pkl', 'rb')) classes = pickle.load(open('classes.pkl', 'rb')) def clean_up_text(text): text_words = nltk.word_tokenize(text) text_words = [lemmatizer.lemmatize(word.lower()) for word in text_words] return text_words def predict_class(text): bow = np.array([1 if w in clean_up_text(text) else 0 for w in words]) pred = model.predict(np.array([bow]))[0] return classes[np.argmax(pred)] def chatbot_response(text, emotion): intent = predict_class(text) return random.choice(intents[intent][1][emotion]) def determine_emotion(text): emotions = te.get_emotion(text) emotion = max(emotions, key=emotions.get) return 'Neutral' if emotion == 'Surprise' or emotions[emotion] < 0.5 else emotion def update_image(emotion): global image if emotion == "Happy": image = PhotoImage(file="happy.png") elif emotion == "Angry": image = PhotoImage(file="concerned.png") elif emotion in ["Sad", "Fear"]: image = PhotoImage(file="reassuring.png") else: image = PhotoImage(file="neutral.png") image_label.configure(image=image) def send(event): msg = EntryBox.get("1.0", 'end-1c').strip() EntryBox.delete("0.0", END) if msg: emotion = determine_emotion(msg) update_image(emotion) ChatLog.config(state=NORMAL) ChatLog.insert(END, "You: " + msg + '\n\n') ChatLog.config(foreground="#442265", font=("Verdana", 12)) res = chatbot_response(msg, emotion) ChatLog.insert(END, "Bot: " + res + '\n\n') ChatLog.config(state=DISABLED) ChatLog.yview(END) return 'break' def on_entry_focus_in(event): if EntryBox.get("1.0", END).strip() == DEFAULT_TEXT: EntryBox.delete("1.0", END) EntryBox.config(fg="black") def on_entry_focus_out(event): if EntryBox.get("1.0", END).strip() == "": EntryBox.insert(END, DEFAULT_TEXT) EntryBox.config(fg="grey") DEFAULT_TEXT = 'Enter text here' GAP = 5 WINDOW_WIDTH = 600 WINDOW_HEIGHT = 400 CHAT_WIDTH = WINDOW_WIDTH - 30 ENTRY_HEIGHT = 100 IMAGE_HEIGHT = 100 CHAT_HEIGHT = WINDOW_HEIGHT - ENTRY_HEIGHT - IMAGE_HEIGHT - 4 * GAP base = Tk() base.title("Empathic Robot") base.geometry(f"{WINDOW_WIDTH}x{WINDOW_HEIGHT}") base.resizable(width=FALSE, height=FALSE) ChatLog = Text(base, bd=0, bg="white", font="Arial") ChatLog.config(state=DISABLED) scrollbar = Scrollbar(base, command=ChatLog.yview, cursor="heart") ChatLog['yscrollcommand'] = scrollbar.set EntryBox = Text(base, bd=0, bg="white", font="Arial") EntryBox.insert(END, DEFAULT_TEXT) EntryBox.config(fg="grey") EntryBox.bind("", send) EntryBox.bind("", on_entry_focus_in) EntryBox.bind("", on_entry_focus_out) image = PhotoImage(file="neutral.png") image_label = Label(base, image=image) image_label.place(x=GAP, y=GAP, width=WINDOW_WIDTH - 2 * GAP, height=IMAGE_HEIGHT) scrollbar.place(x=CHAT_WIDTH + GAP, y=IMAGE_HEIGHT + 2 * GAP, height=CHAT_HEIGHT) ChatLog.place(x=GAP, y=IMAGE_HEIGHT + 2 * GAP, height=CHAT_HEIGHT, width=CHAT_WIDTH) EntryBox.place(x=GAP, y=IMAGE_HEIGHT + CHAT_HEIGHT + 3 * GAP, height=ENTRY_HEIGHT, width=WINDOW_WIDTH - 2 * GAP) base.mainloop()