Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
# Chatbot-using-Python
Build a chatbot using deep learning techniques. The chatbot will be trained on the dataset which contains categories (intents), pattern and responses. We use a special recurrent neural network (LSTM) to classify which category the user’s message belongs to and then we will give a random response from the list of responses.
Build a chatbot using deep learning techniques. The chatbot will be trained on the dataset which contains categories (intents),
pattern and responses. We use a special recurrent neural network (LSTM) to classify which category the user’s message belongs to
and then we will give a random response from the list of responses.

:white_check_mark: ## Getting Started
:white_check_mark: ## Getting Started

- [x] Download all the files

- [x] Open Command Prompt

- [x] Get the control to the folder where your files are present

- [x] Make sure your system has the following modules installed -
tensorflow, keras, nltk, pickle. If not, then install the modules using the command - {pip install module_name}. If your system already has the module, it will show "Requirement already satisfied".
- [x] Make sure your system has the following modules installed -
tensorflow, keras, nltk, pickle. If not, then install the modules using the command - {pip install module_name}. If your system
already has the module, it will show "Requirement already satisfied".

- [x] Now we have to train and create the model. Hence execute the "train_chatbot.py" file using the following command - {python train_chatbot.py}. If the training is successful it will show model created.
- [x] Now we have to train and create the model. Hence execute the "train_chatbot.py" file using the following command - {python
train_chatbot.py}. If the training is successful it will show model created.

- [x] To open the GUI window and start conversation with the chatbot execute the "chatgui.py" file using the following command - {python chatgui.py}. It will open the GUI window.
- [x] To open the GUI window and start conversation with the chatbot execute the "chatgui.py" file using the following command -
{python chatgui.py}. It will open the GUI window.

- [x] Write your text in the section on the right to the send button and click on "Send". Enjoy the responses !
- [x] Write your text in the section on the right to the send button and click on "Send". Enjoy the responses !

### Command line chat

If you prefer using the chatbot directly from your terminal, run:

```
python chatbot_cli.py
```

type your question and press Enter. Type `exit` or `quit` to leave the conversation.


!!! ERROR GUIDE !!!

