absiitr commited on
Commit
86a71ff
Β·
verified Β·
1 Parent(s): 8601c8e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -94
app.py CHANGED
@@ -22,7 +22,6 @@ client = None
22
  if GROQ_API_KEY:
23
  try:
24
  client = Groq(api_key=GROQ_API_KEY)
25
- # βœ… Removed the st.success message (Problem #1)
26
  logging.info("βœ… Groq client initialized successfully.")
27
  except Exception as e:
28
  st.error(f"❌ Failed to initialize Groq client: {e}")
@@ -36,10 +35,7 @@ st.set_page_config(page_title="PDF Assistant", page_icon="πŸ“˜", layout="wide")
36
  # ---------------- CSS ----------------
37
  st.markdown("""
38
  <style>
39
- /* -------------------------------------- */
40
- /* 1. SCROLL FIX FOR SIDEBAR & MAIN AREA */
41
- /* -------------------------------------- */
42
- /* Fix the sidebar and prevent it from scrolling */
43
  [data-testid="stSidebar"] {
44
  position: fixed;
45
  overflow-y: hidden !important;
@@ -47,28 +43,13 @@ st.markdown("""
47
  z-index: 99;
48
  }
49
 
50
- /* Allow the main content area to scroll independently */
51
  .main .block-container {
52
  overflow-y: auto;
53
  height: 100vh;
54
- padding-bottom: 5rem; /* Space for scrolling */
55
  }
56
 
