[
  {
    "path": "README.md",
    "content": "# Simple-Python-Chatbot\n\nCreating a simple Python chatbot using natural language processing and deep learning.\n\n"
  },
  {
    "path": "chatgui.py",
    "content": "\r\nimport nltk\r\nfrom nltk.stem import WordNetLemmatizer\r\nlemmatizer = WordNetLemmatizer()\r\nimport pickle\r\nimport numpy as np\r\n\r\nfrom keras.models import load_model\r\nmodel = load_model('chatbot_model.h5')\r\nimport json\r\nimport random\r\nintents = json.loads(open('intents.json').read())\r\nwords = pickle.load(open('words.pkl','rb'))\r\nclasses = pickle.load(open('classes.pkl','rb'))\r\n\r\n\r\ndef clean_up_sentence(sentence):\r\n    sentence_words = nltk.word_tokenize(sentence)\r\n    sentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words]\r\n    return sentence_words\r\n\r\n# return bag of words array: 0 or 1 for each word in the bag that exists in the sentence\r\n\r\ndef bow(sentence, words, show_details=True):\r\n    # tokenize the pattern\r\n    sentence_words = clean_up_sentence(sentence)\r\n    # bag of words - matrix of N words, vocabulary matrix\r\n    bag = [0]*len(words)\r\n    for s in sentence_words:\r\n        for i,w in enumerate(words):\r\n            if w == s:\r\n                # assign 1 if current word is in the vocabulary position\r\n                bag[i] = 1\r\n                if show_details:\r\n                    print (\"found in bag: %s\" % w)\r\n    return(np.array(bag))\r\n\r\ndef predict_class(sentence, model):\r\n    # filter out predictions below a threshold\r\n    p = bow(sentence, words,show_details=False)\r\n    res = model.predict(np.array([p]))[0]\r\n    ERROR_THRESHOLD = 0.25\r\n    results = [[i,r] for i,r in enumerate(res) if r>ERROR_THRESHOLD]\r\n    # sort by strength of probability\r\n    results.sort(key=lambda x: x[1], reverse=True)\r\n    return_list = []\r\n    for r in results:\r\n        return_list.append({\"intent\": classes[r[0]], \"probability\": str(r[1])})\r\n    return return_list\r\n\r\ndef getResponse(ints, intents_json):\r\n    tag = ints[0]['intent']\r\n    list_of_intents = intents_json['intents']\r\n    for i in list_of_intents:\r\n        if(i['tag']== tag):\r\n            result = random.choice(i['responses'])\r\n            break\r\n    return result\r\n\r\ndef chatbot_response(msg):\r\n    ints = predict_class(msg, model)\r\n    res = getResponse(ints, intents)\r\n    return res\r\n\r\n\r\n#Creating GUI with tkinter\r\nimport tkinter\r\nfrom tkinter import *\r\n\r\n\r\ndef send():\r\n    msg = EntryBox.get(\"1.0\",'end-1c').strip()\r\n    EntryBox.delete(\"0.0\",END)\r\n\r\n    if msg != '':\r\n        ChatLog.config(state=NORMAL)\r\n        ChatLog.insert(END, \"You: \" + msg + '\\n\\n')\r\n        ChatLog.config(foreground=\"#442265\", font=(\"Verdana\", 12 ))\r\n\r\n        res = chatbot_response(msg)\r\n        ChatLog.insert(END, \"Bot: \" + res + '\\n\\n')\r\n\r\n        ChatLog.config(state=DISABLED)\r\n        ChatLog.yview(END)\r\n\r\n\r\nbase = Tk()\r\nbase.title(\"Hello\")\r\nbase.geometry(\"400x500\")\r\nbase.resizable(width=FALSE, height=FALSE)\r\n\r\n#Create Chat window\r\nChatLog = Text(base, bd=0, bg=\"white\", height=\"8\", width=\"50\", font=\"Arial\",)\r\n\r\nChatLog.config(state=DISABLED)\r\n\r\n#Bind scrollbar to Chat window\r\nscrollbar = Scrollbar(base, command=ChatLog.yview, cursor=\"heart\")\r\nChatLog['yscrollcommand'] = scrollbar.set\r\n\r\n#Create Button to send message\r\nSendButton = Button(base, font=(\"Verdana\",12,'bold'), text=\"Send\", width=\"12\", height=5,\r\n                    bd=0, bg=\"#32de97\", activebackground=\"#3c9d9b\",fg='#ffffff',\r\n                    command= send )\r\n\r\n#Create the box to enter message\r\nEntryBox = Text(base, bd=0, bg=\"white\",width=\"29\", height=\"5\", font=\"Arial\")\r\n#EntryBox.bind(\"<Return>\", send)\r\n\r\n\r\n#Place all components on the screen\r\nscrollbar.place(x=376,y=6, height=386)\r\nChatLog.place(x=6,y=6, height=386, width=370)\r\nEntryBox.place(x=128, y=401, height=90, width=265)\r\nSendButton.place(x=6, y=401, height=90)\r\n\r\nbase.mainloop()\r\n"
  },
  {
    "path": "classes.pkl",
    "content": "(lp0\nVadverse_drug\np1\naVblood_pressure\np2\naVblood_pressure_search\np3\naVgoodbye\np4\naVgreeting\np5\naVhospital_search\np6\naVoptions\np7\naVpharmacy_search\np8\naVthanks\np9\na."
  },
  {
    "path": "intents.json",
    "content": "{\"intents\": [\n        {\"tag\": \"greeting\",\n         \"patterns\": [\"Hi there\", \"How are you\", \"Is anyone there?\",\"Hey\",\"Hola\", \"Hello\", \"Good day\"],\n         \"responses\": [\"Hello, thanks for asking\", \"Good to see you again\", \"Hi there, how can I help?\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"goodbye\",\n         \"patterns\": [\"Bye\", \"See you later\", \"Goodbye\", \"Nice chatting to you, bye\", \"Till next time\"],\n         \"responses\": [\"See you!\", \"Have a nice day\", \"Bye! Come back again soon.\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"thanks\",\n         \"patterns\": [\"Thanks\", \"Thank you\", \"That's helpful\", \"Awesome, thanks\", \"Thanks for helping me\"],\n         \"responses\": [\"Happy to help!\", \"Any time!\", \"My pleasure\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"noanswer\",\n         \"patterns\": [],\n         \"responses\": [\"Sorry, can't understand you\", \"Please give me more info\", \"Not sure I understand\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"options\",\n         \"patterns\": [\"How you could help me?\", \"What you can do?\", \"What help you provide?\", \"How you can be helpful?\", \"What support is offered\"],\n         \"responses\": [\"I can guide you through Adverse drug reaction list, Blood pressure tracking, Hospitals and Pharmacies\", \"Offering support for Adverse drug reaction, Blood pressure, Hospitals and Pharmacies\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"adverse_drug\",\n         \"patterns\": [\"How to check Adverse drug reaction?\", \"Open adverse drugs module\", \"Give me a list of drugs causing adverse behavior\", \"List all drugs suitable for patient with adverse reaction\", \"Which drugs dont have adverse reaction?\" ],\n         \"responses\": [\"Navigating to Adverse drug reaction module\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"blood_pressure\",\n         \"patterns\": [\"Open blood pressure module\", \"Task related to blood pressure\", \"Blood pressure data entry\", \"I want to log blood pressure results\", \"Blood pressure data management\" ],\n         \"responses\": [\"Navigating to Blood Pressure module\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"blood_pressure_search\",\n         \"patterns\": [\"I want to search for blood pressure result history\", \"Blood pressure for patient\", \"Load patient blood pressure result\", \"Show blood pressure results for patient\", \"Find blood pressure results by ID\" ],\n         \"responses\": [\"Please provide Patient ID\", \"Patient ID?\"],\n         \"context\": [\"search_blood_pressure_by_patient_id\"]\n        },\n        {\"tag\": \"search_blood_pressure_by_patient_id\",\n         \"patterns\": [],\n         \"responses\": [\"Loading Blood pressure result for Patient\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"pharmacy_search\",\n         \"patterns\": [\"Find me a pharmacy\", \"Find pharmacy\", \"List of pharmacies nearby\", \"Locate pharmacy\", \"Search pharmacy\" ],\n         \"responses\": [\"Please provide pharmacy name\"],\n         \"context\": [\"search_pharmacy_by_name\"]\n        },\n        {\"tag\": \"search_pharmacy_by_name\",\n         \"patterns\": [],\n         \"responses\": [\"Loading pharmacy details\"],\n         \"context\": [\"\"]\n        },\n        {\"tag\": \"hospital_search\",\n         \"patterns\": [\"Lookup for hospital\", \"Searching for hospital to transfer patient\", \"I want to search hospital data\", \"Hospital lookup for patient\", \"Looking up hospital details\" ],\n         \"responses\": [\"Please provide hospital name or location\"],\n         \"context\": [\"search_hospital_by_params\"]\n        },\n        {\"tag\": \"search_hospital_by_params\",\n         \"patterns\": [],\n         \"responses\": [\"Please provide hospital type\"],\n         \"context\": [\"search_hospital_by_type\"]\n        },\n        {\"tag\": \"search_hospital_by_type\",\n         \"patterns\": [],\n         \"responses\": [\"Loading hospital details\"],\n         \"context\": [\"\"]\n        }\n   ]\n}\n"
  },
  {
    "path": "train_chatbot.py",
    "content": "import nltk\r\nnltk.download('punkt')\r\nnltk.download('wordnet')\r\nfrom nltk.stem import WordNetLemmatizer\r\nlemmatizer = WordNetLemmatizer()\r\nimport json\r\nimport pickle\r\n\r\nimport numpy as np\r\nfrom keras.models import Sequential\r\nfrom keras.layers import Dense, Activation, Dropout\r\nfrom keras.optimizers import SGD\r\nimport random\r\n\r\nwords=[]\r\nclasses = []\r\ndocuments = []\r\nignore_words = ['?', '!']\r\ndata_file = open('intents.json').read()\r\nintents = json.loads(data_file)\r\n\r\n\r\nfor intent in intents['intents']:\r\n    for pattern in intent['patterns']:\r\n\r\n        # take each word and tokenize it\r\n        w = nltk.word_tokenize(pattern)\r\n        words.extend(w)\r\n        # adding documents\r\n        documents.append((w, intent['tag']))\r\n\r\n        # adding classes to our class list\r\n        if intent['tag'] not in classes:\r\n            classes.append(intent['tag'])\r\n\r\nwords = [lemmatizer.lemmatize(w.lower()) for w in words if w not in ignore_words]\r\nwords = sorted(list(set(words)))\r\n\r\nclasses = sorted(list(set(classes)))\r\n\r\nprint (len(documents), \"documents\")\r\n\r\nprint (len(classes), \"classes\", classes)\r\n\r\nprint (len(words), \"unique lemmatized words\", words)\r\n\r\n\r\npickle.dump(words,open('words.pkl','wb'))\r\npickle.dump(classes,open('classes.pkl','wb'))\r\n\r\n# initializing training data\r\ntraining = []\r\noutput_empty = [0] * len(classes)\r\nfor doc in documents:\r\n    # initializing bag of words\r\n    bag = []\r\n    # list of tokenized words for the pattern\r\n    pattern_words = doc[0]\r\n    # lemmatize each word - create base word, in attempt to represent related words\r\n    pattern_words = [lemmatizer.lemmatize(word.lower()) for word in pattern_words]\r\n    # create our bag of words array with 1, if word match found in current pattern\r\n    for w in words:\r\n        bag.append(1) if w in pattern_words else bag.append(0)\r\n\r\n    # output is a '0' for each tag and '1' for current tag (for each pattern)\r\n    output_row = list(output_empty)\r\n    output_row[classes.index(doc[1])] = 1\r\n\r\n    training.append([bag, output_row])\r\n# shuffle our features and turn into np.array\r\nrandom.shuffle(training)\r\ntraining = np.array(training)\r\n# create train and test lists. X - patterns, Y - intents\r\ntrain_x = list(training[:,0])\r\ntrain_y = list(training[:,1])\r\nprint(\"Training data created\")\r\n\r\n\r\n# Create model - 3 layers. First layer 128 neurons, second layer 64 neurons and 3rd output layer contains number of neurons\r\n# equal to number of intents to predict output intent with softmax\r\nmodel = Sequential()\r\nmodel.add(Dense(128, input_shape=(len(train_x[0]),), activation='relu'))\r\nmodel.add(Dropout(0.5))\r\nmodel.add(Dense(64, activation='relu'))\r\nmodel.add(Dropout(0.5))\r\nmodel.add(Dense(len(train_y[0]), activation='softmax'))\r\n\r\n# Compile model. Stochastic gradient descent with Nesterov accelerated gradient gives good results for this model\r\nsgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)\r\nmodel.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])\r\n\r\n#fitting and saving the model\r\nhist = model.fit(np.array(train_x), np.array(train_y), epochs=200, batch_size=5, verbose=1)\r\nmodel.save('chatbot_model.h5', hist)\r\n\r\nprint(\"model created\")\r\n"
  },
  {
    "path": "words.pkl",
    "content": "(lp0\nV's\np1\naV,\np2\naVa\np3\naVadverse\np4\naVall\np5\naVanyone\np6\naVare\np7\naVawesome\np8\naVbe\np9\naVbehavior\np10\naVblood\np11\naVby\np12\naVbye\np13\naVcan\np14\naVcausing\np15\naVchatting\np16\naVcheck\np17\naVcould\np18\naVdata\np19\naVday\np20\naVdetail\np21\naVdo\np22\naVdont\np23\naVdrug\np24\naVentry\np25\naVfind\np26\naVfor\np27\naVgive\np28\naVgood\np29\naVgoodbye\np30\naVhave\np31\naVhello\np32\naVhelp\np33\naVhelpful\np34\naVhelping\np35\naVhey\np36\naVhi\np37\naVhistory\np38\naVhola\np39\naVhospital\np40\naVhow\np41\naVi\np42\naVid\np43\naVis\np44\naVlater\np45\naVlist\np46\naVload\np47\naVlocate\np48\naVlog\np49\naVlooking\np50\naVlookup\np51\naVmanagement\np52\naVme\np53\naVmodule\np54\naVnearby\np55\naVnext\np56\naVnice\np57\naVof\np58\naVoffered\np59\naVopen\np60\naVpatient\np61\naVpharmacy\np62\naVpressure\np63\naVprovide\np64\naVreaction\np65\naVrelated\np66\naVresult\np67\naVsearch\np68\naVsearching\np69\naVsee\np70\naVshow\np71\naVsuitable\np72\naVsupport\np73\naVtask\np74\naVthank\np75\naVthanks\np76\naVthat\np77\naVthere\np78\naVtill\np79\naVtime\np80\naVto\np81\naVtransfer\np82\naVup\np83\naVwant\np84\naVwhat\np85\naVwhich\np86\naVwith\np87\naVyou\np88\na."
  }
]