While executing the file "train_chatbot.py" if you get some error like - "ImportError: cannot import name 'tf_utils'", uninstall keras using the command - {pip uninstall keras}, then reinstall keras using the command - {pip install keras==2.2.0}. Try executing the file, i hope it works properly !
While executing the file "train_chatbot.py" if you get some error like - "ImportError: cannot import name 'tf_utils'", uninstall
keras using the command - {pip uninstall keras}, then reinstall keras using the command - {pip install keras==2.2.0}. Try execu
ting the file, i hope it works properly !
28 changes: 28 additions & 0 deletions chatbot_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Command line interface for chatting with the trained model."""

from chatbot_core import Chatbot


def main() -> None:
bot = Chatbot()
print("Chatbot gestartet. Tippe 'exit' oder 'quit' zum Beenden.")

while True:
try:
message = input("You: ").strip()
except (EOFError, KeyboardInterrupt):
print("\nAuf Wiedersehen!")
break

if not message:
continue
if message.lower() in {"exit", "quit"}:
print("Auf Wiedersehen!")
break

response = bot.chatbot_response(message)
print(f"Bot: {response}")


if __name__ == "__main__":
main()
85 changes: 85 additions & 0 deletions chatbot_core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"""Core chatbot utilities shared between the GUI and CLI interfaces."""

from dataclasses import dataclass
import json
import pickle
import random
from pathlib import Path
from typing import List, Sequence

import nltk
from nltk.stem import WordNetLemmatizer
import numpy as np
from keras.models import load_model


@dataclass
class IntentPrediction:
"""Represents a single intent prediction with its probability."""

intent: str
probability: float


class Chatbot:
"""Encapsulates the model and helper utilities for generating responses."""

def __init__(
self,
model_path: str | Path = "chatbot_model.h5",
intents_path: str | Path = "intents.json",
words_path: str | Path = "words.pkl",
classes_path: str | Path = "classes.pkl",
error_threshold: float = 0.25,
Comment on lines +29 to +33

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid Python 3.10-only type syntax in Chatbot init

The new Chatbot constructor uses the PEP604 union operator (str | Path, str | None) introduced in Python 3.10. The README still points users to keras 2.2.0 (the error guide) which only supports Python ≤3.6, so following the documented setup and running python chatgui.py or python chatbot_cli.py on that environment will raise a SyntaxError before the app starts. Consider reverting to typing.Union/Optional (or bumping the documented Python version) so the chatbot remains runnable on the advertised stack.

Useful? React with 👍 / 👎.

default_response: str | None = "I did not understand. Could you rephrase?",
) -> None:
self.model = load_model(model_path)
self.intents = json.loads(Path(intents_path).read_text())
self.words: List[str] = pickle.loads(Path(words_path).read_bytes())
self.classes: List[str] = pickle.loads(Path(classes_path).read_bytes())
self.error_threshold = error_threshold
self.default_response = default_response
self.lemmatizer = WordNetLemmatizer()

def clean_up_sentence(self, sentence: str) -> List[str]:
"""Tokenize and lemmatize the input sentence."""

sentence_words = nltk.word_tokenize(sentence)
return [self.lemmatizer.lemmatize(word.lower()) for word in sentence_words]

def bow(self, sentence: str) -> np.ndarray:
"""Create a bag-of-words vector for the provided sentence."""

sentence_words = self.clean_up_sentence(sentence)
bag = [1 if word in sentence_words else 0 for word in self.words]
return np.array(bag)

def predict_class(self, sentence: str) -> List[IntentPrediction]:
"""Predict the intent of the provided sentence."""

bag = self.bow(sentence)
probabilities: Sequence[float] = self.model.predict(np.array([bag]), verbose=0)[0]
results = [
IntentPrediction(intent=self.classes[index], probability=probability)
for index, probability in enumerate(probabilities)
if probability > self.error_threshold
]
return sorted(results, key=lambda prediction: prediction.probability, reverse=True)

def _response_for_intent(self, intent_tag: str) -> str | None:
for intent in self.intents.get("intents", []):
if intent.get("tag") == intent_tag:
responses = intent.get("responses", [])
return random.choice(responses) if responses else None
return None

def chatbot_response(self, message: str) -> str:
"""Generate a chatbot response for the given user message."""

predictions = self.predict_class(message)
if not predictions:
return self.default_response or ""

top_intent = predictions[0].intent
response = self._response_for_intent(top_intent)
return response if response is not None else self.default_response or ""
186 changes: 66 additions & 120 deletions chatgui.py
Original file line number Diff line number Diff line change
@@ -1,120 +1,66 @@
#https://github.com/tridibsamanta/Chatbot-using-Python

import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import pickle
import numpy as np

from keras.models import load_model
model = load_model('chatbot_model.h5')
import json
import random
intents = json.loads(open('intents.json').read())
words = pickle.load(open('words.pkl','rb'))
classes = pickle.load(open('classes.pkl','rb'))


def clean_up_sentence(sentence):
# tokenize the pattern - split words into array
sentence_words = nltk.word_tokenize(sentence)
# stem each word - create short form for word
sentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words]
return sentence_words

# return bag of words array: 0 or 1 for each word in the bag that exists in the sentence

def bow(sentence, words, show_details=True):
# tokenize the pattern
sentence_words = clean_up_sentence(sentence)
# bag of words - matrix of N words, vocabulary matrix
bag = [0]*len(words)
for s in sentence_words:
for i,w in enumerate(words):
if w == s:
# assign 1 if current word is in the vocabulary position
bag[i] = 1
if show_details:
print ("found in bag: %s" % w)
return(np.array(bag))

def predict_class(sentence, model):
# filter out predictions below a threshold
p = bow(sentence, words,show_details=False)
res = model.predict(np.array([p]))[0]
ERROR_THRESHOLD = 0.25
results = [[i,r] for i,r in enumerate(res) if r>ERROR_THRESHOLD]
# sort by strength of probability
results.sort(key=lambda x: x[1], reverse=True)
return_list = []
for r in results:
return_list.append({"intent": classes[r[0]], "probability": str(r[1])})
return return_list

def getResponse(ints, intents_json):
tag = ints[0]['intent']
list_of_intents = intents_json['intents']
for i in list_of_intents:
if(i['tag']== tag):
result = random.choice(i['responses'])
break
return result

def chatbot_response(msg):
ints = predict_class(msg, model)
res = getResponse(ints, intents)
return res


#Creating GUI with tkinter
import tkinter
from tkinter import *


def send():
msg = EntryBox.get("1.0",'end-1c').strip()
EntryBox.delete("0.0",END)

if msg != '':
ChatLog.config(state=NORMAL)
ChatLog.insert(END, "You: " + msg + '\n\n')
ChatLog.config(foreground="#442265", font=("Verdana", 12 ))

res = chatbot_response(msg)
ChatLog.insert(END, "Bot: " + res + '\n\n')

ChatLog.config(state=DISABLED)
ChatLog.yview(END)


base = Tk()
base.title("Hello")
base.geometry("400x500")
base.resizable(width=FALSE, height=FALSE)

#Create Chat window
ChatLog = Text(base, bd=0, bg="white", height="8", width="50", font="Arial",)

ChatLog.config(state=DISABLED)

#Bind scrollbar to Chat window
scrollbar = Scrollbar(base, command=ChatLog.yview, cursor="heart")
ChatLog['yscrollcommand'] = scrollbar.set

#Create Button to send message
SendButton = Button(base, font=("Verdana",12,'bold'), text="Send", width="12", height=5,
bd=0, bg="#32de97", activebackground="#3c9d9b",fg='#ffffff',
command= send )

#Create the box to enter message
EntryBox = Text(base, bd=0, bg="white",width="29", height="5", font="Arial")
#EntryBox.bind("<Return>", send)


#Place all components on the screen
scrollbar.place(x=376,y=6, height=386)
ChatLog.place(x=6,y=6, height=386, width=370)
EntryBox.place(x=128, y=401, height=90, width=265)
SendButton.place(x=6, y=401, height=90)

base.mainloop()
# https://github.com/tridibsamanta/Chatbot-using-Python

import tkinter
from tkinter import *

from chatbot_core import Chatbot

bot = Chatbot()


def send():
msg = EntryBox.get("1.0", "end-1c").strip()
EntryBox.delete("0.0", END)

if msg:
ChatLog.config(state=NORMAL)
ChatLog.insert(END, "You: " + msg + "\n\n")
ChatLog.config(foreground="#442265", font=("Verdana", 12))

res = bot.chatbot_response(msg)
ChatLog.insert(END, "Bot: " + res + "\n\n")

ChatLog.config(state=DISABLED)
ChatLog.yview(END)


base = Tk()
base.title("Hello")
base.geometry("400x500")
base.resizable(width=FALSE, height=FALSE)

# Create Chat window
ChatLog = Text(base, bd=0, bg="white", height="8", width="50", font="Arial")

ChatLog.config(state=DISABLED)

# Bind scrollbar to Chat window
scrollbar = Scrollbar(base, command=ChatLog.yview, cursor="heart")
ChatLog["yscrollcommand"] = scrollbar.set

# Create Button to send message
SendButton = Button(
base,
font=("Verdana", 12, "bold"),
text="Send",
width="12",
height=5,
bd=0,
bg="#32de97",
activebackground="#3c9d9b",
fg="#ffffff",
command=send,
)

# Create the box to enter message
EntryBox = Text(base, bd=0, bg="white", width="29", height="5", font="Arial")
# EntryBox.bind("<Return>", send)


# Place all components on the screen
scrollbar.place(x=376, y=6, height=386)
ChatLog.place(x=6, y=6, height=386, width=370)
EntryBox.place(x=128, y=401, height=90, width=265)
SendButton.place(x=6, y=401, height=90)

base.mainloop()