forked from tridibsamanta/Chatbot-using-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Add core chatbot module and CLI interface #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
HeiligerHoly
wants to merge
1
commit into
master
Choose a base branch
from
codex/erstelle-den-chatbot
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 ! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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, | ||
| 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 "" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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() |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 runningpython chatgui.pyorpython chatbot_cli.pyon that environment will raise a SyntaxError before the app starts. Consider reverting totyping.Union/Optional(or bumping the documented Python version) so the chatbot remains runnable on the advertised stack.Useful? React with 👍 / 👎.