Spaces:
Sleeping
Sleeping
| import os | |
| from prompt import rag_system_prompt,rag_history_prompt,chat_prompt | |
| from langchain_community.chat_message_histories import ChatMessageHistory | |
| import uuid | |
| from langchain_huggingface import HuggingFaceEndpoint,ChatHuggingFace | |
| import time | |
| import json | |
| from langchain_core.chat_history import ( | |
| BaseChatMessageHistory, | |
| InMemoryChatMessageHistory, | |
| ) | |
| from langchain_openai import ChatOpenAI | |
| from langchain.chains.combine_documents import create_stuff_documents_chain | |
| from langchain_core.runnables.history import RunnableWithMessageHistory | |
| from langchain.chains import create_history_aware_retriever,create_retrieval_chain | |
| from langchain_community.document_loaders import PyPDFLoader | |
| from langchain_core.runnables.history import RunnableWithMessageHistory | |
| from functools import wraps | |
| from langchain_experimental.text_splitter import SemanticChunker | |
| from dotenv import load_dotenv | |
| from utils import create_retriever | |
| from langchain_core.messages import HumanMessage | |
| # from utils import indexing,retrieval,time_it | |
| import os | |
| from langchain_core.globals import set_debug,get_debug | |
| #Setting up Enviroment Variables | |
| api_key = os.getenv('OPENAI_API_KEY') | |
| set_debug(False) | |
| load_dotenv() | |
| HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') | |
| """ | |
| Todos: | |
| -- Use multithreading to speed up the process | |
| -- Add more comments | |
| -- add the ability to work with more resources | |
| -- how to handle chat history(if it just grows and grows) | |
| -- slinding context window? | |
| -- Streaming integration with langchain (this one is too slow and we shouldn't be doing this) | |
| -- Improve prompt to only use context if needed | |
| """ | |
| class Chat: | |
| """ | |
| A class representing a chatbot. | |
| Attributes: | |
| - file_path (str): The path to the file containing the source data. | |
| - model (str): The name or ID of the Hugging Face model to use for chat generation. | |
| - embedding (str): The type of embedding to use for the chat model. | |
| - chunking_method (str): The method used for semantic chunking. | |
| Methods: | |
| - __init__(self, file_path=None, model="mistralai/Mistral-7B-Instruct-v0.2", embedding="", chunking_method="semantic_chunking"): Initializes a Chat instance. | |
| - add_source(self, file_path): Adds a source file for the chatbot to use. | |
| - get_session_history(self, session_id): Retrieves the chat message history for a given session ID. | |
| - run(self, query, username="Usman"): Runs the chatbot with the given query and username. | |
| """ | |
| def __init__(self,file_path=None,model="mistralai/Mistral-7B-Instruct-v0.2",embedding="",chunking_method="semantic_chunking"): | |
| self.file_path = file_path | |
| self.llm = HuggingFaceEndpoint(repo_id=model,temperature=0.5,huggingfacehub_api_token=HUGGINGFACEHUB_API_TOKEN,max_new_tokens=4096) | |
| self.session_id = str(uuid.uuid4()) | |
| self.store = {} | |
| self.file_uploaded = False | |
| self.current_file = None | |
| self.db = None | |
| self.retriever = None | |
| self.chunking_method = chunking_method | |
| self.chat_model = ChatOpenAI( | |
| model="mistralai/Mistral-7B-Instruct-v0.2", | |
| base_url="https://api-inference.huggingface.co/v1", | |
| api_key=os.environ.get('HUGGINGFACEHUB_API_TOKEN'),max_tokens=1000) | |
| self.retriever_chain = None | |
| self.chat_chain = None | |
| # add the source file and create the relevent chains | |
| def add_source(self,file_path): | |
| print(f"Adding the following source: {file_path}") | |
| self.file_uploaded = True | |
| self.current_file = file_path | |
| self.qa_chain = create_stuff_documents_chain(self.chat_model,rag_system_prompt) | |
| data = create_retriever(file_path,self.chunking_method) | |
| self.retriever = data['retriever'] | |
| self.db = data['vectordb'] | |
| self.history_retriever = create_history_aware_retriever(self.llm,self.retriever,rag_history_prompt) | |
| self.source_chain = create_retrieval_chain(self.history_retriever,self.qa_chain) | |
| # Used to retrieve the chat session history | |
| def get_session_history(self,session_id): | |
| if session_id not in self.store: | |
| self.store[session_id] = InMemoryChatMessageHistory() | |
| return self.store[session_id] | |
| # Used to invoke the chain and generate response | |
| def run(self,query,username="Usman"): | |
| if self.file_uploaded == True: | |
| # Goes in this block if the user has uploaded the file/source | |
| print("RETURNED FROM FILE 1") | |
| response = self.source_chain.invoke({"input":query,'username':username}) | |
| analysis = [] | |
| for data in response['context']: | |
| data = {'metadata':[data.metadata],'page_content':[data.page_content]} | |
| analysis.append(data) | |
| with open("documents.json", "w") as file: | |
| json.dump(analysis, file, indent=4) | |
| print(f"response returned is {response['context']}") | |
| return response['answer'] | |
| else: | |
| #Change this so it only creates the chain if it hasnt created before | |
| if self.chat_chain: | |
| response = self.simple_chain.invoke({"input":query,'username':username},{'configurable':{"session_id":self.session_id}}) | |
| print(response) | |
| return response.content | |
| else: | |
| self.chat_chain = chat_prompt | self.chat_model | |
| self.simple_chain = RunnableWithMessageHistory( | |
| self.chat_chain, | |
| self.get_session_history, | |
| history_messages_key="messages" | |
| ) | |
| response = self.simple_chain.invoke({"input":query,'username':username},{'configurable':{"session_id":self.session_id}}) | |
| print(response) | |
| return response.content | |
| if __name__ == "__main__": | |
| bot = Chat() | |
| user_inp = input("User:") | |
| while user_inp != "n": | |
| start_time = time.time() | |
| asd = bot.run(user_inp) | |
| end_time = time.time() | |
| response_time = end_time - start_time | |
| print(asd) | |
| print(f"(Response generated in {response_time:.2f} seconds)") | |
| user_inp = input("User:") | |