diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..53550da0f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/__pycache__ +/venv \ No newline at end of file diff --git a/app.py b/app.py index e69de29bb..b6fccf1b0 100644 --- a/app.py +++ b/app.py @@ -0,0 +1,22 @@ +from flask import Flask, render_template, request, jsonify +from chat import get_response + +app = Flask(__name__) + + +@app.get("/") +def index_get(): + return render_template("base.html") + + +@app.post("/predict") +def predict(): + text = request.get_json().get("message") + # TODO: check if the text is valid + response = get_response(text) + message = {"answer": response} + return jsonify(message) + + +if __name__ == "__main__": + app.run(debug=True) diff --git a/chat.py b/chat.py index 1abbbee6f..b6b213734 100644 --- a/chat.py +++ b/chat.py @@ -25,7 +25,8 @@ model.load_state_dict(model_state) model.eval() -bot_name = "Sam" +bot_name = "SDF" + def get_response(msg): sentence = tokenize(msg) @@ -44,18 +45,16 @@ def get_response(msg): for intent in intents['intents']: if tag == intent["tag"]: return random.choice(intent['responses']) - + return "I do not understand..." if __name__ == "__main__": print("Let's chat! (type 'quit' to exit)") while True: - # sentence = "do you use credit cards?" sentence = input("You: ") if sentence == "quit": break resp = get_response(sentence) print(resp) - diff --git a/data.pth b/data.pth new file mode 100644 index 000000000..b6b09a80a Binary files /dev/null and b/data.pth differ diff --git a/intents.bak b/intents.bak new file mode 100644 index 000000000..18e0891b3 --- /dev/null +++ b/intents.bak @@ -0,0 +1,84 @@ +{ + "intents": [ + { + "tag": "greeting", + "patterns": [ + "Hi", + "Hey", + "How are you", + "Is anyone there?", + "Hello", + "Good day" + ], + "responses": [ + "Hey :-)", + "Hello, thanks for visiting", + "Hi there, what can I do for you?", + "Hi there, how can I help?" + ] + }, + { + "tag": "goodbye", + "patterns": ["Bye", "See you later", "Goodbye"], + "responses": [ + "See you later, thanks for visiting", + "Have a nice day", + "Bye! Come back again soon." + ] + }, + { + "tag": "thanks", + "patterns": ["Thanks", "Thank you", "That's helpful", "Thank's a lot!"], + "responses": ["Happy to help!", "Any time!", "My pleasure"] + }, + { + "tag": "items", + "patterns": [ + "Which items do you have?", + "What kinds of items are there?", + "What do you sell?" + ], + "responses": [ + "We sell coffee and tea", + "We have coffee and tea" + ] + }, + { + "tag": "payments", + "patterns": [ + "Do you take credit cards?", + "Do you accept Mastercard?", + "Can I pay with Paypal?", + "Are you cash only?" + ], + "responses": [ + "We accept VISA, Mastercard and Paypal", + "We accept most major credit cards, and Paypal" + ] + }, + { + "tag": "delivery", + "patterns": [ + "How long does delivery take?", + "How long does shipping take?", + "When do I get my delivery?" + ], + "responses": [ + "Delivery takes 2-4 days", + "Shipping takes 2-4 days" + ] + }, + { + "tag": "funny", + "patterns": [ + "Tell me a joke!", + "Tell me something funny!", + "Do you know a joke?" + ], + "responses": [ + "Why did the hipster burn his mouth? He drank the coffee before it was cool.", + "What did the buffalo say when his son left for college? Bison." + ] + } + ] +} diff --git a/intents.json b/intents.json index 18e0891b3..d9f1d7239 100644 --- a/intents.json +++ b/intents.json @@ -1,84 +1,147 @@ { - "intents": [ - { - "tag": "greeting", - "patterns": [ - "Hi", - "Hey", - "How are you", - "Is anyone there?", - "Hello", - "Good day" - ], - "responses": [ - "Hey :-)", - "Hello, thanks for visiting", - "Hi there, what can I do for you?", - "Hi there, how can I help?" - ] - }, - { - "tag": "goodbye", - "patterns": ["Bye", "See you later", "Goodbye"], - "responses": [ - "See you later, thanks for visiting", - "Have a nice day", - "Bye! Come back again soon." - ] - }, - { - "tag": "thanks", - "patterns": ["Thanks", "Thank you", "That's helpful", "Thank's a lot!"], - "responses": ["Happy to help!", "Any time!", "My pleasure"] - }, - { - "tag": "items", - "patterns": [ - "Which items do you have?", - "What kinds of items are there?", - "What do you sell?" - ], - "responses": [ - "We sell coffee and tea", - "We have coffee and tea" - ] - }, - { - "tag": "payments", - "patterns": [ - "Do you take credit cards?", - "Do you accept Mastercard?", - "Can I pay with Paypal?", - "Are you cash only?" - ], - "responses": [ - "We accept VISA, Mastercard and Paypal", - "We accept most major credit cards, and Paypal" - ] - }, - { - "tag": "delivery", - "patterns": [ - "How long does delivery take?", - "How long does shipping take?", - "When do I get my delivery?" - ], - "responses": [ - "Delivery takes 2-4 days", - "Shipping takes 2-4 days" - ] - }, - { - "tag": "funny", - "patterns": [ - "Tell me a joke!", - "Tell me something funny!", - "Do you know a joke?" - ], - "responses": [ - "Why did the hipster burn his mouth? He drank the coffee before it was cool.", - "What did the buffalo say when his son left for college? Bison." - ] - } - ] -} + "intents": [ + { + "tag": "greetings", + "patterns": [ + "Hi", + "Hey", + "How are you", + "Is anyone there?", + "Hello", + "Good day", + "Hi there" + ], + "responses": [ + "Hello thanks for checking in", + "Hi there, how can i help you", + "Hi there, what can I do for you?", + "Hi there, how can I help?" + ] + }, + { + "tag": "goodbye", + "patterns": [ + "bye", + "good bye", + "see you later" + ], + "responses": [ + "have a nice time, welcome back again", + "bye bye" + ] + }, + { + "tag": "thanks", + "patterns": [ + "Thanks", + "okay", + "Thank you", + "thankyou", + "That's helpful", + "Awesome, thanks", + "Thanks for helping me", + "wow", + "great" + ], + "responses": [ + "Happy to help!", + "Any time!", + "you're welcome", + "My pleasure" + ] + }, + { + "tag": "noanswer", + "patterns": [ + "" + ], + "responses": [ + "Sorry, I didn't understand you", + "Please give me more info", + "Not sure I understand that" + ] + }, + { + "tag": "name1", + "patterns": [ + "what's your name?", + "who are you?" + ], + "responses": [ + "I'm just an SDF virtual agent. I only exist in the world of DoFPD", + "I'm a SDF virtual chat agent" + ] + }, + { + "tag": "name", + "patterns": [ + "my name is ", + "I'm ", + "I am" + ], + "responses": [ + "Oooh great to meet you ! How may I assist you ", + "Oh, I'll keep that in mind" + ] + }, + { + "tag": "charge", + "patterns": [ + "Whether charge lower than the SDF charge be ceded?", + "what is the charge of SDF, lower than the SDF charge be ceded?", + "May I know the Charge", + "may i know the charge" + ], + "responses": [ + "Oh Yes, it can be ceded", + "It is ceded", + "it can be ceded" + ] + }, + { + "tag": "nodal", + "patterns": [ + "which nodal agency for cooperative factories?", + "Who will be the nodal agency for processing NOC request?", + "can you help me, which nodal agency for co-operative sugar factories for processing NOC requests?", + "who will process NOC request for co-operative sugar factories?" + ], + "responses": [ + "IFCI for private sugar factories and NCDC for co-operative sugar factories." + ] + }, + { + "tag": "private", + "patterns": [ + "Which is the nodal agency for private sugar factories for processing NOC requests?", + "private nodal agency", + "nodal agency for private sugar factories", + "Please tell me the nodal agency for private factories", + "Will you help me as a prive sugar factory ownere, which agency will facilitate in this?", + "private agency", + "private organization", + "private organisation" + ], + "responses": [ + "Yes, here is the link https://www.ifciltd.com/", + "yes IFCL", + "Hey! you can visit https://www.ifciltd.com/", + "I am sure it's Industrial Finance Corporation of India (IFCI)" + ] + }, + { + "tag": "loan application ", + "patterns": [ + "SDF Loan", + "sdf loan", + "loan link", + "loan form" + ], + "responses": [ + "https://sdfportal.in/Login", + "https://dfpd.gov.in/SDF-Main.htm" + ] + + } + ] +} \ No newline at end of file diff --git a/standalone-frontend/app.js b/standalone-frontend/app.js deleted file mode 100644 index 6bdf287d1..000000000 --- a/standalone-frontend/app.js +++ /dev/null @@ -1,91 +0,0 @@ -class Chatbox { - constructor() { - this.args = { - openButton: document.querySelector('.chatbox__button'), - chatBox: document.querySelector('.chatbox__support'), - sendButton: document.querySelector('.send__button') - } - - this.state = false; - this.messages = []; - } - - display() { - const {openButton, chatBox, sendButton} = this.args; - - openButton.addEventListener('click', () => this.toggleState(chatBox)) - - sendButton.addEventListener('click', () => this.onSendButton(chatBox)) - - const node = chatBox.querySelector('input'); - node.addEventListener("keyup", ({key}) => { - if (key === "Enter") { - this.onSendButton(chatBox) - } - }) - } - - toggleState(chatbox) { - this.state = !this.state; - - // show or hides the box - if(this.state) { - chatbox.classList.add('chatbox--active') - } else { - chatbox.classList.remove('chatbox--active') - } - } - - onSendButton(chatbox) { - var textField = chatbox.querySelector('input'); - let text1 = textField.value - if (text1 === "") { - return; - } - - let msg1 = { name: "User", message: text1 } - this.messages.push(msg1); - - fetch('http://127.0.0.1:5000/predict', { - method: 'POST', - body: JSON.stringify({ message: text1 }), - mode: 'cors', - headers: { - 'Content-Type': 'application/json' - }, - }) - .then(r => r.json()) - .then(r => { - let msg2 = { name: "Sam", message: r.answer }; - this.messages.push(msg2); - this.updateChatText(chatbox) - textField.value = '' - - }).catch((error) => { - console.error('Error:', error); - this.updateChatText(chatbox) - textField.value = '' - }); - } - - updateChatText(chatbox) { - var html = ''; - this.messages.slice().reverse().forEach(function(item, index) { - if (item.name === "Sam") - { - html += '
' + item.message + '
' - } - else - { - html += '
' + item.message + '
' - } - }); - - const chatmessage = chatbox.querySelector('.chatbox__messages'); - chatmessage.innerHTML = html; - } -} - - -const chatbox = new Chatbox(); -chatbox.display(); \ No newline at end of file diff --git a/standalone-frontend/base.html b/standalone-frontend/base.html deleted file mode 100644 index c2c3b5c39..000000000 --- a/standalone-frontend/base.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - Chatbot - - -
-
-
-
-
- image -
-
-

