| |
| import os |
| import json |
| from datetime import datetime |
| |
| import numpy as np |
| from sentence_transformers import SentenceTransformer |
| from pypdf import PdfReader |
| import requests |
| from bs4 import BeautifulSoup |
|
|
| |
| from langchain_community.document_loaders import PyPDFLoader |
| from langchain_community.document_loaders import WebBaseLoader |
| from langchain_community.vectorstores import FAISS |
| from langchain_huggingface import HuggingFaceEmbeddings |
|
|
|
|
| class vectorstore: |
| |
| def __init__(self, path, Initlize_with=3): |
| if Initlize_with == 1: |
| self.index_path = self.create_vectorstore_from_pdf(path, embedder_model="all-MiniLM-L6-v2") |
| self.vectorstore = self.load_vectorstore(self.index_path) |
| elif Initlize_with == 2: |
| self.index_path = self.create_vectorstore_from_website(path, embedder_model="all-MiniLM-L6-v2") |
| self.vectorstore = self.load_vectorstore(self.index_path) |
| elif Initlize_with == 3: |
| self.index_path = path |
| self.vectorstore = self.load_vectorstore(self.index_path) |
| |
| def chunk_text(self,text, chunk_size=1200): |
| """ |
| Split text into chunks of approximately 'chunk_size' words. |
| |
| Parameters: |
| text (str): The input text. |
| chunk_size (int): Maximum number of words per chunk. |
| |
| Returns: |
| List[str]: A list of text chunks. |
| """ |
| words = text.split() |
| chunks = [] |
| for i in range(0, len(words), chunk_size): |
| chunk = " ".join(words[i:i+chunk_size]) |
| chunks.append(chunk) |
| return chunks |
|
|
| def create_vectorstore_from_pdf(self,pdf_path, chunk_size=1200, embedder_model="all-MiniLM-L6-v2"): |
| """ |
| Extract text from a PDF using pypdf, chunk the text, compute embeddings, |
| and create a FAISS index. |
| |
| Parameters: |
| pdf_path (str): Path to the PDF file. |
| chunk_size (int): Number of words per chunk. |
| embedder_model (str): The sentence-transformer model to use. |
| |
| Returns: |
| index: A FAISS index containing the embeddings. |
| chunks: A list of text chunks. |
| embedder: The SentenceTransformer embedder. |
| """ |
| |
| loader = PyPDFLoader(pdf_path) |
| documents = loader.load() |
| text = " ".join([doc.page_content for doc in documents]) |
| |
| |
| chunks = self.chunk_text(text, chunk_size) |
| |
| |
| embedder = HuggingFaceEmbeddings(model_name=embedder_model) |
| vectorstore = FAISS.from_texts(chunks, embedder) |
| |
| |
| index_path = self.save_vectorstore_with_timestamp_and_without(vectorstore, embedder_model) |
| return index_path |
|
|
| def create_vectorstore_from_website(self, url, chunk_size=1200, embedder_model="all-MiniLM-L6-v2"): |
| """ |
| Fetch text from a website, chunk the text, compute embeddings, |
| and create a FAISS index. |
| |
| Parameters: |
| url (str): The URL of the website. |
| chunk_size (int): Number of words per chunk. |
| embedder_model (str): The sentence-transformer model to use. |
| |
| Returns: |
| index: A FAISS index containing the embeddings. |
| chunks: A list of text chunks. |
| embedder: The SentenceTransformer embedder. |
| """ |
| |
| loader = WebBaseLoader(url) |
| documents = loader.load() |
| text = " ".join([doc.page_content for doc in documents]) |
| |
| |
| chunks = self.chunk_text(text, chunk_size) |
| |
| |
| embedder = HuggingFaceEmbeddings(model_name=embedder_model) |
| vectorstore = FAISS.from_texts(chunks, embedder) |
| |
| |
| index_path = self.save_vectorstore_with_timestamp_and_without(vectorstore, embedder_model) |
| return index_path |
|
|
| def add_to_vectorstore_web(self, url, index_file_path, chunk_size=1200): |
| """ |
| Fetch text from a website, chunk the text, compute embeddings using the existing embedder, |
| and add them to the existing FAISS vectorstore. |
| |
| Parameters: |
| url (str): The URL of the website. |
| index_file_path (str): The file path of the saved vectorstore index. |
| chunk_size (int): Maximum number of words per chunk. |
| |
| Returns: |
| str: The updated vectorstore index file path. |
| """ |
| |
| vectorstore = self.load_vectorstore(index_file_path) |
| |
| |
| loader = WebBaseLoader(url) |
| documents = loader.load() |
| text = " ".join([doc.page_content for doc in documents]) |
| |
| |
| new_chunks = self.chunk_text(text, chunk_size) |
| |
| |
| vectorstore.add_texts(new_chunks) |
| |
| |
| updated_index_path = self.save_vectorstore_with_timestamp_and_without(vectorstore, vectorstore.embedding_function.model_name) |
| return updated_index_path |
|
|
|
|
| def add_to_vectorstore_from_pdf(self, pdf_path, chunk_size=1200): |
| """ |
| Extract text from a PDF using PyPDF2, chunk the text, compute embeddings using the existing embedder, |
| and add them to the existing FAISS vectorstore. |
| |
| Parameters: |
| pdf_path (str): Path to the PDF file. |
| index_file_path (str): The file path of the saved vectorstore index. |
| chunk_size (int): Maximum number of words per chunk. |
| |
| Returns: |
| str: The updated vectorstore index file path. |
| """ |
| |
| loader = PyPDFLoader(pdf_path) |
| documents = loader.load() |
| text = " ".join([doc.page_content for doc in documents]) |
| |
| |
| new_chunks = self.chunk_text(text, chunk_size) |
| |
| |
| self.vectorstore.add_texts(new_chunks) |
| |
| |
| self.index_path = self.save_vectorstore_with_timestamp_and_without(self.vectorstore, self.vectorstore.embedding_function.model_name) |
| return self.index_path |
|
|
| def save_vectorstore_with_timestamp_and_without(self, vectorstore, embedder_model=None): |
| vector_db_folder = os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")), "VectorDB") |
| os.makedirs(vector_db_folder, exist_ok=True) |
| |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| folder_name = f"vectorstore_{timestamp}" |
| folder_path = os.path.join(vector_db_folder, folder_name) |
| |
| |
| vectorstore.save_local(folder_path) |
| |
| |
| metadata = {"embedder_model": embedder_model or "all-MiniLM-L6-v2"} |
| with open(os.path.join(folder_path, "metadata.json"), "w") as f: |
| json.dump(metadata, f) |
| |
| |
| main_folder = os.path.join(vector_db_folder, "vectorstore_mainV2") |
| vectorstore.save_local(main_folder) |
| with open(os.path.join(main_folder, "metadata.json"), "w") as f: |
| json.dump(metadata, f) |
| |
| return main_folder |
|
|
| def load_vectorstore(self, index_path): |
| |
| metadata_path = os.path.join(index_path, "metadata.json") |
| with open(metadata_path, "r") as f: |
| metadata = json.load(f) |
| embedder_model = metadata["embedder_model"] |
| |
| |
| embedder = HuggingFaceEmbeddings(model_name=embedder_model) |
| vectorstore = FAISS.load_local(index_path, embedder,allow_dangerous_deserialization=True) |
| return vectorstore |
| |
| |
| def search_vectorstore(self, query, top_k=5): |
| |
| docs = self.vectorstore.similarity_search(query, k=top_k) |
| results = [doc.page_content for doc in docs] |
| return results |
|
|
| def log_conversation(self, user_text, bot_text=""): |
| |
| logs_folder = os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")), "logs") |
| os.makedirs(logs_folder, exist_ok=True) |
| log_file = os.path.join(logs_folder, "conversation_logs.json") |
| entry = { |
| "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), |
| "User": {"text": user_text}, |
| "bot": {"text": bot_text} |
| } |
| if os.path.exists(log_file): |
| with open(log_file, "r", encoding="utf-8") as f: |
| try: |
| logs = json.load(f) |
| except json.JSONDecodeError: |
| logs = [] |
| else: |
| logs = [] |
| logs.append(entry) |
| with open(log_file, "w", encoding="utf-8") as f: |
| json.dump(logs, f, indent=4) |
| |
| |
| self.memory.add_message({"role": "user", "content": user_text}) |
| if bot_text: |
| self.memory.add_message({"role": "assistant", "content": bot_text}) |
|
|
| |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |