From 10aa52b1de0531b5be14004347691d25096e1fde Mon Sep 17 00:00:00 2001 From: 000Andre000 <89241490+000Andre000@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:28:39 +0530 Subject: [PATCH] completed chatbot with gui it works but is very slow gui not responding error also appears after every question but u have to wait it will work --- gui.py | 69 ----------------- long_responses.py | 13 ---- main.py | 189 ++++++++++++++++++++++++--------------------- new.py | 85 ++++++++++++++++++++ website_scraper.py | 35 --------- 5 files changed, 185 insertions(+), 206 deletions(-) delete mode 100644 gui.py delete mode 100644 long_responses.py create mode 100644 new.py delete mode 100644 website_scraper.py diff --git a/gui.py b/gui.py deleted file mode 100644 index 593d8b0..0000000 --- a/gui.py +++ /dev/null @@ -1,69 +0,0 @@ -import tkinter as tk -from tkinter import messagebox -from bs4 import BeautifulSoup -import requests - - -def scrape_website(url): - try: - response = requests.get(url) - soup = BeautifulSoup(response.content, 'html.parser') - title = soup.title.text - description = soup.find('meta', attrs={'name': 'description'})['content'] - # Additional content - # Extracting all links on the page - links = [link.get('href') for link in soup.find_all('a')] - # Extracting all paragraphs - paragraphs = [p.text for p in soup.find_all('p')] - # Extracting all image URLs - images = [img.get('src') for img in soup.find_all('img')] - return {'title': title, 'description': description, 'links': links, 'paragraphs': paragraphs, 'images': images} - except Exception as e: - print(e) - return None - - -def get_website_details(): - url = entry.get() - website_info = scrape_website(url) - if website_info: - messagebox.showinfo("Website Details", - f"Title: {website_info['title']}\nDescription: {website_info['description']}") - else: - messagebox.showerror("Error", "Failed to fetch website details. Please check the URL.") - - -def send_message(event=None): - message = user_input.get() - chat_log.config(state=tk.NORMAL) - chat_log.insert(tk.END, "You: " + message + "\n") - chat_log.config(state=tk.DISABLED) - user_input.delete(0, tk.END) - - -root = tk.Tk() -root.title("Website Scraper & Chatbot") - -# Website Details Section -url_label = tk.Label(root, text="Enter Website URL:") -url_label.pack() - -entry = tk.Entry(root, width=50) -entry.pack() - -details_button = tk.Button(root, text="Get Details", command=get_website_details) -details_button.pack() - -# Chat Section -chat_log = tk.Text(root, width=50, height=20) -chat_log.config(state=tk.DISABLED) -chat_log.pack() - -user_input = tk.Entry(root, width=50) -user_input.pack() -user_input.bind("", send_message) - -send_button = tk.Button(root, text="Send", command=send_message) -send_button.pack() - -root.mainloop() diff --git a/long_responses.py b/long_responses.py deleted file mode 100644 index 515bc1f..0000000 --- a/long_responses.py +++ /dev/null @@ -1,13 +0,0 @@ -import random - -R_EATING = "I don't like eating anything because I'm a bot obviously!" -R_ADVICE = "If I were you, I would go to the internet and type exactly what you wrote there!" - - -def unknown(): - response = ["Could you please re-phrase that? ", - "...", - "Sounds about right.", - "What does that mean?"][ - random.randrange(4)] - return response \ No newline at end of file diff --git a/main.py b/main.py index 0f0d75e..8d15b1f 100644 --- a/main.py +++ b/main.py @@ -1,90 +1,101 @@ -import re -import long_responses as long import tkinter as tk - -def message_probability(user_message, recognised_words, single_response=False, required_words=[]): - message_certainty = 0 - has_required_words = True - - # Counts how many words are present in each predefined message - for word in user_message: - if word in recognised_words: - message_certainty += 1 - - # Calculates the percent of recognised words in a user message - percentage = float(message_certainty) / float(len(recognised_words)) - - # Checks that the required words are in the string - for word in required_words: - if word not in user_message: - has_required_words = False - break - - # Must either have the required words, or be a single response - if has_required_words or single_response: - return int(percentage * 100) - else: - return 0 - -def check_all_messages(message): - highest_prob_list = {} - - # Simplifies response creation / adds it to the dict - def response(bot_response, list_of_words, single_response=False, required_words=[]): - nonlocal highest_prob_list - highest_prob_list[bot_response] = message_probability(message, list_of_words, single_response, required_words) - - # Responses ------------------------------------------------------------------------------------------------------- - response('Hello!', ['hello', 'hi', 'hey', 'sup', 'heyo'], single_response=True) - response('See you!', ['bye', 'goodbye'], single_response=True) - response('I\'m doing fine, and you?', ['how', 'are', 'you', 'doing'], required_words=['how']) - response('You\'re welcome!', ['thank', 'thanks'], single_response=True) - response('Thank you!', ['i', 'love', 'code', 'palace'], required_words=['code', 'palace']) - - # Longer responses - response(long.R_ADVICE, ['give', 'advice'], required_words=['advice']) - response(long.R_EATING, ['what', 'you', 'eat'], required_words=['you', 'eat']) - - best_match = max(highest_prob_list, key=highest_prob_list.get) - - return long.unknown() if highest_prob_list[best_match] < 1 else best_match - -# Used to get the response -def get_response(user_input): - split_message = re.split(r'\s+|[,;?!.-]\s*', user_input.lower()) - response = check_all_messages(split_message) - return response - -def send_message(event=None): - user_input = entry.get() - if user_input.strip().lower() == 'quit': - root.quit() - else: - response = get_response(user_input) - chat_box.config(state=tk.NORMAL) - chat_box.insert(tk.END, f"You: {user_input}\n") - chat_box.insert(tk.END, f"Bot: {response}\n\n") - chat_box.config(state=tk.DISABLED) - entry.delete(0, tk.END) - -# Create main window -root = tk.Tk() -root.title("Chatbot") - -# Chat history display -chat_box = tk.Text(root, height=20, width=50) -chat_box.config(state=tk.DISABLED) -chat_box.grid(row=0, column=0, columnspan=2, padx=10, pady=10) - -# User input field -entry = tk.Entry(root, width=40) -entry.grid(row=1, column=0, padx=10, pady=10) - -# Send button -send_button = tk.Button(root, text="Send", command=send_message) -send_button.grid(row=1, column=1, padx=10, pady=10) - -# Bind key to send_message function -root.bind('', send_message) - -root.mainloop() +from tkinter import messagebox +from new import myAiBot +from bs4 import BeautifulSoup +import requests + +class ChatGUI: + url = None + def __init__(self, ai_bot): + self.ai_bot = ai_bot + self.chat_history = [] + + # Create the main Tkinter window + self.root = tk.Tk() + self.root.title("Chatbot") + + # Enter Website URL Section + url_label = tk.Label(self.root, text="Enter Website URL:") + url_label.pack() + + entry = tk.Entry(self.root, width=50) + entry.pack() + + def details(url): + """Load documents from a website using BeautifulSoup.""" + try: + response = requests.get(url) + soup = BeautifulSoup(response.content, 'html.parser') + # Extract text content from paragraphs + paragraphs = [p.text.strip() for p in soup.find_all('p')] + # Extract text content from headings + headings = [h.text.strip() for h in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])] + # Combine paragraphs and headings to form documents + documents = paragraphs + headings + return documents + except Exception as e: + print(f"Error loading documents from {url}: {e}") + return [] + + def get_website_details(): + global url + url = entry.get() + website_info = details(url) + print(website_info) + if website_info: + messagebox.showinfo("Website Details", + f"Details : {website_info}") + else: + messagebox.showerror("Error", "Failed to fetch website details. Please check the URL.") + + details_button = tk.Button(self.root, text="Get Details", command=get_website_details) + details_button.pack() + + # Chat history display + self.chat_box = tk.Text(self.root, height=20, width=50) + self.chat_box.config(state=tk.DISABLED) + self.chat_box.pack(padx=10, pady=10) + + # User input field + self.entry = tk.Entry(self.root, width=40) + self.entry.pack(padx=10, pady=10) + + # Send button + self.send_button = tk.Button(self.root, text="Send", command=self.send_message) + self.send_button.pack(padx=10, pady=10) + + # Bind key to send_message function + self.root.bind('', self.send_message) + + def send_message(self, event=None): + # Get user input + user_input = self.entry.get() + + # Display user input in the chat history + self.chat_box.config(state=tk.NORMAL) + self.chat_box.insert(tk.END, "You: " + user_input + "\n") + self.chat_box.config(state=tk.DISABLED) + + # Clear the input field + self.entry.delete(0, tk.END) + + # Get AI response + ai_response = self.ai_bot.start_conversation(user_input ,url) + + # Display AI response in the chat history + self.chat_box.config(state=tk.NORMAL) + self.chat_box.insert(tk.END, "Bot: " + ai_response + "\n") + self.chat_box.config(state=tk.DISABLED) + + def run(self): + # Start the Tkinter event loop + self.root.mainloop() + +# Create an instance of the ConversationSystem class +ai = myAiBot("AIzaSyC9u1gjP_ZyGDuyYkv5gnkkOyaDX50aR7U") + +# Create the chat GUI +chat_gui = ChatGUI(ai) + +# Run the chat GUI +chat_gui.run() diff --git a/new.py b/new.py new file mode 100644 index 0000000..abe1d50 --- /dev/null +++ b/new.py @@ -0,0 +1,85 @@ +import locale +from langchain_google_genai import ChatGoogleGenerativeAI +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.output_parsers import StrOutputParser +from langchain_community.document_loaders import WebBaseLoader +from langchain.embeddings import HuggingFaceEmbeddings +from langchain_community.vectorstores import FAISS +from langchain.text_splitter import RecursiveCharacterTextSplitter +from langchain.chains.combine_documents import create_stuff_documents_chain +from langchain.chains import create_retrieval_chain, ConversationalRetrievalChain + +class myAiBot: + def __init__(self, google_api_key): + # Set preferred encoding to UTF-8 + locale.getpreferredencoding = lambda: "UTF-8" + # Google API key for Gemini + self.google_api_key = google_api_key + # Instantiate Google Gemini model + self.llm = ChatGoogleGenerativeAI(model="gemini-pro", google_api_key=self.google_api_key, + convert_system_message_to_human=True, temperature=0.5, + top_p=0.9, top_k=40) + # Define a chat prompt template + self.prompt = ChatPromptTemplate.from_template("""Answer the following question based only on the provided context: + {context} + Question: {input}""") + + + # Define output parser + self.output_parser = StrOutputParser() + self.result = None + + def load_documents_from_website(self, url): + """Load documents from a website.""" + loader = WebBaseLoader(url) + return loader.load() + + def initialize_embeddings(self): + """Initialize HuggingFace embeddings.""" + return HuggingFaceEmbeddings() + + def split_documents_and_create_vector_store(self, docs, embeddings): + """Split documents and create vector store using FAISS.""" + text_splitter = RecursiveCharacterTextSplitter() + documents = text_splitter.split_documents(docs) + return FAISS.from_documents(documents, embeddings) + + def create_document_chain_for_retrieval(self): + """Create a document chain for retrieval.""" + return create_stuff_documents_chain(self.llm, self.prompt) + + def create_retrieval_chain_with_vector_retriever(self, vector): + """Create a retrieval chain with vector retriever.""" + retriever = vector.as_retriever() + document_chain = self.create_document_chain_for_retrieval() + return create_retrieval_chain(retriever, document_chain) + + def create_conversational_retrieval_chain(self, vector): + """Create a conversational retrieval chain.""" + retriever = vector.as_retriever() + retrieval_chain = self.create_retrieval_chain_with_vector_retriever(vector) + return ConversationalRetrievalChain.from_llm(self.llm, retriever, return_source_documents=True) + + def start_conversation(self,query,url): + """Start conversation loop.""" + + docs = self.load_documents_from_website(url) + embeddings = self.initialize_embeddings() + vector = self.split_documents_and_create_vector_store(docs, embeddings) + qa_chain = self.create_conversational_retrieval_chain(vector) + + global result + + chat_history = [] + query + result = qa_chain({'question': query, 'chat_history': chat_history}) + answer = result['answer'] + print('Answer: ' + result['answer'] + '\n') + chat_history.append((query, result['answer'])) + + return answer +# Usage: +if __name__ == "__main__": + GOOGLE_API_KEY = 'AIzaSyC9u1gjP_ZyGDuyYkv5gnkkOyaDX50aR7U' + ai_bot = myAiBot(GOOGLE_API_KEY) + ai_bot.start_conversation() diff --git a/website_scraper.py b/website_scraper.py deleted file mode 100644 index 4c8aa1d..0000000 --- a/website_scraper.py +++ /dev/null @@ -1,35 +0,0 @@ -from bs4 import BeautifulSoup -import requests - - -def scrape_website(url): - # Make a GET request to the URL - response = requests.get(url) - - # Parse the HTML content - soup = BeautifulSoup(response.content, 'html.parser') - - # Extract relevant information from the website - # You can customize this according to your requirements - - # Title and description - title = soup.title.text - description = soup.find('meta', attrs={'name': 'description'})['content'] - - # Additional content - # Extracting all links on the page - links = [link.get('href') for link in soup.find_all('a')] - - # Extracting all paragraphs - paragraphs = [p.text for p in soup.find_all('p')] - - # Extracting all image URLs - images = [img.get('src') for img in soup.find_all('img')] - - return { - 'title': title, - 'description': description, - 'links': links, - 'paragraphs': paragraphs, - 'images': images - }