Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add files via upload
  • Loading branch information
ojogbedek committed Apr 18, 2024
0 parents commit 9ee8025
Show file tree
Hide file tree
Showing 10 changed files with 1,246 additions and 0 deletions.
57 changes: 57 additions & 0 deletions MLecomChatbot/README.md
@@ -0,0 +1,57 @@

# E-Commerce Chatbot README

This repository contains code for a simple chatbot implemented in Python using TensorFlow and NLTK.

## Overview

The chatbot is trained to understand and respond to user queries based on predefined intents. It uses a bag-of-words approach to encode input sentences and a neural network for classification.

## Requirements

- Python 3.9.7
- TensorFlow
- NLTK (Natural Language Toolkit)


2. Install dependencies:

```bash
pip install -r requirements.txt
```

## Usage

1. Train the model:

```bash
python ecomChatbot.py
```

2. Run with the chatbot:

```bash
streamlit run chatbotApp.py
```

## Files

- `intents.json`: Contains predefined intents and responses.
- `ecomChatbot.py`: Script to train the chatbot model.
- `chatbotApp.py`: Script to interact with the trained chatbot. with streamlit GUI.
- `chatbot_model.h5`: Trained model file.
- `words.pkl` and `classes.pkl`: Pickled files containing words and classes used for training.

## How it Works

1. **Data Preprocessing**: Intents are loaded from `intents.json`, tokenized, lemmatized, and converted into a bag-of-words format.
2. **Model Training**: A neural network model is defined and trained on the processed data.
3. **Prediction**: Input sentences are tokenized and converted into bag-of-words vectors, and the model predicts the intent.
4. **Response Generation**: Based on the predicted intent, a response is randomly chosen from the predefined responses in `intents.json`.

## Customization

- Modify `intents.json` to add or edit intents and responses.
- Tweak model architecture and parameters in `train_chatbot.py` for better performance.
- Extend functionalities by adding more functions in `chatbot.py`.

Binary file added MLecomChatbot/aiChatbot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
100 changes: 100 additions & 0 deletions MLecomChatbot/chatbotApp.py
@@ -0,0 +1,100 @@
import streamlit as st
import nltk
from nltk.stem import WordNetLemmatizer
import json
import pickle
import numpy as np
from keras.models import load_model

# Load necessary resources
lemmatizer = WordNetLemmatizer()
nltk.download('punkt')
nltk.download('wordnet')
model = load_model('chatbot_model.h5')
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

words = pickle.load(open('words.pkl', 'rb'))
classes = pickle.load(open('classes.pkl', 'rb'))
intents = json.loads(open('intents.json').read())

# Initialize chat history
if "chat_history" not in st.session_state:
st.session_state.chat_history = []

# Chatbot functions
def clean_up_sentence(sentence):
sentence_words = nltk.word_tokenize(sentence)
sentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words]
return sentence_words

def bow(sentence, words, show_details=True):
sentence_words = clean_up_sentence(sentence)
bag = [0] * len(words)
for s in sentence_words:
for i, w in enumerate(words):
if w == s:
bag[i] = 1
if show_details:
print ("found in bag: %s" % w)
return(np.array(bag))

def predict_class(sentence, model):
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]
results.sort(key=lambda x: x[1], reverse=True)
return [{"intent": classes[r[0]], "probability": str(r[1])} for r in results]

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 = np.random.choice(i['responses'])
break
return result

# Streamlit GUI

st.title("E-Commerce Store Assistant")

def main():
# Container for chat history
chat_container = st.container()

# Form to handle user input
with st.form("user_input_form"):
# Text input for user
user_input = st.text_input("Prompt:")
# Submit button
submit_button = st.form_submit_button("Send")

# Handle form submission
if submit_button and user_input.strip() != "":
st.session_state.chat_history.append({"user": user_input})
response = chatbot_response(user_input)
st.session_state.chat_history.append({"bot": response})

# Display entire chat history
with chat_container:
for item in st.session_state.chat_history:
if "user" in item:
st.image("user.png", width=32)
st.markdown(f"{item['user']}")
elif "bot" in item:
st.image("aiChatbot.png", width=32)
st.markdown(f"{item['bot']}")

def chatbot_response(text):
ints = predict_class(text, model)
if ints:
res = getResponse(ints, intents)
return res
else:
return "I'm sorry, I didn't understand that."


if __name__ == "__main__":
main()

Binary file added MLecomChatbot/chatbot_model.h5
Binary file not shown.
Binary file added MLecomChatbot/classes.pkl
Binary file not shown.
89 changes: 89 additions & 0 deletions MLecomChatbot/ecomChatbot.py
@@ -0,0 +1,89 @@
import random # Importing the random module

import nltk
from nltk.stem import WordNetLemmatizer
import json
import pickle
import numpy as np
from tensorflow.keras.models import Sequential, load_model
from tensorflow.keras.layers import Dense, Dropout

lemmatizer = WordNetLemmatizer()
nltk.download('punkt')
nltk.download('wordnet')

# Load intents from JSON (correcting the path)
intents = json.loads(open('intents.json').read())

# Initialize lists
words = []
classes = []
documents = []
ignore_words = ['?', '!']

# Process intents
for intent in intents['intents']:
for pattern in intent['patterns']:
# Tokenize each word
w = nltk.word_tokenize(pattern)
words.extend(w)
# Add documents in the corpus
documents.append((w, intent['tag']))
# Add to classes list
if intent['tag'] not in classes:
classes.append(intent['tag'])

# Lemmatize, lowercase, and remove duplicates
words = [lemmatizer.lemmatize(w.lower()) for w in words if w not in ignore_words]
words = sorted(list(set(words)))
classes = sorted(list(set(classes)))

# Save words and classes to pickle files
pickle.dump(words, open('words.pkl', 'wb'))
pickle.dump(classes, open('classes.pkl', 'wb'))

random.shuffle(documents)

# Initialize lists for training
train_x = []
train_y = []

# Generate training data
for doc in documents:
bag = [0] * len(words)
pattern_words = doc[0]
intent = doc[1]
for word in pattern_words:
if word in words:
bag[words.index(word)] = 1
train_x.append(bag)
label = [0] * len(classes)
label[classes.index(intent)] = 1
train_y.append(label)

# Convert lists to numpy arrays
train_x = np.array(train_x)
train_y = np.array(train_y)

# Define and compile the model
model = Sequential()
model.add(Dense(128, input_shape=(len(train_x[0]),), activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(len(train_y[0]), activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# Fit the model to the data
history = model.fit(train_x, train_y, epochs=200, batch_size=8, verbose=1)

# Save the model
model.save('chatbot_model.h5')

print("Model training completed. Model saved as 'chatbot_model.h5'.")

# Load the model and necessary files
model = load_model('chatbot_model.h5')
words = pickle.load(open('words.pkl', 'rb'))
classes = pickle.load(open('classes.pkl', 'rb'))

0 comments on commit 9ee8025

Please sign in to comment.