stevafernandes commited on
Commit
99e1a1c
·
verified ·
1 Parent(s): ace8959

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -45
app.py CHANGED
@@ -13,7 +13,6 @@ from langchain.chains.question_answering import load_qa_chain
13
  from langchain.prompts import PromptTemplate
14
 
15
  # --- Get API key from Hugging Face Secrets ---
16
- # In Hugging Face Spaces, set this in Settings -> Repository secrets
17
  GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY", "")
18
 
19
  # Use temporary directory for Hugging Face Spaces
@@ -23,6 +22,7 @@ FAISS_INDEX_PATH = os.path.join(TEMP_DIR, "faiss_index")
23
  # PDF file path
24
  PDF_FILE_PATH = "./slide.pdf"
25
 
 
26
  def get_pdf_text_from_file(pdf_path):
27
  """Read PDF from file path"""
28
  text = ""
@@ -36,40 +36,91 @@ def get_pdf_text_from_file(pdf_path):
36
  text += page_text
37
  return text
38
 
 
39
  def get_text_chunks(text):
40
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000, chunk_overlap=1000)
41
  return text_splitter.split_text(text)
42
 
 
43
  def get_vector_store(text_chunks, api_key):
44
  embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001", google_api_key=api_key)
45
  vector_store = FAISS.from_texts(text_chunks, embedding=embeddings)
46
  vector_store.save_local(FAISS_INDEX_PATH)
47
 
 
48
  def get_conversational_chain(api_key):
49
  prompt_template = """
50
- You are a helpful assistant that only answers based on the context provided from the PDF documents.
51
- Do not use any external knowledge or assumptions. If the answer is not found in the context below, reply with "I don't know."
52
- Context:
 
 
 
 
 
 
 
 
 
 
53
  {context}
54
- Question:
 
55
  {question}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  Answer:
57
  """
58
- model = ChatGoogleGenerativeAI(model="gemini-2.0-flash-exp", temperature=0, google_api_key=api_key)
59
- prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])
60
  chain = load_qa_chain(model, chain_type="stuff", prompt=prompt)
61
  return chain
62
 
63
- def user_input(user_question, api_key):
 
 
64
  embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001", google_api_key=api_key)
65
  new_db = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
66
- docs = new_db.similarity_search(user_question)
 
 
 
 
 
 
 
67
  chain = get_conversational_chain(api_key)
68
- response = chain({"input_documents": docs, "question": user_question}, return_only_outputs=True)
69
- st.write("Reply: ", response["output_text"])
 
 
 
 
 
 
 
 
70
 
71
  def main():
72
- st.set_page_config(page_title="Antimicrobial Pharmacology Chatbot", page_icon="")
 
 
 
 
 
73
  st.header("Antimicrobial Pharmacology Chatbot (RX24)")
74
  st.markdown("---")
75
 
@@ -78,6 +129,8 @@ def main():
78
  st.session_state["api_entered"] = False
79
  if "pdf_processed" not in st.session_state:
80
  st.session_state["pdf_processed"] = False
 
 
81
 
82
  # Check for API key
83
  api_key = GOOGLE_API_KEY
@@ -85,13 +138,17 @@ def main():
85
  # STEP 1: API Key handling
86
  if not st.session_state["api_entered"]:
87
  if not api_key:
88
- st.warning(" Google API Key not found in environment variables.")
89
  st.info("Please add GOOGLE_API_KEY to your Hugging Face Space secrets or enter it below.")
90
- user_api_key = st.text_input("Enter your Gemini API key", type="password", help="Get your API key from https://makersuite.google.com/app/apikey")
 
 
 
 
91
  if st.button("Continue", type="primary") and user_api_key:
92
  st.session_state["user_api_key"] = user_api_key
93
  st.session_state["api_entered"] = True
94
- st.experimental_rerun()
95
  st.stop()
96
  else:
97
  st.session_state["user_api_key"] = api_key
@@ -107,7 +164,7 @@ def main():
107
  try:
108
  raw_text = get_pdf_text_from_file(PDF_FILE_PATH)
109
  if not raw_text.strip():