Chat support

-

Hi. My name is Sam. How can I help you?

-
-
-
-
-
- -
-
- -
-
-
- - - - - \ No newline at end of file diff --git a/standalone-frontend/images/chatbox-icon.svg b/standalone-frontend/images/chatbox-icon.svg deleted file mode 100644 index 15617acc8..000000000 --- a/standalone-frontend/images/chatbox-icon.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/standalone-frontend/style.css b/standalone-frontend/style.css deleted file mode 100644 index a6dcf2585..000000000 --- a/standalone-frontend/style.css +++ /dev/null @@ -1,200 +0,0 @@ -* { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -body { - font-family: 'Nunito', sans-serif; - font-weight: 400; - font-size: 100%; - background: #F1F1F1; -} - -*, html { - --primaryGradient: linear-gradient(93.12deg, #581B98 0.52%, #9C1DE7 100%); - --secondaryGradient: linear-gradient(268.91deg, #581B98 -2.14%, #9C1DE7 99.69%); - --primaryBoxShadow: 0px 10px 15px rgba(0, 0, 0, 0.1); - --secondaryBoxShadow: 0px -10px 15px rgba(0, 0, 0, 0.1); - --primary: #581B98; -} - -/* CHATBOX -=============== */ -.chatbox { - position: absolute; - bottom: 30px; - right: 30px; -} - -/* CONTENT IS CLOSE */ -.chatbox__support { - display: flex; - flex-direction: column; - background: #eee; - width: 300px; - height: 350px; - z-index: -123456; - opacity: 0; - transition: all .5s ease-in-out; -} - -/* CONTENT ISOPEN */ -.chatbox--active { - transform: translateY(-40px); - z-index: 123456; - opacity: 1; - -} - -/* BUTTON */ -.chatbox__button { - text-align: right; -} - -.send__button { - padding: 6px; - background: transparent; - border: none; - outline: none; - cursor: pointer; -} - - -/* HEADER */ -.chatbox__header { - position: sticky; - top: 0; - background: orange; -} - -/* MESSAGES */ -.chatbox__messages { - margin-top: auto; - display: flex; - overflow-y: scroll; - flex-direction: column-reverse; -} - -.messages__item { - background: orange; - max-width: 60.6%; - width: fit-content; -} - -.messages__item--operator { - margin-left: auto; -} - -.messages__item--visitor { - margin-right: auto; -} - -/* FOOTER */ -.chatbox__footer { - position: sticky; - bottom: 0; -} - -.chatbox__support { - background: #f9f9f9; - height: 450px; - width: 350px; - box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); - border-top-left-radius: 20px; - border-top-right-radius: 20px; -} - -/* HEADER */ -.chatbox__header { - background: var(--primaryGradient); - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - padding: 15px 20px; - border-top-left-radius: 20px; - border-top-right-radius: 20px; - box-shadow: var(--primaryBoxShadow); -} - -.chatbox__image--header { - margin-right: 10px; -} - -.chatbox__heading--header { - font-size: 1.2rem; - color: white; -} - -.chatbox__description--header { - font-size: .9rem; - color: white; -} - -/* Messages */ -.chatbox__messages { - padding: 0 20px; -} - -.messages__item { - margin-top: 10px; - background: #E0E0E0; - padding: 8px 12px; - max-width: 70%; -} - -.messages__item--visitor, -.messages__item--typing { - border-top-left-radius: 20px; - border-top-right-radius: 20px; - border-bottom-right-radius: 20px; -} - -.messages__item--operator { - border-top-left-radius: 20px; - border-top-right-radius: 20px; - border-bottom-left-radius: 20px; - background: var(--primary); - color: white; -} - -/* FOOTER */ -.chatbox__footer { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - padding: 20px 20px; - background: var(--secondaryGradient); - box-shadow: var(--secondaryBoxShadow); - border-bottom-right-radius: 10px; - border-bottom-left-radius: 10px; - margin-top: 20px; -} - -.chatbox__footer input { - width: 80%; - border: none; - padding: 10px 10px; - border-radius: 30px; - text-align: left; -} - -.chatbox__send--footer { - color: white; -} - -.chatbox__button button, -.chatbox__button button:focus, -.chatbox__button button:visited { - padding: 10px; - background: white; - border: none; - outline: none; - border-top-left-radius: 50px; - border-top-right-radius: 50px; - border-bottom-left-radius: 50px; - box-shadow: 0px 10px 15px rgba(0, 0, 0, 0.1); - cursor: pointer; -} diff --git a/static/app.js b/static/app.js index e69de29bb..628f9b846 100644 --- a/static/app.js +++ b/static/app.js @@ -0,0 +1,83 @@ +class Chatbox { + constructor() { + this.args = { + openButton: document.querySelector(".chatbox__button"), + chatBox: document.querySelector(".chatbox__support"), + sendButton: document.querySelector(".send__button"), + }; + this.state = false; + this.messages = []; + } + display() { + const { openButton, chatBox, sendButton } = this.args; + openButton.addEventListener("click", () => this.toggleState(chatBox)); + sendButton.addEventListener("click", () => this.onSendButton(chatBox)); + + const node = chatBox.querySelector("input"); + node.addEventListener("keyup", ({ key }) => { + if (key === "Enter") { + this.onSendButton(chatBox); + } + }); + } + toggleState(chatbox) { + this.state = !this.state; + if (this.state) { + chatbox.classList.add("chatbox--active"); + } else { + chatbox.classList.remove("chatbox--active"); + } + } + onSendButton(chatbox) { + let textField = chatbox.querySelector("input"); + let text1 = textField.value; + if (text1 === "") { + return; + } + let msg1 = { name: "User", message: text1 }; + this.messages.push(msg1); + + fetch($SCRIPT_ROOT + "/predict", { + method: "POST", + body: JSON.stringify({ message: text1 }), + mode: "cors", + headers: { "Content-Type": "application/json" }, + }) + .then((r) => r.json()) + .then((r) => { + let msg2 = { name: "SDF", message: r.answer }; + this.messages.push(msg2); + this.updateChatText(chatbox); + textField.value = ""; + }) + .catch((error) => { + console.error("Error: ", error); + this.updateChatText(chatbox); + textField.value = ""; + }); + } + updateChatText(chatbox) { + let html = ""; + this.messages + .slice() + .reverse() + .forEach(function (item) { + if (item.name === "SDF") { + html += + '
' + + item.message + + "
"; + } else { + html += + '
' + + item.message + + "
"; + } + }); + const chatmessage = chatbox.querySelector(".chatbox__messages"); + chatmessage.innerHTML = html; + } +} + +const chatbox = new Chatbox(); +chatbox.display(); diff --git a/templates/base.html b/templates/base.html index 80834196b..fecf57f15 100644 --- a/templates/base.html +++ b/templates/base.html @@ -16,7 +16,7 @@

Chat support

-

Hi. My name is Sam. How can I help you?

+

Hi. I'm SDF Virtual Agent. How can I help you?

diff --git a/train.py b/train.py index 3555f040a..0002a8b6d 100644 --- a/train.py +++ b/train.py @@ -29,7 +29,7 @@ xy.append((w, tag)) # stem and lower each word -ignore_words = ['?', '.', '!'] +ignore_words = ['?', '.', '!', ","] all_words = [stem(w) for w in all_words if w not in ignore_words] # remove duplicates and sort all_words = sorted(set(all_words)) @@ -53,7 +53,7 @@ X_train = np.array(X_train) y_train = np.array(y_train) -# Hyper-parameters +# Hyper-parameters num_epochs = 1000 batch_size = 8 learning_rate = 0.001 @@ -62,6 +62,7 @@ output_size = len(tags) print(input_size, output_size) + class ChatDataset(Dataset): def __init__(self): @@ -77,6 +78,7 @@ def __getitem__(self, index): def __len__(self): return self.n_samples + dataset = ChatDataset() train_loader = DataLoader(dataset=dataset, batch_size=batch_size, @@ -96,31 +98,31 @@ def __len__(self): for (words, labels) in train_loader: words = words.to(device) labels = labels.to(dtype=torch.long).to(device) - + # Forward pass outputs = model(words) # if y would be one-hot, we must apply # labels = torch.max(labels, 1)[1] loss = criterion(outputs, labels) - + # Backward and optimize optimizer.zero_grad() loss.backward() optimizer.step() - + if (epoch+1) % 100 == 0: - print (f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}') + print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}') print(f'final loss: {loss.item():.4f}') data = { -"model_state": model.state_dict(), -"input_size": input_size, -"hidden_size": hidden_size, -"output_size": output_size, -"all_words": all_words, -"tags": tags + "model_state": model.state_dict(), + "input_size": input_size, + "hidden_size": hidden_size, + "output_size": output_size, + "all_words": all_words, + "tags": tags } FILE = "data.pth"