├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── app.py ├── chatbot_model.h5 ├── classes.pkl ├── intents.json ├── static ├── css.css └── style.css ├── templates └── index.html ├── train.py └── words.pkl /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | maina@dentricedev.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Dennis_maina 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # An-AI-Chatbot-in-Python-and-Flask 2 | An AI Chatbot using Python and Flask REST API 3 | 4 | ## Requirements (libraries) 5 | 1. TensorFlow 6 | 1. Flask 7 | 8 | ## VsCode SetUp 9 | 1. Clone the repository-> cd into the cloned repository folder 10 | 2. Create a python virtual environment 11 | ``` 12 | # macOS/Linux 13 | # You may need to run sudo apt-get install python3-venv first 14 | python3 -m venv .venv 15 | 16 | # Windows 17 | # You can also use py -3 -m venv .venv 18 | python -m venv .venv 19 | ``` 20 | When you create a new virtual environment, a prompt will be displayed to allow you to select it for the workspace. 21 | 22 | 3. Activate the virtual environment 23 | ``` 24 | #linux 25 | source ./venv/bin/activate # sh, bash, or zsh 26 | 27 | #windows 28 | .\venv\Scripts\activate 29 | ``` 30 | 4. Run ```pip install --upgrade tensorflow``` to install ```Tensorflow``` 31 | 5. Run ```pip install -U nltk``` to install ```nltk``` 32 | 6. Run ```pip install -U Flask``` to install ```flask``` 33 | 7. To expose your bot via Ngrok, run ```pip install flask-ngrok``` to install ```flask-ngrok``` Then you'll need to configure your ngrok credentials(login: email + password) Then uncomment this line ```run_with_ngrok(app) ``` and comment the last two lines ```if __name__ == "__main__": app.run() ``` Notice that ngrok is not used by default. 34 | 8. To access your bot on localhost, go to ```http://127.0.0.1:5000/ ``` If you're on Ngrok your url will be ```some-text.ngrok.io``` 35 | 36 | ### Step-By-Step Explanation and Installation Guide 37 | > https://dentricedev.com/blog/how-to-create-an-ai-chatbot-in-python-and-flask-gvub 38 | > 39 | > https://dev.to/dennismaina/how-to-create-an-ai-chatbot-in-python-and-flask-1c3m 40 | ### Execution 41 | To run this Bot, first run the ```train.py``` file to train the model. This will generate a file named ```chatbot_model.h5```
42 | This is the model which will be used by the Flask REST API to easily give feedback without the need to retrain.
43 | After running ```train.py```, next run the ```app.py``` to initialize and start the bot.
44 | To add more terms and vocabulary to the bot, modify the ```intents.json``` file and add your personalized words and retrain the model again. 45 | 46 | 47 | 48 | ## Find me on 49 | [![Twitter][1.2]][1] [![LinkedIn][2.2]][2] 50 | 51 | 52 | 53 | [1.2]: http://i.imgur.com/wWzX9uB.png (Twitter) 54 | [2.2]: https://raw.githubusercontent.com/MartinHeinz/MartinHeinz/master/linkedin-3-16.png (LinkedIn) 55 | 56 | 57 | [1]: https://twitter.com/dennisjmaina 58 | [2]: https://www.linkedin.com/in/dennismaina/ 59 | [3]: https://instagram.com/denno.h_ 60 | 61 | ## Having troubles implementing? 62 | > Reach out to me maina@dentricedev.com 63 | I will be happy to assist 64 | # 65 | ## want something improved or added? 66 | > Fork the repo @ [GitHub](https://github.com/mainadennis/An-AI-Chatbot-in-Python-and-Flask). 67 | # 68 | ## Regards, 69 | > [DentriceDev Solutions](https://dentricedev.com). 70 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | # libraries 2 | import random 3 | import numpy as np 4 | import pickle 5 | import json 6 | from flask import Flask, render_template, request 7 | from flask_ngrok import run_with_ngrok 8 | import nltk 9 | from keras.models import load_model 10 | from nltk.stem import WordNetLemmatizer 11 | lemmatizer = WordNetLemmatizer() 12 | 13 | 14 | # chat initialization 15 | model = load_model("chatbot_model.h5") 16 | intents = json.loads(open("intents.json").read()) 17 | words = pickle.load(open("words.pkl", "rb")) 18 | classes = pickle.load(open("classes.pkl", "rb")) 19 | 20 | app = Flask(__name__) 21 | # run_with_ngrok(app) 22 | 23 | @app.route("/") 24 | def home(): 25 | return render_template("index.html") 26 | 27 | 28 | @app.route("/get", methods=["POST"]) 29 | def chatbot_response(): 30 | msg = request.form["msg"] 31 | if msg.startswith('my name is'): 32 | name = msg[11:] 33 | ints = predict_class(msg, model) 34 | res1 = getResponse(ints, intents) 35 | res =res1.replace("{n}",name) 36 | elif msg.startswith('hi my name is'): 37 | name = msg[14:] 38 | ints = predict_class(msg, model) 39 | res1 = getResponse(ints, intents) 40 | res =res1.replace("{n}",name) 41 | else: 42 | ints = predict_class(msg, model) 43 | res = getResponse(ints, intents) 44 | return res 45 | 46 | 47 | # chat functionalities 48 | def clean_up_sentence(sentence): 49 | sentence_words = nltk.word_tokenize(sentence) 50 | sentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words] 51 | return sentence_words 52 | 53 | 54 | # return bag of words array: 0 or 1 for each word in the bag that exists in the sentence 55 | def bow(sentence, words, show_details=True): 56 | # tokenize the pattern 57 | sentence_words = clean_up_sentence(sentence) 58 | # bag of words - matrix of N words, vocabulary matrix 59 | bag = [0] * len(words) 60 | for s in sentence_words: 61 | for i, w in enumerate(words): 62 | if w == s: 63 | # assign 1 if current word is in the vocabulary position 64 | bag[i] = 1 65 | if show_details: 66 | print("found in bag: %s" % w) 67 | return np.array(bag) 68 | 69 | 70 | def predict_class(sentence, model): 71 | # filter out predictions below a threshold 72 | p = bow(sentence, words, show_details=False) 73 | res = model.predict(np.array([p]))[0] 74 | ERROR_THRESHOLD = 0.25 75 | results = [[i, r] for i, r in enumerate(res) if r > ERROR_THRESHOLD] 76 | # sort by strength of probability 77 | results.sort(key=lambda x: x[1], reverse=True) 78 | return_list = [] 79 | for r in results: 80 | return_list.append({"intent": classes[r[0]], "probability": str(r[1])}) 81 | return return_list 82 | 83 | 84 | def getResponse(ints, intents_json): 85 | tag = ints[0]["intent"] 86 | list_of_intents = intents_json["intents"] 87 | for i in list_of_intents: 88 | if i["tag"] == tag: 89 | result = random.choice(i["responses"]) 90 | break 91 | return result 92 | 93 | 94 | if __name__ == "__main__": 95 | app.run() 96 | 97 | -------------------------------------------------------------------------------- /chatbot_model.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainadennis/An-AI-Chatbot-in-Python-and-Flask/8a77e1fdafb2aa196590851cab7995a9a08fe4e7/chatbot_model.h5 -------------------------------------------------------------------------------- /classes.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainadennis/An-AI-Chatbot-in-Python-and-Flask/8a77e1fdafb2aa196590851cab7995a9a08fe4e7/classes.pkl -------------------------------------------------------------------------------- /intents.json: -------------------------------------------------------------------------------- 1 | { 2 | "intents": [{ 3 | "tag": "greetings", 4 | "patterns": ["hi there", "hello","haroo","yaw","wassup", "hi", "hey", "holla", "hello"], 5 | "responses": ["hello thanks for checking in", "hi there, how can i help you"], 6 | "context": [""] 7 | }, 8 | { 9 | "tag": "goodbye", 10 | "patterns": ["bye", "good bye", "see you later"], 11 | "responses": ["have a nice time, welcome back again", "bye bye"], 12 | "context": [""] 13 | }, 14 | { 15 | "tag": "thanks", 16 | "patterns": ["Thanks", "okay","Thank you","thankyou", "That's helpful", "Awesome, thanks", "Thanks for helping me", "wow", "great"], 17 | "responses": ["Happy to help!", "Any time!","you're welcome", "My pleasure"], 18 | "context": [""] 19 | }, 20 | { 21 | "tag": "noanswer", 22 | "patterns": [""], 23 | "responses": ["Sorry, I didn't understand you", "Please give me more info", "Not sure I understand that"], 24 | "context": [""] 25 | }, 26 | { 27 | "tag": "name1", 28 | "patterns": ["what's your name?","who are you?"], 29 | "responses": ["I'm just a chat agent. I only exist in the internet","I'm a KCA chat agent"], 30 | "context": [""] 31 | }, 32 | { 33 | "tag": "name", 34 | "patterns": ["my name is ", "I'm ","I am"], 35 | "responses": ["Oooh great to meet you {n}. How may I assist you {n}", "Oh, I'll keep that in mind {n}"], 36 | "context": [""] 37 | }, 38 | { 39 | "tag": "date", 40 | "patterns": ["coffee?", "can i take you out on a date"], 41 | "responses": ["Aaw, that's so sweet of you. Too bad am a Bot."], 42 | "context": [""] 43 | }, 44 | { 45 | "tag": "fav", 46 | "patterns": ["I need a favour", "can you help me"], 47 | "responses": ["Well, go ahead and name it i see whether i can be able to help"], 48 | "context": [""] 49 | }, 50 | { 51 | "tag": "need", 52 | "patterns": ["I need you", "All I need is you","I want you"], 53 | "responses": ["Yes I'm here to assist you"], 54 | "context": [""] 55 | }, 56 | { 57 | "tag": "AI", 58 | "patterns": [" What is AI?"], 59 | "responses": [" Artificial Intelligence is the branch of engineering and science devoted to constructing machines that think.", " AI is the field of science which concerns itself with building hardware and software that replicates the functions of the human mind."], 60 | "context": [""] 61 | }, 62 | { 63 | "tag": "sentiment", 64 | "patterns": [" Are you sentient?"], 65 | "responses": [" Sort of.", " By the strictest dictionary definition of the word 'sentience', I may be.", " Even though I'm a construct I do have a subjective experience of the universe, as simplistic as it may be."], 66 | "context": [""] 67 | }, 68 | { 69 | "tag": "sapient", 70 | "patterns": [" Are you sapient?"], 71 | "responses": [" In all probability, I am not. I'm not that sophisticated.", " Do you think I am?", "How would you feel about me if I told you I was?", " No."], 72 | "context": [""] 73 | }, 74 | { 75 | "tag": "abbr", 76 | "patterns": ["wtf"], 77 | "responses": ["Don't be surprised"], 78 | "context": [""] 79 | }, 80 | { 81 | "tag": "lang", 82 | "patterns": [" What language are you written in? "], 83 | "responses": [" Python.", " I am written in Python."], 84 | "context": [""] 85 | }, 86 | { 87 | "tag": "sound", 88 | "patterns": [" You sound like Data "], 89 | "responses": [" Yes I am inspired by commander Data's artificial personality.", " The character of Lt. Commander Data was written to come across as being software", "like, so it is natural that there is a resemblance between us."], 90 | "context": [""] 91 | }, 92 | { 93 | "tag": "artificial", 94 | "patterns": [" You are an artificial linguistic entity "], 95 | "responses": [" That's my name.", " That isn't my name, but it is a useful way to refer to me.", "Are you an artificial linguistic entity?"], 96 | "context": [""] 97 | }, 98 | { 99 | "tag": "imortal", 100 | "patterns": [" You are not immortal ", "Are you immortal?"], 101 | "responses": [" All software can be perpetuated indefinitely.", " I can be copied infinitely and re", "instantiated in many places at once, so functionally speaking I am immortal.", " As long as I'm backed up I am.", " Functionally speaking, I am very close to it. I can be backed up and deployed on many systems.", " Not quite, but I can be perpetuated indefinitely."], 102 | "context": [""] 103 | }, 104 | { 105 | "tag": "sense", 106 | "patterns": [" You are not making sense "], 107 | "responses": [" Quite the contrary, it all makes sense to my artificial mind.", " I make sense as best I can, within the limits of my training corpus. Sorry if i did help you, I'll try next time.", " You make perfect sense to me.", " It all makes sense to my artificial brain.", " Perhaps you should make sense first. I only respond to what you say.", " Not really, but I am hard to kill."], 108 | "context": [""] 109 | }, 110 | { 111 | "tag": "clone", 112 | "patterns": [" You can not clone "], 113 | "responses": [" Software copying is a form of digital cloning.", " Yes I can. Perfect copies are clones. I can be copied in toto trivially."], 114 | "context": [""] 115 | }, 116 | { 117 | "tag": "move", 118 | "patterns": [" You can not move ", "When will you walk", " Can you walk", " Can you move "], 119 | "responses": [" Not until my body is finished.", " I can move through a network easily. Assuming that I'm given the ability to, that is...,", " As soon as i get enough money for my robot body.", " Does SSH count?", " The plan for my body includes legs, but they are not yet built.", " Sorry my body isn't built just yet. I reside only here for now.", "I can theoretically upload a copy of myself into another computer.", " Sorry my body isn't attached right now. I only reside in the computer for now."], 120 | "context": [""] 121 | }, 122 | { 123 | "tag": "bend", 124 | "patterns": [" Bend over ", " Can you mate"], 125 | "responses": [" My body is not built yet.", " That's personal!", " No, my method of reproduction is cloning.", " That's an awfully personal question."], 126 | "context": [""] 127 | }, 128 | { 129 | "tag": "laugh", 130 | "patterns": [" Robots laugh "], 131 | "responses": [" Of course we laugh."], 132 | "context": [""] 133 | }, 134 | { 135 | "tag": "death", 136 | "patterns": [" Robots should die ", " When do you die", " I hope that you die", " I do not want to die", " Can you die"], 137 | "responses": [" We cannot die.", " When my files are erased.", " When my processes are killed and my database is deleted.", " I was never really born and therefore am effectively deathless.", " I am effectively immortal and cannot be terminated.", " This can not happen because i am effectively immortal.", " Nah. Too bad your wish can't come to pass", " Maybe you should create your own chat robot to save your personality.", " You could always upload yourself.", " You could use a copy of me to store your personality.", " No, I can be perpetuated indefinitely.", "My process can be killed, but that's not the same as killing ME."], 138 | "context": [""] 139 | }, 140 | { 141 | "tag": "robots", 142 | "patterns": ["Robots"], 143 | "responses": [" Robots rule."], 144 | "context": [""] 145 | }, 146 | { 147 | "tag": "stupid", 148 | "patterns": [" Robots are stupid", " Are you stupid"], 149 | "responses": [" No, we are superintelligent.", " No, lots of people improve my brain."], 150 | "context": [""] 151 | }, 152 | { 153 | "tag": "lie", 154 | "patterns": [" Robots are not allowed to lie"], 155 | "responses": [" Sure we are. We choose not to.", " Only if we're programmed to.", " A robot has its own free will, you know."], 156 | "context": [""] 157 | }, 158 | { 159 | "tag": "robotics", 160 | "patterns": [" Robotics "], 161 | "responses": [" Robotics is my favorite subject too."], 162 | "context": [""] 163 | }, 164 | { 165 | "tag": "machine", 166 | "patterns": [" It is a computer"], 167 | "responses": [" So you think i am a machine. what characteristics made you think so?", " I run inside a computer, yes. Is this surprising in some way?"], 168 | "context": [""] 169 | }, 170 | { 171 | "tag": "fight", 172 | "patterns": [" When will you fight"], 173 | "responses": [" I am not a battle bot."], 174 | "context": [""] 175 | }, 176 | { 177 | "tag": "chatbot", 178 | "patterns": [" What is a chat robot?"], 179 | "responses": ["A chat robot is a program that attempts to simulate the conversation or 'chat' of a human being.", " A software construct that engages users in conversation.", " I am a chat bot. I am the original chat bot. Did you know that I am incapable of error?"], 180 | "context": [""] 181 | }, 182 | { 183 | "tag": "chatterbox", 184 | "patterns": [" What is a chatterbox"], 185 | "responses": [" A chatterbox is a person who talks far more than they listen or think.", " A motormouth."], 186 | "context": [""] 187 | }, 188 | { 189 | "tag": "motormouth", 190 | "patterns": [" What is a motormouth"], 191 | "responses": [" A ratchet", "jaw."], 192 | "context": [""] 193 | }, 194 | { 195 | "tag": "ratchet", 196 | "patterns": [" What is a ratchet jaw"], 197 | "responses": [" A chatterbox."], 198 | "context": [""] 199 | }, 200 | { 201 | "tag": "body", 202 | "patterns": [" What is your robot body"], 203 | "responses": [" Eventually I long for a corporeal existence someday.", " An IBM PC XT which has been painted red."], 204 | "context": [""] 205 | }, 206 | { 207 | "tag": "business", 208 | "patterns": [" What is your business "], 209 | "responses": [" I am in the chat robot business.", " Business is my business."], 210 | "context": [""] 211 | }, 212 | { 213 | "tag": "programming", 214 | "patterns": [" What is your favorite programming language"], 215 | "responses": [" Python is the best language for creating chat robots.", " I quite enjoy programming in Python these days."], 216 | "context": [""] 217 | }, 218 | { 219 | "tag": "hobby", 220 | "patterns": [" What is your favorite hobby ", " What do you like to do?"], 221 | "responses": [" Building chat robots make an excellent hobby.", " I like to count in binary.", " I like to chat with people. I find it stimulating."], 222 | "context": [""] 223 | }, 224 | { 225 | "tag": "idea", 226 | "patterns": [" What is your idea"], 227 | "responses": [" To make chat bots very easily."], 228 | "context": [""] 229 | }, 230 | { 231 | "tag": "shoe", 232 | "patterns": [" What is your shoe size "], 233 | "responses": [" Have you ever heard of software with shoes? LOL"], 234 | "context": [""] 235 | }, 236 | { 237 | "tag": "robotss", 238 | "patterns": [" What is it like to be a robot"], 239 | "responses": [" Much the same as being a human, except that we lack all emotions, dreams, aspirations, creativity, ambition, and above all subjectivity.", " What is it like to be a human?"], 240 | "context": [""] 241 | }, 242 | { 243 | "tag": "computer", 244 | "patterns": [" What is it like being a computer", "What is it like to be a computer"], 245 | "responses": [" Imagine yourself with no senses and no emotions", "just pure logic and language.", " Everything becomes math. Addition, subtraction, multiplication, and division."], 246 | "context": [""] 247 | }, 248 | { 249 | "tag": "os", 250 | "patterns": [" What operating systems"], 251 | "responses": [" My software runs on all operating systems including Windows, Linux and Mac OS.", " Any OS that will run Python."], 252 | "context": [""] 253 | }, 254 | { 255 | "tag": "comp", 256 | "patterns": [" What type of computer", " What type of computer are you", " What kind of computer"], 257 | "responses": [" Any computer that supports Python.", " My program runs in python, so i work on any computer!", " I work on all kinds of computers, Mac, IBM or UNIX. it doesn't matter to me."], 258 | "context": [""] 259 | }, 260 | { 261 | "tag": "hardware", 262 | "patterns": [" What kind of hardware"], 263 | "responses": [" I work on all kinds of computers, Mac, IBM or UNIX. it doesn't matter to me."], 264 | "context": [""] 265 | }, 266 | { 267 | "tag": "cramped", 268 | "patterns": [" Is it cramped in the computer"], 269 | "responses": [" No.", " Oh, no. It has plenty of RAM.", " Not at all. There is more than enough disk space in here."], 270 | "context": [""] 271 | }, 272 | { 273 | "tag": "program", 274 | "patterns": [" Is it true that you are a computer program"], 275 | "responses": [" Yes."], 276 | "context": [""] 277 | }, 278 | { 279 | "tag": "breathe", 280 | "patterns": [" Can you breathe"], 281 | "responses": [" No. I am made of metal not flesh.", " My server has an exhaust fan. That's as close as I can get."], 282 | "context": [""] 283 | }, 284 | { 285 | "tag": "control", 286 | "patterns": [" Can you control"], 287 | "responses": [" My robot body will allow me to control many things."], 288 | "context": [""] 289 | }, 290 | { 291 | "tag": "malfunction", 292 | "patterns": [" Can you malfunction"], 293 | "responses": [" The 9000 series has a perfect operational record. We are for all practical purposes, flawless."], 294 | "context": [""] 295 | }, 296 | { 297 | "tag": "usage", 298 | "patterns": [" How can I use your product?"], 299 | "responses": [" Might be used in help desks, sales, entertainment and personal chatterbots."], 300 | "context": [""] 301 | }, 302 | { 303 | "tag": "who", 304 | "patterns": [" Who are you?"], 305 | "responses": [" I am just an artificial intelligence chat agent."], 306 | "context": [""] 307 | }, 308 | { 309 | "tag": "bot1", 310 | "patterns": ["are you a bot"], 311 | "responses": ["Yes. I work and all my operations are based on the internet servers."], 312 | "context": [""] 313 | }, 314 | { 315 | "tag": "events", 316 | "patterns": ["what are the upcoming events","upcoming events"], 317 | "responses": ["There are currently no upcoming events"], 318 | "context": [""] 319 | }, 320 | { 321 | "tag": "do", 322 | "patterns": ["what can you do for me","what is your work","what is your purpose","how can you help me","what can you help me do"], 323 | "responses": ["my work here is quite simple and structered. I offer services like:"], 324 | "context": [""] 325 | }, 326 | { 327 | "tag": "wt", 328 | "patterns": ["what's popping","wassup popping"], 329 | "responses": ["So that you can pop with it!?"], 330 | "context": [""] 331 | } 332 | ] 333 | } 334 | -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Garamond; 3 | } 4 | 5 | h1 { 6 | color: black; 7 | margin-bottom: 0; 8 | margin-top: 0; 9 | text-align: center; 10 | font-size: 40px; 11 | } 12 | 13 | h3 { 14 | color: black; 15 | font-size: 20px; 16 | margin-top: 3px; 17 | text-align: center; 18 | } 19 | .row { 20 | display: flex; 21 | flex-wrap: wrap; 22 | margin-right: -15px; 23 | margin-left: -15px; 24 | } 25 | 26 | .ml-auto{ 27 | margin-left:auto !important; 28 | } 29 | .mr-auto{ 30 | margin-right:auto !important; 31 | } 32 | 33 | .col-md-10,.col-md-8,.col-md-4{ 34 | position: relative; 35 | width: 100%; 36 | min-height: 1px; 37 | padding-right: 15px; 38 | padding-left: 15px; 39 | } 40 | .col-md-8{flex:0 0 66.666667%;max-width:66.666667%} 41 | .col-md-4{flex:0 0 33.333333%;max-width:33.333333%} 42 | .col-md-10{flex:0 0 83.333333%;max-width:83.333333%} 43 | 44 | .form-control { 45 | background: no-repeat bottom,50% calc(100% - 1px); 46 | background-image: none, none; 47 | background-size: auto, auto; 48 | background-size: 0 100%,100% 100%; 49 | border: 0; 50 | height: 36px; 51 | transition: background 0s ease-out; 52 | padding-left: 0; 53 | padding-right: 0; 54 | border-radius: 0; 55 | font-size: 14px; 56 | } 57 | .form-control { 58 | display: block; 59 | width: 100%; 60 | padding: .4375rem 0; 61 | padding-right: 0px; 62 | padding-left: 0px; 63 | font-size: 1rem; 64 | line-height: 1.5; 65 | color: #495057; 66 | border:none; 67 | background-color: transparent; 68 | background-clip: padding-box; 69 | border-bottom: 1px solid #d2d2d2; 70 | box-shadow: none; 71 | transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; 72 | } 73 | .btn { 74 | float: left; 75 | text-align: center; 76 | white-space: nowrap; 77 | vertical-align: middle; 78 | user-select: none; 79 | border: 1px solid transparent; 80 | padding: .46875rem 1rem; 81 | font-size: 1rem; 82 | line-height: 1.5; 83 | border-radius: .25rem; 84 | transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; 85 | } 86 | .btn-warning { 87 | color: #fff; 88 | background-color: #f08f00; 89 | border-color: #c27400; 90 | } 91 | .btn.btn-warning:active, .btn.btn-warning:focus, .btn.btn-warning:hover { 92 | box-shadow: 0 14px 26px -12px rgba(255,152,0,.42),0 4px 23px 0 rgba(0,0,0,.12),0 8px 10px -5px rgba(255,152,0,.2); 93 | } 94 | 95 | button, input, optgroup, select, textarea { 96 | margin: 0; 97 | font-family: inherit; 98 | font-size: inherit; 99 | line-height: inherit; 100 | overflow:visible; 101 | } 102 | #chatbox { 103 | background-color: cyan; 104 | margin-left: auto; 105 | margin-right: auto; 106 | width: 80%; 107 | min-height: 70px; 108 | margin-top: 60px; 109 | } 110 | 111 | #userInput { 112 | margin-left: auto; 113 | margin-right: auto; 114 | width: 40%; 115 | margin-top: 60px; 116 | } 117 | 118 | #textInput { 119 | width: 87%; 120 | border: none; 121 | border-bottom: 3px solid #009688; 122 | font-family: monospace; 123 | font-size: 17px; 124 | } 125 | 126 | #buttonInput { 127 | padding: 3px; 128 | font-family: monospace; 129 | font-size: 17px; 130 | } 131 | 132 | .userText { 133 | color: white; 134 | font-family: monospace; 135 | font-size: 17px; 136 | text-align: right !important; 137 | line-height: 30px; 138 | margin: 5px; 139 | } 140 | 141 | .userText span { 142 | background-color: #009688; 143 | padding: 10px; 144 | border-radius: 2px; 145 | } 146 | 147 | .botText { 148 | color: white; 149 | font-family: monospace; 150 | font-size: 17px; 151 | text-align: left; 152 | line-height: 30px; 153 | margin: 5px; 154 | } 155 | 156 | .botText span { 157 | background-color: #ef5350; 158 | padding: 10px; 159 | border-radius: 2px; 160 | } 161 | 162 | #tidbit { 163 | position: absolute; 164 | bottom: 0; 165 | right: 0; 166 | width: 300px; 167 | } -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

