captain-awesome commited on
Commit
f7172b2
1 Parent(s): 5cc9f1b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +294 -0
app.py ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.chains import ConversationalRetrievalChain
2
+ from langchain.chains.question_answering import load_qa_chain
3
+ from langchain.memory import ConversationBufferMemory
4
+ from langchain.llms import HuggingFacePipeline
5
+ from langchain import PromptTemplate
6
+ from langchain.embeddings import HuggingFaceEmbeddings
7
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain.vectorstores import Chroma
9
+ from langchain.document_loaders import (
10
+ CSVLoader,
11
+ DirectoryLoader,
12
+ GitLoader,
13
+ NotebookLoader,
14
+ OnlinePDFLoader,
15
+ PythonLoader,
16
+ TextLoader,
17
+ UnstructuredFileLoader,
18
+ UnstructuredHTMLLoader,
19
+ UnstructuredPDFLoader,
20
+ UnstructuredWordDocumentLoader,
21
+ WebBaseLoader,
22
+ )
23
+ from transformers import (
24
+ AutoModelForCausalLM,
25
+ AutoTokenizer,
26
+ StoppingCriteria,
27
+ StoppingCriteriaList,
28
+ pipeline,
29
+ GenerationConfig,
30
+ TextStreamer,
31
+ pipeline
32
+ )
33
+ from langchain.llms import HuggingFaceHub
34
+ import torch
35
+ from transformers import BitsAndBytesConfig
36
+ import os
37
+ from langchain.llms import CTransformers
38
+ import streamlit as st
39
+
40
+ def load_model():
41
+ # model_path=HuggingFaceHub(repo_id="vilsonrodrigues/falcon-7b-instruct-sharded")
42
+
43
+ # if not os.path.exists(model_path):
44
+ # raise FileNotFoundError(f"No model file found at {model_path}")
45
+
46
+ # quantization_config = BitsAndBytesConfig(
47
+ # load_in_4bit=True,
48
+ # bnb_4bit_compute_dtype=torch.float16,
49
+ # bnb_4bit_quant_type="nf4",
50
+ # bnb_4bit_use_double_quant=True,
51
+ # )
52
+
53
+ # model_4bit = AutoModelForCausalLM.from_pretrained(
54
+ # model_path,
55
+ # device_map="auto",
56
+ # quantization_config=quantization_config,
57
+ # )
58
+
59
+ # tokenizer = AutoTokenizer.from_pretrained(model_path)
60
+
61
+ # pipeline = pipeline(
62
+ # "text-generation",
63
+ # model=model_4bit,
64
+ # tokenizer=tokenizer,
65
+ # use_cache=True,
66
+ # device_map="auto",
67
+ # max_length=700,
68
+ # do_sample=True,
69
+ # top_k=5,
70
+ # num_return_sequences=1,
71
+ # eos_token_id=tokenizer.eos_token_id,
72
+ # pad_token_id=tokenizer.eos_token_id,
73
+ # )
74
+
75
+ # llm = HuggingFacePipeline(pipeline=pipeline)
76
+ # llm = CTransformers(
77
+ # model=HuggingFaceHub(repo_id="TheBloke/Llama-2-7B-Chat-GGML", model_kwargs={"temperature":0.5, "max_length":512})
78
+ # # model_type=model_type,
79
+ # # max_new_tokens=max_new_tokens, # type: ignore
80
+ # # temperature=temperature, # type: ignore
81
+ # )
82
+ llm = CTransformers(
83
+ model="TheBloke/Llama-2-7B-Chat-GGML"
84
+ # model_type=model_type,
85
+ # max_new_tokens=max_new_tokens, # type: ignore
86
+ # temperature=temperature, # type: ignore
87
+ )
88
+ return llm
89
+
90
+
91
+ def create_vector_database():
92
+ # DB_DIR: str = os.path.join(ABS_PATH, "db")
93
+ """
94
+ Creates a vector database using document loaders and embeddings.
95
+
96
+ This function loads data from PDF, markdown and text files in the 'data/' directory,
97
+ splits the loaded documents into chunks, transforms them into embeddings using HuggingFace,
98
+ and finally persists the embeddings into a Chroma vector database.
99
+
100
+ """
101
+ # Initialize loaders for different file types
102
+ pdf_loader = DirectoryLoader("data/", glob="**/*.pdf", loader_cls=PyPDFLoader)
103
+ markdown_loader = DirectoryLoader("data/", glob="**/*.md", loader_cls=UnstructuredMarkdownLoader)
104
+ text_loader = DirectoryLoader("data/", glob="**/*.txt", loader_cls=TextLoader)
105
+ csv_loader = DirectoryLoader("data/", glob="**/*.csv", loader_cls=CSVLoader)
106
+ python_loader = DirectoryLoader("data/", glob="**/*.py", loader_cls=PythonLoader)
107
+ epub_loader = DirectoryLoader("data/", glob="**/*.epub", loader_cls=UnstructuredEPubLoader)
108
+ html_loader = DirectoryLoader("data/", glob="**/*.html", loader_cls=UnstructuredHTMLLoader)
109
+ ppt_loader = DirectoryLoader("data/", glob="**/*.ppt", loader_cls=UnstructuredPowerPointLoader)
110
+ pptx_loader = DirectoryLoader("data/", glob="**/*.pptx", loader_cls=UnstructuredPowerPointLoader)
111
+ doc_loader = DirectoryLoader("data/", glob="**/*.doc", loader_cls=UnstructuredWordDocumentLoader)
112
+ docx_loader = DirectoryLoader("data/", glob="**/*.docx", loader_cls=UnstructuredWordDocumentLoader)
113
+ odt_loader = DirectoryLoader("data/", glob="**/*.odt", loader_cls=UnstructuredODTLoader)
114
+ notebook_loader = DirectoryLoader("data/", glob="**/*.ipynb", loader_cls=NotebookLoader)
115
+
116
+
117
+ all_loaders = [pdf_loader, markdown_loader, text_loader, csv_loader, python_loader, epub_loader, html_loader, ppt_loader, pptx_loader, doc_loader, docx_loader, odt_loader, notebook_loader]
118
+
119
+ # Load documents from all loaders
120
+ loaded_documents = []
121
+ for loader in all_loaders:
122
+ loaded_documents.extend(loader.load())
123
+
124
+ # Split loaded documents into chunks
125
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=40)
126
+ chunked_documents = text_splitter.split_documents(loaded_documents)
127
+
128
+ # Initialize HuggingFace embeddings
129
+ embeddings = HuggingFaceEmbeddings(
130
+ model_name="sentence-transformers/all-MiniLM-L6-v2"
131
+ )
132
+
133
+ # Create and persist a Chroma vector database from the chunked documents
134
+ db = Chroma.from_documents(
135
+ documents=chunked_documents,
136
+ embedding=embeddings,
137
+ # persist_directory=DB_DIR,
138
+ )
139
+ db.persist()
140
+ return db
141
+
142
+ def set_custom_prompt_condense():
143
+ _template = """Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language.
144
+
145
+ Chat History:
146
+ {chat_history}
147
+ Follow Up Input: {question}
148
+ Standalone question:"""
149
+ CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template)
150
+ return CONDENSE_QUESTION_PROMPT
151
+
152
+ def set_custom_prompt():
153
+ """
154
+ Prompt template for retrieval for each vectorstore
155
+ """
156
+
157
+
158
+ prompt_template = """<Instructions>
159
+ Important:
160
+ Answer with the facts listed in the list of sources below. If there isn't enough information below, say you don't know.
161
+ If asking a clarifying question to the user would help, ask the question.
162
+ ALWAYS return a "SOURCES" part in your answer, except for small-talk conversations.
163
+
164
+ Question: {question}
165
+
166
+ {context}
167
+
168
+
169
+ Question: {question}
170
+ Helpful Answer:
171
+
172
+ ---------------------------
173
+ ---------------------------
174
+ Sources:
175
+ """
176
+
177
+ prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])
178
+ return prompt
179
+
180
+ def create_chain(llm, prompt, CONDENSE_QUESTION_PROMPT, db):
181
+ """
182
+ Creates a Retrieval Question-Answering (QA) chain using a given language model, prompt, and database.
183
+
184
+ This function initializes a ConversationalRetrievalChain object with a specific chain type and configurations,
185
+ and returns this chain. The retriever is set up to return the top 3 results (k=3).
186
+
187
+ Args:
188
+ llm (any): The language model to be used in the RetrievalQA.
189
+ prompt (str): The prompt to be used in the chain type.
190
+ db (any): The database to be used as the
191
+ retriever.
192
+
193
+ Returns:
194
+ ConversationalRetrievalChain: The initialized conversational chain.
195
+ """
196
+ memory = ConversationTokenBufferMemory(llm=llm, memory_key="chat_history", return_messages=True, input_key='question', max_token_limit=1000)
197
+ chain = ConversationalRetrievalChain.from_llm(
198
+ llm=llm,
199
+ chain_type="stuff",
200
+ retriever=db.as_retriever(search_kwargs={"k": 3}),
201
+ return_source_documents=True,
202
+ combine_docs_chain_kwargs={"prompt": prompt},
203
+ condense_question_prompt=CONDENSE_QUESTION_PROMPT,
204
+ memory=memory,
205
+ )
206
+ return chain
207
+
208
+ def create_retrieval_qa_bot():
209
+ if not os.path.exists(persist_dir):
210
+ raise FileNotFoundError(f"No directory found at {persist_dir}")
211
+
212
+ try:
213
+ llm = load_model() # Assuming this function exists and works as expected
214
+ except Exception as e:
215
+ raise Exception(f"Failed to load model: {str(e)}")
216
+
217
+ try:
218
+ prompt = set_custom_prompt() # Assuming this function exists and works as expected
219
+ except Exception as e:
220
+ raise Exception(f"Failed to get prompt: {str(e)}")
221
+
222
+ try:
223
+ CONDENSE_QUESTION_PROMPT = set_custom_prompt_condense() # Assuming this function exists and works as expected
224
+ except Exception as e:
225
+ raise Exception(f"Failed to get condense prompt: {str(e)}")
226
+
227
+ try:
228
+ db = create_vector_database() # Assuming this function exists and works as expected
229
+ except Exception as e:
230
+ raise Exception(f"Failed to get database: {str(e)}")
231
+
232
+ try:
233
+ qa = create_chain(
234
+ llm=llm, prompt=prompt,CONDENSE_QUESTION_PROMPT=CONDENSE_QUESTION_PROMPT, db=db
235
+ ) # Assuming this function exists and works as expected
236
+ except Exception as e:
237
+ raise Exception(f"Failed to create retrieval QA chain: {str(e)}")
238
+
239
+ return qa
240
+
241
+ def retrieve_bot_answer(query):
242
+ """
243
+ Retrieves the answer to a given query using a QA bot.
244
+
245
+ This function creates an instance of a QA bot, passes the query to it,
246
+ and returns the bot's response.
247
+
248
+ Args:
249
+ query (str): The question to be answered by the QA bot.
250
+
251
+ Returns:
252
+ dict: The QA bot's response, typically a dictionary with response details.
253
+ """
254
+ qa_bot_instance = create_retrieval_qa_bot()
255
+ bot_response = qa_bot_instance({"query": query})
256
+ return bot_response
257
+
258
+
259
+ # from your_module import load_model, set_custom_prompt, set_custom_prompt_condense, create_vector_database, retrieve_bot_answer
260
+
261
+ def main():
262
+ st.title("Docuverse")
263
+
264
+ # Upload files
265
+ uploaded_files = st.file_uploader("Upload your documents", type=["pdf", "md", "txt", "csv", "py", "epub", "html", "ppt", "pptx", "doc", "docx", "odt", "ipynb"], accept_multiple_files=True)
266
+
267
+ if uploaded_files:
268
+ # Process uploaded files
269
+ for uploaded_file in uploaded_files:
270
+ st.write(f"Uploaded: {uploaded_file.name}")
271
+
272
+ st.write("Chat with the Document:")
273
+ query = st.text_input("Ask a question:")
274
+
275
+ if st.button("Get Answer"):
276
+ if query:
277
+ # Load model, set prompts, create vector database, and retrieve answer
278
+ try:
279
+ llm = load_model()
280
+ prompt = set_custom_prompt()
281
+ CONDENSE_QUESTION_PROMPT = set_custom_prompt_condense()
282
+ db = create_vector_database()
283
+ response = retrieve_bot_answer(query)
284
+
285
+ # Display bot response
286
+ st.write("Bot Response:")
287
+ st.write(response)
288
+ except Exception as e:
289
+ st.error(f"An error occurred: {str(e)}")
290
+ else:
291
+ st.warning("Please enter a question.")
292
+
293
+ if __name__ == "__main__":
294
+ main()