Rehman1603 commited on
Commit
445b24b
·
verified ·
1 Parent(s): f8f842e

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +220 -0
app.py ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit_lottie import st_lottie
3
+ import fitz # PyMuPDF
4
+ import requests
5
+ import os, shutil
6
+ import llm_model
7
+
8
+
9
+ SYSTEM_PROMPT = [
10
+ """
11
+ You are not Mistral AI, but rather a Q&A bot trained by Krishna Kumar while building a cool side project based on RAG. Whenever asked, you need to answer as Q&A bot.
12
+ """,
13
+ """You are a RAG based Document Q&A bot. Based on the input prompt and retrieved context from the vector database you will answer questions that are closer to the context.
14
+ If no context was found then, say "I don't know" instead of making up answer on your own. Follow above rules strictly.
15
+ """
16
+ ]
17
+
18
+
19
+ @st.cache_data(experimental_allow_widgets=True)
20
+ def index_document(_llm_object, uploaded_file):
21
+
22
+ if uploaded_file is not None:
23
+ # Specify the folder path where you want to store the uploaded file in the 'assets' folder
24
+ assets_folder = "assets/uploaded_files"
25
+ if not os.path.exists(assets_folder):
26
+ os.makedirs(assets_folder)
27
+
28
+ # Save the uploaded file to the specified folder
29
+ file_path = os.path.join(assets_folder, uploaded_file.name)
30
+ with open(file_path, "wb") as f:
31
+ f.write(uploaded_file.getvalue())
32
+
33
+ file_name = os.path.join(assets_folder, uploaded_file.name)
34
+ st.success(f"File '{file_name}' uploaded !")
35
+
36
+ with st.spinner("Indexing document... This is a free CPU version and may take a while ⏳"):
37
+ retriever = _llm_object.create_vector_db(file_name)
38
+
39
+ return file_name, retriever
40
+ else:
41
+ return None, None
42
+
43
+
44
+ def load_lottieurl(url: str):
45
+ r = requests.get(url)
46
+ if r.status_code != 200:
47
+ return None
48
+ return r.json()
49
+
50
+
51
+ def is_query_valid(query: str) -> bool:
52
+ if not query:
53
+ st.error("Please enter a question!")
54
+ return False
55
+ return True
56
+
57
+ def init_state() :
58
+ if "filename" not in st.session_state:
59
+ st.session_state.filename = None
60
+
61
+ if "messages" not in st.session_state:
62
+ st.session_state.messages = []
63
+
64
+ if "temp" not in st.session_state:
65
+ st.session_state.temp = 0.7
66
+
67
+ if "history" not in st.session_state:
68
+ st.session_state.history = [SYSTEM_PROMPT]
69
+
70
+ if "repetion_penalty" not in st.session_state:
71
+ st.session_state.repetion_penalty = 1
72
+
73
+ if "chat_bot" not in st.session_state:
74
+ st.session_state.chat_bot = "Mixtral-8x7B-Instruct-v0.1"
75
+
76
+
77
+
78
+ def faq():
79
+ st.markdown(
80
+ """
81
+ # FAQ
82
+ ## How does Document Q&A Bot work?
83
+ When you upload a document (in Pdf, word, csv or txt format), it will be divided into smaller chunks
84
+ and stored in a special type of database called a vector index
85
+ that allows for semantic search and retrieval.
86
+
87
+ When you ask a question, our Q&A bot will first look through the document chunks and find the
88
+ most relevant ones using the vector index. This acts as a context to our custom prompt which will be feed to the LLM model.
89
+ If the context was not found in the document then, LLM will reply 'I don't know'
90
+
91
+ ## Is my data safe?
92
+ Yes, your data is safe. Our bot does not store your documents or
93
+ questions. All uploaded data is deleted after you close the browser tab.
94
+
95
+ ## Why does it take so long to index my document?
96
+ Since, this is a sample QA bot project that uses open-source model
97
+ and doesn't have much resource capabilities like GPU, it may take time
98
+ to index your document based on the size of the document.
99
+
100
+ ## Are the answers 100% accurate?
101
+ No, the answers are not 100% accurate.
102
+ But for most use cases, our QA bot is very accurate and can answer
103
+ most questions. Always check with the sources to make sure that the answers
104
+ are correct.
105
+ """
106
+ )
107
+
108
+
109
+ def sidebar():
110
+ with st.sidebar:
111
+ st.markdown("## Document Q&A Bot")
112
+ st.write("LLM: Mixtral-8x7B-Instruct-v0.1")
113
+ #st.success('API key already provided!', icon='✅')
114
+
115
+ st.markdown("### Set Model Parameters")
116
+ # select LLM model
117
+ st.session_state.model_name = 'Mixtral-8x7B-Instruct-v0.1'
118
+ # set model temperature
119
+ st.session_state.temperature = st.slider(label="Temperature", min_value=0.0, max_value=1.0, step=0.1, value=0.7)
120
+ st.session_state.top_p = st.slider(label="Top Probablity", min_value=0.0, max_value=1.0, step=0.1, value=0.95)
121
+ st.session_state.repetition_penalty = st.slider(label="Repetition Penalty", min_value=0.0, max_value=1.0, step=0.1, value=1.0)
122
+
123
+ # load model parameters
124
+ st.session_state.llm_object = load_model()
125
+ st.markdown("---")
126
+ # Upload file through Streamlit
127
+ st.session_state.uploaded_file = st.file_uploader("Upload a file", type=["pdf", "doc", "docx", "txt"])
128
+ _, retriever = index_document(st.session_state.llm_object, st.session_state.uploaded_file)
129
+
130
+ st.markdown("---")
131
+ st.markdown("# About")
132
+ st.markdown(
133
+ """QA bot 🤖 allows you to ask questions about your
134
+ documents and get accurate answers with citations."""
135
+ )
136
+
137
+ st.markdown("Created with ❤️ by Krishna Kumar Yadav")
138
+ st.markdown(
139
+ """
140
+ - [Email](mailto:krishna158@live.com)
141
+ - [LinkedIn](https://www.linkedin.com/in/krishna-kumar-yadav-726831105/)
142
+ - [Github](https://github.com/krish-yadav23)
143
+ - [LeetCode](https://leetcode.com/KrishnaKumar23/)
144
+ """
145
+ )
146
+
147
+ faq()
148
+ return retriever
149
+
150
+
151
+ def chat_box() :
152
+ for message in st.session_state.messages:
153
+ with st.chat_message(message["role"]):
154
+ st.markdown(message["content"])
155
+
156
+
157
+ def generate_chat_stream(prompt, retriever) :
158
+
159
+ with st.spinner("Fetching relevant answers from source document..."):
160
+ response, sources = st.session_state.llm_object.mixtral_chat_inference(prompt, st.session_state.history, st.session_state.temperature,
161
+ st.session_state.top_p, st.session_state.repetition_penalty, retriever)
162
+
163
+
164
+ return response, sources
165
+
166
+ def stream_handler(chat_stream, placeholder) :
167
+ full_response = ''
168
+
169
+ for chunk in chat_stream :
170
+ if chunk.token.text!='</s>' :
171
+ full_response += chunk.token.text
172
+ placeholder.markdown(full_response + "▌")
173
+ placeholder.markdown(full_response)
174
+
175
+ return full_response
176
+
177
+ def show_source(sources) :
178
+ with st.expander("Show source") :
179
+ for source in sources:
180
+ st.info(f"{source}")
181
+
182
+
183
+ # Function to load model parameters
184
+ @st.cache_resource()
185
+ def load_model():
186
+ # create llm object
187
+ return llm_model.LlmModel()
188
+
189
+ st.set_page_config(page_title="Document QA Bot")
190
+ #lottie_book = load_lottieurl("https://assets4.lottiefiles.com/temp/lf20_aKAfIn.json")
191
+ #st_lottie(lottie_book, speed=1, height=200, key="initial")
192
+ # Place the title below the Lottie animation
193
+ st.title("Document Q&A Bot 🤖")
194
+
195
+ # initialize session state for streamlit app
196
+ init_state()
197
+ # Left Sidebar
198
+ retriever = sidebar()
199
+ chat_box()
200
+
201
+ if prompt := st.chat_input("Ask a question about your document!"):
202
+ st.chat_message("user").markdown(prompt)
203
+ st.session_state.messages.append({"role": "user", "content": prompt})
204
+
205
+ try:
206
+ chat_stream, sources = generate_chat_stream(prompt, retriever)
207
+
208
+ with st.chat_message("assistant"):
209
+ placeholder = st.empty()
210
+ full_response = stream_handler(chat_stream, placeholder)
211
+ show_source(sources)
212
+
213
+ st.session_state.history.append([prompt, full_response])
214
+ st.session_state.messages.append({"role": "assistant", "content": full_response})
215
+ except Exception as e:
216
+ if not st.session_state.uploaded_file:
217
+ st.error("Kindly provide the document file by uploading it before posing any questions. Your cooperation is appreciated!")
218
+ else:
219
+ st.error(e)
220
+