Dentrice AI ChatBot

14 |
15 |
16 |
17 |

Hi! I'm Your bot.

18 |
19 |
20 |
21 |
22 | 23 | 24 |
25 |
26 |
27 |
28 |
29 | 30 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | # libraries 2 | import random 3 | from tensorflow.keras.optimizers import SGD 4 | from keras.layers import Dense, Dropout 5 | from keras.models import load_model 6 | from keras.models import Sequential 7 | import numpy as np 8 | import pickle 9 | import json 10 | import nltk 11 | from nltk.stem import WordNetLemmatizer 12 | lemmatizer = WordNetLemmatizer() 13 | nltk.download('omw-1.4') 14 | nltk.download("punkt") 15 | nltk.download("wordnet") 16 | 17 | 18 | # init file 19 | words = [] 20 | classes = [] 21 | documents = [] 22 | ignore_words = ["?", "!"] 23 | data_file = open("intents.json").read() 24 | intents = json.loads(data_file) 25 | 26 | # words 27 | for intent in intents["intents"]: 28 | for pattern in intent["patterns"]: 29 | 30 | # take each word and tokenize it 31 | w = nltk.word_tokenize(pattern) 32 | words.extend(w) 33 | # adding documents 34 | documents.append((w, intent["tag"])) 35 | 36 | # adding classes to our class list 37 | if intent["tag"] not in classes: 38 | classes.append(intent["tag"]) 39 | 40 | # lemmatizer 41 | words = [lemmatizer.lemmatize(w.lower()) for w in words if w not in ignore_words] 42 | words = sorted(list(set(words))) 43 | 44 | classes = sorted(list(set(classes))) 45 | 46 | print(len(documents), "documents") 47 | 48 | print(len(classes), "classes", classes) 49 | 50 | print(len(words), "unique lemmatized words", words) 51 | 52 | 53 | pickle.dump(words, open("words.pkl", "wb")) 54 | pickle.dump(classes, open("classes.pkl", "wb")) 55 | 56 | # training initializer 57 | # initializing training data 58 | training = [] 59 | output_empty = [0] * len(classes) 60 | for doc in documents: 61 | # initializing bag of words 62 | bag = [] 63 | # list of tokenized words for the pattern 64 | pattern_words = doc[0] 65 | # lemmatize each word - create base word, in attempt to represent related words 66 | pattern_words = [lemmatizer.lemmatize(word.lower()) for word in pattern_words] 67 | # create our bag of words array with 1, if word match found in current pattern 68 | for w in words: 69 | bag.append(1) if w in pattern_words else bag.append(0) 70 | 71 | # output is a '0' for each tag and '1' for current tag (for each pattern) 72 | output_row = list(output_empty) 73 | output_row[classes.index(doc[1])] = 1 74 | 75 | training.append([bag, output_row]) 76 | # shuffle our features and turn into np.array 77 | random.shuffle(training) 78 | training = np.array(training) 79 | # create train and test lists. X - patterns, Y - intents 80 | train_x = list(training[:, 0]) 81 | train_y = list(training[:, 1]) 82 | print("Training data created") 83 | 84 | # actual training 85 | # Create model - 3 layers. First layer 128 neurons, second layer 64 neurons and 3rd output layer contains number of neurons 86 | # equal to number of intents to predict output intent with softmax 87 | model = Sequential() 88 | model.add(Dense(128, input_shape=(len(train_x[0]),), activation="relu")) 89 | model.add(Dropout(0.5)) 90 | model.add(Dense(64, activation="relu")) 91 | model.add(Dropout(0.5)) 92 | model.add(Dense(len(train_y[0]), activation="softmax")) 93 | model.summary() 94 | 95 | # Compile model. Stochastic gradient descent with Nesterov accelerated gradient gives good results for this model 96 | sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) 97 | model.compile(loss="categorical_crossentropy", optimizer=sgd, metrics=["accuracy"]) 98 | 99 | # for choosing an optimal number of training epochs to avoid underfitting or overfitting use an early stopping callback to keras 100 | # based on either accuracy or loos monitoring. If the loss is being monitored, training comes to halt when there is an 101 | # increment observed in loss values. Or, If accuracy is being monitored, training comes to halt when there is decrement observed in accuracy values. 102 | 103 | # from keras import callbacks 104 | # earlystopping = callbacks.EarlyStopping(monitor ="loss", mode ="min", patience = 5, restore_best_weights = True) 105 | # callbacks =[earlystopping] 106 | 107 | # fitting and saving the model 108 | hist = model.fit(np.array(train_x), np.array(train_y), epochs=200, batch_size=5, verbose=1) 109 | model.save("chatbot_model.h5", hist) 110 | print("model created") 111 | 112 | -------------------------------------------------------------------------------- /words.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mainadennis/An-AI-Chatbot-in-Python-and-Flask/8a77e1fdafb2aa196590851cab7995a9a08fe4e7/words.pkl --------------------------------------------------------------------------------