empatia-projekt/chatgui.py
2023-06-11 00:23:39 +02:00

119 lines
3.6 KiB
Python

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("<Return>", send)
EntryBox.bind("<FocusIn>", on_entry_focus_in)
EntryBox.bind("<FocusOut>", 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()