57
- /* Hide main page scrollbar for cleaner look */
58
- ::-webkit-scrollbar {
59
- width: 8px;
60
- }
61
- ::-webkit-scrollbar-track {
62
- background: #0e1117;
63
- }
64
- ::-webkit-scrollbar-thumb {
65
- background: #2d3748;
66
- border-radius: 4px;
67
- }
68
-
69
- /* -------------------------------------- */
70
- /* 2. CHAT & UI STYLING */
71
- /* -------------------------------------- */
72
  :root {
73
  --primary-color: #1e3a8a;
74
  --background-color: #0e1117;
@@ -103,10 +84,28 @@ st.markdown("""
103
  padding-top: 5px;
104
  }
105
 
106
- /* -------------------------------------- */
107
- /* 3. INPUT FORM STYLING */
108
- /* -------------------------------------- */
109
- /* Align the input box and button properly */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  [data-testid="stForm"] {
111
  border: none;
112
  padding: 0;
@@ -142,7 +141,7 @@ def clear_memory():
142
  gc.collect()
143
  if torch.cuda.is_available():
144
  torch.cuda.empty_cache()
145
- st.success("Memory cleared. Please upload a new PDF.")
146
 
147
  def process_pdf(uploaded_file):
148
  """Process uploaded PDF and create vectorstore."""
@@ -224,58 +223,64 @@ FINAL ANSWER:
224
  except Exception as e:
225
  return None, 0, f"General error: {str(e)}"
226
 
227
- # ---------------- UI COMPONENTS ----------------
228
-
229
- # βœ… Problem #2: Title and Creator info at Top Left
230
- col_header, col_space = st.columns([0.6, 0.4])
231
- with col_header:
232
- st.title("πŸ“˜ PDF Assistant")
233
- st.markdown("**Created by [Abhishek Saxena](https://www.linkedin.com/in/abhishek-iitr/)**")
 
 
234
 
235
- # Sidebar Controls
236
  with st.sidebar:
237
  st.header("Controls")
238
- st.button("πŸ—‘οΈ Clear Chat History", on_click=clear_chat_history, use_container_width=True)
239
- st.button("πŸ”₯ Clear PDF Memory", on_click=clear_memory, use_container_width=True)
240
 
241
- st.markdown("---")
242
- if st.session_state.uploaded_file_name:
243
- st.success(f"βœ… **Active PDF:**\n `{st.session_state.uploaded_file_name}`")
244
- else:
245
- st.warning("⬆️ Upload a PDF to start chatting!")
246
-
247
- # File Upload
248
- uploaded = st.file_uploader(
249
- "Upload your PDF",
250
- type=["pdf"],
251
- key=st.session_state.uploader_key
252
- )
253
 
254
- if uploaded and uploaded.name != st.session_state.uploaded_file_name:
255
- st.session_state.uploaded_file_name = None
256
- st.session_state.chat = []
257
 
258
- with st.spinner(f"Processing '{uploaded.name}'..."):
259
- chunks_count = process_pdf(uploaded)
260
-
261
- if chunks_count is not None:
262
- st.success(f"βœ… PDF processed successfully! {chunks_count} chunks created.")
263
- st.session_state.uploaded_file_name = uploaded.name
264
- else:
265
- st.error("❌ Failed to process PDF")
 
 
 
266
  st.session_state.uploaded_file_name = None
267
-
268
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  # ---------------- INPUT AREA ----------------
271
- # βœ… Problem #3: "Enter" key submission + Arrow button using st.form
272
- # We use a form so that pressing "Enter" on the keyboard submits the question.
273
-
274
  disabled_input = st.session_state.uploaded_file_name is None or client is None
275
 
276
- # Create a form container
277
  with st.form(key='chat_form', clear_on_submit=True):
278
- # Use columns to put the input box and the button side-by-side
279
  col_input, col_btn = st.columns([0.85, 0.15], gap="small")
280
 
281
  with col_input:
@@ -287,41 +292,29 @@ with st.form(key='chat_form', clear_on_submit=True):
287
  )
288
 
289
  with col_btn:
290
- # The arrow button acts as the submit button for the form
291
  submit_btn = st.form_submit_button("➀", disabled=disabled_input, use_container_width=True)
292
 
293
- # Processing the Input (Run only when form is submitted)
294
- if submit_btn or (user_question and not disabled_input):
295
- # Note: Streamlit forms usually require the submit button click check,
296
- # but clear_on_submit=True handles the reset.
297
 
298
- if user_question:
299
- # Add user query to chat history
300
- st.session_state.chat.append(("user", user_question))
301
-
302
- # Get answer
303
- with st.spinner("Thinking..."):
304
- answer, sources, error = ask_question(user_question)
305
-
306
- if answer:
307
- bot_message = f"{answer}<div class='sources'>Context Chunks Used: {sources}</div>"
308
- st.session_state.chat.append(("bot", bot_message))
309
- else:
310
- st.session_state.chat.append(("bot", f"πŸ”΄ **Error:** {error}"))
311
 
312
- # Rerun to update the chat history display below
313
- st.rerun()
 
 
 
 
 
314
 
315
  # ---------------- CHAT HISTORY DISPLAY ----------------
316
  st.markdown("---")
317
- st.markdown("## Chat History")
318
-
319
- # Display in reverse order (newest top) or standard (newest bottom)?
320
- # Standard chat is newest bottom.
321
  for role, msg in st.session_state.chat:
322
  if role == "user":
323
  st.markdown(f"<div class='chat-user'>{msg}</div>", unsafe_allow_html=True)
324
  else:
325
- st.markdown(f"<div class='chat-bot'>{msg}</div>", unsafe_allow_html=True)
326
-
327
- # (Footer removed as requested, info moved to top)
 
22
  if GROQ_API_KEY:
23
  try:
24
  client = Groq(api_key=GROQ_API_KEY)
 
25
  logging.info("βœ… Groq client initialized successfully.")
26
  except Exception as e:
27
  st.error(f"❌ Failed to initialize Groq client: {e}")
 
35
  # ---------------- CSS ----------------
36
  st.markdown("""
37
  <style>
38
+ /* 1. SCROLL FIX FOR SIDEBAR & MAIN AREA */
 
 
 
39
  [data-testid="stSidebar"] {
40
  position: fixed;
41
  overflow-y: hidden !important;
 
43
  z-index: 99;
44
  }
45
 
 
46
  .main .block-container {
47
  overflow-y: auto;
48
  height: 100vh;
49
+ padding-bottom: 5rem;
50
  }
51
 
52
+ /* 2. CHAT & UI STYLING */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  :root {
54
  --primary-color: #1e3a8a;
55
  --background-color: #0e1117;
 
84
  padding-top: 5px;
85
  }
86
 
87
+ /* 3. CENTER TITLE STYLING */
88
+ .title-container {
89
+ text-align: center;
90
+ margin-bottom: 20px;
91
+ }
92
+ .title-text {
93
+ font-size: 3rem;
94
+ font-weight: 800;
95
+ margin: 0;
96
+ }
97
+ .creator-text {
98
+ font-size: 1.1rem;
99
+ font-weight: 500;
100
+ margin-top: -5px;
101
+ color: #cccccc;
102
+ }
103
+ .creator-text a {
104
+ color: #4da6ff;
105
+ text-decoration: none;
106
+ }
107
+
108
+ /* 4. INPUT FORM STYLING */
109
  [data-testid="stForm"] {
110
  border: none;
111
  padding: 0;
 
141
  gc.collect()
142
  if torch.cuda.is_available():
143
  torch.cuda.empty_cache()
144
+ # Notification moved to UI logic to avoid rerun issues
145
 
146
  def process_pdf(uploaded_file):
147
  """Process uploaded PDF and create vectorstore."""
 
223
  except Exception as e:
224
  return None, 0, f"General error: {str(e)}"
225
 
226
+ # ---------------- CENTERED TITLE ----------------
227
+ st.markdown("""
228
+ <div class="title-container">
229
+ <div class="title-text">πŸ“˜ PDF Assistant</div>
230
+ <div class="creator-text">
231
+ Created by <a href="https://www.linkedin.com/in/abhishek-iitr/" target="_blank">Abhishek Saxena</a>
232
+ </div>
233
+ </div>
234
+ """, unsafe_allow_html=True)
235
 
236
+ # ---------------- SIDEBAR CONTROLS ----------------
237
  with st.sidebar:
238
  st.header("Controls")
 
 
239
 
240
+ # Buttons
241
+ col_clear_chat, col_clear_mem = st.columns(2)
242
+ with col_clear_chat:
243
+ if st.button("πŸ—‘οΈ Chat", use_container_width=True):
244
+ clear_chat_history()
245
+ with col_clear_mem:
246
+ if st.button("πŸ”₯ Memory", on_click=clear_memory, use_container_width=True):
247
+ st.success("Cleared!")
 
 
 
 
248
 
249
+ st.markdown("---")
 
 
250
 
251
+ # File Upload
252
+ uploaded = st.file_uploader(
253
+ "Upload your PDF",
254
+ type=["pdf"],
255
+ key=st.session_state.uploader_key
256
+ )
257
+
258
+ # Status Message directly below uploader
259
+ if uploaded:
260
+ if uploaded.name != st.session_state.uploaded_file_name:
261
+ # Processing logic
262
  st.session_state.uploaded_file_name = None
263
+ st.session_state.chat = []
264
+
265
+ with st.spinner(f"Processing '{uploaded.name}'..."):
266
+ chunks_count = process_pdf(uploaded)
267
+
268
+ if chunks_count is not None:
269
+ st.session_state.uploaded_file_name = uploaded.name
270
+ st.success(f"βœ… Processed! {chunks_count} chunks.")
271
+ else:
272
+ st.error("❌ Failed.")
273
+ else:
274
+ # File is already processed and active
275
+ st.success(f"βœ… **Active:** `{uploaded.name}`")
276
+ else:
277
+ # No file uploaded yet
278
+ st.warning("⬆️ Upload a PDF to start chatting!")
279
 
280
  # ---------------- INPUT AREA ----------------
 
 
 
281
  disabled_input = st.session_state.uploaded_file_name is None or client is None
282
 
 
283
  with st.form(key='chat_form', clear_on_submit=True):
 
284
  col_input, col_btn = st.columns([0.85, 0.15], gap="small")
285
 
286
  with col_input:
 
292
  )
293
 
294
  with col_btn:
 
295
  submit_btn = st.form_submit_button("➀", disabled=disabled_input, use_container_width=True)
296
 
297
+ # Processing the Input
298
+ if submit_btn and user_question:
299
+ st.session_state.chat.append(("user", user_question))
 
300
 
301
+ with st.spinner("Thinking..."):
302
+ answer, sources, error = ask_question(user_question)
 
 
 
 
 
 
 
 
 
 
 
303
 
304
+ if answer:
305
+ bot_message = f"{answer}<div class='sources'>Context Chunks Used: {sources}</div>"
306
+ st.session_state.chat.append(("bot", bot_message))
307
+ else:
308
+ st.session_state.chat.append(("bot", f"πŸ”΄ **Error:** {error}"))
309
+
310
+ # No st.rerun() needed here; the submit interaction refreshes the page automatically.
311
 
312
  # ---------------- CHAT HISTORY DISPLAY ----------------
313
  st.markdown("---")
314
+ # Display newest messages at the top? (Standard is bottom, but customizable)
315
+ # Currently displaying standard order (Top = Oldest, Bottom = Newest)
 
 
316
  for role, msg in st.session_state.chat:
317
  if role == "user":
318
  st.markdown(f"<div class='chat-user'>{msg}</div>", unsafe_allow_html=True)
319
  else:
320
+ st.markdown(f"<div class='chat-bot'>{msg}</div>", unsafe_allow_html=True)