110
- st.error(" No text could be extracted from the PDF. Please check your file.")
111
  st.stop()
112
 
113
  st.info(f"Processing: {PDF_FILE_PATH}")
@@ -115,52 +172,120 @@ def main():
115
  text_chunks = get_text_chunks(raw_text)
116
  get_vector_store(text_chunks, api_key)
117
  st.session_state["pdf_processed"] = True
118
- st.success(" PDF processed successfully! You can now ask questions.")
119
- st.experimental_rerun()
120
  except FileNotFoundError as e:
121
- st.error(f" {str(e)}")
122
  st.stop()
123
  except Exception as e:
124
- st.error(f" Error processing PDF: {str(e)}")
125
  st.stop()
126
 
127
- # STEP 3: Ask questions
128
- st.subheader(" Ask questions about Antimicrobial Pharmacology Text")
129
-
130
- # Show loaded file
131
- st.info(f"Loaded Antimicrobial Pharmacology Course")
132
-
133
- # Add a reprocess button
134
- col1, col2 = st.columns([3, 1])
135
- with col2:
136
- if st.button(" Reprocess PDF"):
137
  st.session_state["pdf_processed"] = False
138
- st.experimental_rerun()
139
-
140
- # Question input
141
- user_question = st.text_input(
142
- "Ask a question about your Antimicrobial Pharmacology Course",
143
- placeholder="e.g., What are the main topics discussed in the document?",
144
- help="The AI will only answer based on the content of your uploaded PDFs"
145
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
- if user_question:
148
- with st.spinner("Searching for answer..."):
149
- try:
150
- user_input(user_question, api_key)
151
- except Exception as e:
152
- st.error(f" Error getting answer: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
  # Add footer
155
  st.markdown("---")
156
  st.markdown(
157
  """
158
  <div style='text-align: center'>
159
- <small></small>
160
  </div>
161
  """,
162
  unsafe_allow_html=True
163
  )
164
 
 
165
  if __name__ == "__main__":
166
  main()
 
13
  from langchain.prompts import PromptTemplate
14
 
15
  # --- Get API key from Hugging Face Secrets ---
 
16
  GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY", "")
17
 
18
  # Use temporary directory for Hugging Face Spaces
 
22
  # PDF file path
23
  PDF_FILE_PATH = "./slide.pdf"
24
 
25
+
26
  def get_pdf_text_from_file(pdf_path):
27
  """Read PDF from file path"""
28
  text = ""
 
36
  text += page_text
37
  return text
38
 
39
+
40
  def get_text_chunks(text):
41
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000, chunk_overlap=1000)
42
  return text_splitter.split_text(text)
43
 
44
+
45
  def get_vector_store(text_chunks, api_key):
46
  embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001", google_api_key=api_key)
47
  vector_store = FAISS.from_texts(text_chunks, embedding=embeddings)
48
  vector_store.save_local(FAISS_INDEX_PATH)
49
 
50
+
51
  def get_conversational_chain(api_key):
52
  prompt_template = """
53
+ You are a helpful assistant for Antimicrobial Pharmacology. You answer questions based ONLY on the context provided from the PDF documents.
54
+
55
+ IMPORTANT RULES:
56
+ 1. Do not use any external knowledge or assumptions.
57
+ 2. If the answer is not found in the context, reply with "I don't know based on the provided materials."
58
+ 3. Be conversational and helpful.
59
+ 4. When generating MCQs, create questions that test understanding of the material.
60
+ 5. When checking answers, be encouraging and provide explanations.
61
+
62
+ Chat History:
63
+ {chat_history}
64
+
65
+ Context from PDF:
66
  {context}
67
+
68
+ Current Question:
69
  {question}
70
+
71
+ Instructions:
72
+ - If the user asks for a multiple choice question (MCQ), quiz, or test question:
73
+ * Generate a question with 4 options (A, B, C, D) based ONLY on the context
74
+ * Make sure the question tests important concepts from the material
75
+ * Do NOT reveal the correct answer yet
76
+ * Ask the user to select their answer
77
+
78
+ - If the user provides an answer (like "A", "B", "C", "D" or the full answer text) AND there was a recent MCQ in the chat history:
79
+ * Check if the answer is correct based on the context
80
+ * If correct: Congratulate them and explain why it's correct
81
+ * If incorrect: Encourage them, reveal the correct answer, and explain why
82
+
83
+ - For regular questions: Answer based on the context provided
84
+
85
  Answer:
86
  """
87
+ model = ChatGoogleGenerativeAI(model="gemini-2.0-flash-exp", temperature=0.3, google_api_key=api_key)
88
+ prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question", "chat_history"])
89
  chain = load_qa_chain(model, chain_type="stuff", prompt=prompt)
90
  return chain
91
 
92
+
93
+ def get_response(user_question, api_key, chat_history):
94
+ """Get response from the AI model with chat history context"""
95
  embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001", google_api_key=api_key)
96
  new_db = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
97
+ docs = new_db.similarity_search(user_question, k=4)
98
+
99
+ # Format chat history for context
100
+ history_text = ""
101
+ for msg in chat_history[-10:]: # Keep last 10 messages for context
102
+ role = "User" if msg["role"] == "user" else "Assistant"
103
+ history_text += f"{role}: {msg['content']}\n"
104
+
105
  chain = get_conversational_chain(api_key)
106
+ response = chain(
107
+ {
108
+ "input_documents": docs,
109
+ "question": user_question,
110
+ "chat_history": history_text
111
+ },
112
+ return_only_outputs=True
113
+ )
114
+ return response["output_text"]
115
+
116
 
117
  def main():
118
+ st.set_page_config(
119
+ page_title="Antimicrobial Pharmacology Chatbot",
120
+ page_icon="",
121
+ layout="wide"
122
+ )
123
+
124
  st.header("Antimicrobial Pharmacology Chatbot (RX24)")
125
  st.markdown("---")
126
 
 
129
  st.session_state["api_entered"] = False
130
  if "pdf_processed" not in st.session_state:
131
  st.session_state["pdf_processed"] = False
132
+ if "messages" not in st.session_state:
133
+ st.session_state["messages"] = []
134
 
135
  # Check for API key
136
  api_key = GOOGLE_API_KEY
 
138
  # STEP 1: API Key handling
139
  if not st.session_state["api_entered"]:
140
  if not api_key:
141
+ st.warning("Google API Key not found in environment variables.")
142
  st.info("Please add GOOGLE_API_KEY to your Hugging Face Space secrets or enter it below.")
143
+ user_api_key = st.text_input(
144
+ "Enter your Gemini API key",
145
+ type="password",
146
+ help="Get your API key from https://makersuite.google.com/app/apikey"
147
+ )
148
  if st.button("Continue", type="primary") and user_api_key:
149
  st.session_state["user_api_key"] = user_api_key
150
  st.session_state["api_entered"] = True
151
+ st.rerun()
152
  st.stop()
153
  else:
154
  st.session_state["user_api_key"] = api_key
 
164
  try:
165
  raw_text = get_pdf_text_from_file(PDF_FILE_PATH)
166
  if not raw_text.strip():
167
+ st.error("No text could be extracted from the PDF. Please check your file.")
168
  st.stop()
169
 
170
  st.info(f"Processing: {PDF_FILE_PATH}")
 
172
  text_chunks = get_text_chunks(raw_text)
173
  get_vector_store(text_chunks, api_key)
174
  st.session_state["pdf_processed"] = True
175
+ st.success("PDF processed successfully. You can now ask questions.")
176
+ st.rerun()
177
  except FileNotFoundError as e:
178
+ st.error(str(e))
179
  st.stop()
180
  except Exception as e:
181
+ st.error(f"Error processing PDF: {str(e)}")
182
  st.stop()
183
 
184
+ # STEP 3: Chat Interface
185
+ # Sidebar with options
186
+ with st.sidebar:
187
+ st.subheader("Options")
188
+ st.info("Loaded: Antimicrobial Pharmacology Course")
189
+
190
+ if st.button("Reprocess PDF"):
 
 
 
191
  st.session_state["pdf_processed"] = False
192
+ st.rerun()
193
+
194
+ if st.button("Clear Chat History"):
195
+ st.session_state["messages"] = []
196
+ st.rerun()
197
+
198
+ st.markdown("---")
199
+ st.subheader("Quick Actions")
200
+ st.markdown("""
201
+ Try asking:
202
+ - "Give me a multiple choice question"
203
+ - "Quiz me on antibiotics"
204
+ - "Generate an MCQ about [topic]"
205
+ - "What are the main topics?"
206
+ """)
207
+
208
+ st.markdown("---")
209
+ st.subheader("How to use MCQs")
210
+ st.markdown("""
211
+ 1. Ask for an MCQ (e.g., "Give me a quiz question")
212
+ 2. The bot will generate a question with options A-D
213
+ 3. Reply with your answer (e.g., "A" or "The answer is B")
214
+ 4. Get feedback on whether you're correct
215
+ """)
216
+
217
+ # Main chat area
218
+ st.subheader("Chat with your Pharmacology Assistant")
219
 
220
+ # Display chat messages
221
+ for message in st.session_state["messages"]:
222
+ with st.chat_message(message["role"]):
223
+ st.markdown(message["content"])
224
+
225
+ # Quick action buttons (only show if no messages yet)
226
+ if len(st.session_state["messages"]) == 0:
227
+ st.markdown("### Quick Start")
228
+ col1, col2, col3 = st.columns(3)
229
+
230
+ with col1:
231
+ if st.button("Generate MCQ", use_container_width=True):
232
+ quick_question = "Give me a multiple choice question to test my knowledge"
233
+ st.session_state["messages"].append({"role": "user", "content": quick_question})
234
+ with st.spinner("Generating question..."):
235
+ response = get_response(quick_question, api_key, st.session_state["messages"])
236
+ st.session_state["messages"].append({"role": "assistant", "content": response})
237
+ st.rerun()
238
+
239
+ with col2:
240
+ if st.button("Summarize Topics", use_container_width=True):
241
+ quick_question = "What are the main topics covered in this material?"
242
+ st.session_state["messages"].append({"role": "user", "content": quick_question})
243
+ with st.spinner("Analyzing..."):
244
+ response = get_response(quick_question, api_key, st.session_state["messages"])
245
+ st.session_state["messages"].append({"role": "assistant", "content": response})
246
+ st.rerun()
247
+
248
+ with col3:
249
+ if st.button("How can you help?", use_container_width=True):
250
+ quick_question = "What can you help me with regarding this pharmacology material?"
251
+ st.session_state["messages"].append({"role": "user", "content": quick_question})
252
+ with st.spinner("Processing..."):
253
+ response = get_response(quick_question, api_key, st.session_state["messages"])
254
+ st.session_state["messages"].append({"role": "assistant", "content": response})
255
+ st.rerun()
256
+
257
+ # Chat input
258
+ if user_question := st.chat_input("Ask a question or answer an MCQ..."):
259
+ # Add user message to chat history
260
+ st.session_state["messages"].append({"role": "user", "content": user_question})
261
+
262
+ # Display user message
263
+ with st.chat_message("user"):
264
+ st.markdown(user_question)
265
+
266
+ # Generate and display assistant response
267
+ with st.chat_message("assistant"):
268
+ with st.spinner("Processing..."):
269
+ try:
270
+ response = get_response(user_question, api_key, st.session_state["messages"])
271
+ st.markdown(response)
272
+ st.session_state["messages"].append({"role": "assistant", "content": response})
273
+ except Exception as e:
274
+ error_msg = f"Error getting answer: {str(e)}"
275
+ st.error(error_msg)
276
+ st.session_state["messages"].append({"role": "assistant", "content": error_msg})
277
 
278
  # Add footer
279
  st.markdown("---")
280
  st.markdown(
281
  """
282
  <div style='text-align: center'>
283
+ <small>Antimicrobial Pharmacology Chatbot - Powered by Gemini AI</small>
284
  </div>
285
  """,
286
  unsafe_allow_html=True
287
  )
288
 
289
+
290
  if __name__ == "__main__":
291
  main()