absiitr commited on
Commit
0eb63e4
·
verified ·
1 Parent(s): 984f2ea

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -74
app.py CHANGED
@@ -46,19 +46,21 @@ st.markdown("""
46
  background: #2d3748;
47
  padding: 12px;
48
  border-radius: 10px 10px 2px 10px;
49
- margin: 6px 0 6px auto;
50
  max-width: 85%;
51
- text-align: right;
52
  color: var(--text-color);
 
53
  }
54
  .chat-bot {
55
  background: var(--primary-color);
56
  padding: 12px;
57
  border-radius: 10px 10px 10px 2px;
58
- margin: 6px auto 6px 0;
59
  max-width: 85%;
60
  text-align: left;
61
  color: #ffffff;
 
62
  }
63
 
64
  .sources {
@@ -70,14 +72,11 @@ st.markdown("""
70
  }
71
 
72
  .footer {
73
- position: fixed;
74
- left: 0;
75
- bottom: 0;
76
- width: 100%;
77
  background-color: var(--secondary-background-color);
78
  color: var(--text-color);
79
  text-align: center;
80
- padding: 10px;
81
  font-size: 0.85em;
82
  border-top: 1px solid rgba(255, 255, 255, 0.1);
83
  }
@@ -90,35 +89,47 @@ st.markdown("""
90
  text-decoration: underline;
91
  }
92
 
93
- /* Scroll container for chat history */
 
 
 
 
 
 
 
94
  .chat-container {
95
- height: 400px;
96
  overflow-y: auto;
97
- padding: 10px;
 
98
  border: 1px solid rgba(255, 255, 255, 0.1);
99
  border-radius: 8px;
100
- margin-bottom: 20px;
101
- background-color: rgba(30, 30, 30, 0.1);
102
  }
103
- </style>
104
 
105
- <script>
106
- // Auto-scroll to bottom of chat when new messages are added
107
- function scrollToBottom() {
108
- const container = document.querySelector('.chat-container');
109
- if (container) {
110
- container.scrollTop = container.scrollHeight;
111
- }
 
112
  }
113
 
114
- // Run scroll after the page loads and after each Streamlit rerun
115
- window.addEventListener('load', scrollToBottom);
 
 
 
 
 
116
 
117
- // Also scroll when Streamlit updates the page
118
- if (window.parent && window.parent.stq) {
119
- window.parent.stq.push(scrollToBottom);
120
  }
121
- </script>
122
  """, unsafe_allow_html=True)
123
 
124
  # ---------------- SESSION STATE ----------------
@@ -137,13 +148,14 @@ if "uploaded_file_name" not in st.session_state:
137
  if "uploader_key" not in st.session_state:
138
  st.session_state.uploader_key = 0
139
 
140
- # Initialize question key to track input state
141
- if "question_submitted" not in st.session_state:
142
- st.session_state.question_submitted = ""
143
 
144
  # ---------------- FUNCTIONS ----------------
145
  def clear_chat_history():
146
  st.session_state.chat = []
 
147
 
148
  def clear_memory():
149
  st.session_state.vectorstore = None
@@ -270,6 +282,7 @@ uploaded = st.file_uploader(
270
  if uploaded and uploaded.name != st.session_state.uploaded_file_name:
271
  st.session_state.uploaded_file_name = None
272
  st.session_state.chat = []
 
273
 
274
  with st.spinner(f"Processing '{uploaded.name}'..."):
275
  chunks_count = process_pdf(uploaded)
@@ -283,10 +296,32 @@ if uploaded and uploaded.name != st.session_state.uploaded_file_name:
283
 
284
  st.rerun()
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  # Chat Input with form for better control
287
  disabled_input = st.session_state.uploaded_file_name is None or client is None
288
 
289
- # Use a form to handle input submission and clearing
290
  with st.form(key="chat_form", clear_on_submit=True):
291
  col1, col2 = st.columns([6, 1])
292
  with col1:
@@ -295,10 +330,14 @@ with st.form(key="chat_form", clear_on_submit=True):
295
  key="question_input",
296
  disabled=disabled_input,
297
  label_visibility="collapsed",
298
- placeholder="Type your question here..."
 
299
  )
300
  with col2:
301
- submit_button = st.form_submit_button("Send", disabled=disabled_input, use_container_width=True)
 
 
 
302
 
303
  # Handle form submission
304
  if submit_button and question:
@@ -315,37 +354,10 @@ if submit_button and question:
315
  else:
316
  st.session_state.chat.append(("bot", f"🔴 **Error:** {error}"))
317
 
318
- # The form already clears the input (clear_on_submit=True)
 
319
  st.rerun()
320
 
321
- # Display Chat History in scrollable container
322
- st.markdown("## Chat History")
323
- with st.container():
324
- st.markdown('<div class="chat-container">', unsafe_allow_html=True)
325
-
326
- if not st.session_state.chat:
327
- st.markdown("<div style='text-align: center; color: #888; padding: 40px;'>No messages yet. Ask a question to start chatting!</div>", unsafe_allow_html=True)
328
- else:
329
- # Display all messages
330
- for role, msg in st.session_state.chat:
331
- if role == "user":
332
- st.markdown(f"<div class='chat-user'>{msg}</div>", unsafe_allow_html=True)
333
- else:
334
- st.markdown(f"<div class='chat-bot'>{msg}</div>", unsafe_allow_html=True)
335
-
336
- st.markdown('</div>', unsafe_allow_html=True)
337
-
338
- # Add JavaScript to auto-scroll
339
- st.markdown("""
340
- <script>
341
- // Auto-scroll to bottom
342
- const container = document.querySelector('.chat-container');
343
- if (container) {
344
- container.scrollTop = container.scrollHeight;
345
- }
346
- </script>
347
- """, unsafe_allow_html=True)
348
-
349
  # Footer
350
  footer_html = """
351
  <div class="footer">
@@ -354,15 +366,35 @@ footer_html = """
354
  """
355
  st.markdown(footer_html, unsafe_allow_html=True)
356
 
357
- # Add auto-scroll JavaScript after footer as well
358
- st.markdown("""
359
- <script>
360
- // Additional scroll trigger for better reliability
361
- setTimeout(() => {
362
- const container = document.querySelector('.chat-container');
363
- if (container) {
364
- container.scrollTop = container.scrollHeight;
365
- }
366
- }, 100);
367
- </script>
368
- """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  background: #2d3748;
47
  padding: 12px;
48
  border-radius: 10px 10px 2px 10px;
49
+ margin: 10px 0 10px auto;
50
  max-width: 85%;
51
+ text-align: left;
52
  color: var(--text-color);
53
+ word-wrap: break-word;
54
  }
55
  .chat-bot {
56
  background: var(--primary-color);
57
  padding: 12px;
58
  border-radius: 10px 10px 10px 2px;
59
+ margin: 10px auto 10px 0;
60
  max-width: 85%;
61
  text-align: left;
62
  color: #ffffff;
63
+ word-wrap: break-word;
64
  }
65
 
66
  .sources {
 
72
  }
73
 
74
  .footer {
75
+ margin-top: 30px;
76
+ padding: 15px;
 
 
77
  background-color: var(--secondary-background-color);
78
  color: var(--text-color);
79
  text-align: center;
 
80
  font-size: 0.85em;
81
  border-top: 1px solid rgba(255, 255, 255, 0.1);
82
  }
 
89
  text-decoration: underline;
90
  }
91
 
92
+ /* Main container to control layout */
93
+ .main-container {
94
+ display: flex;
95
+ flex-direction: column;
96
+ height: 100vh;
97
+ }
98
+
99
+ /* Chat container that grows and scrolls */
100
  .chat-container {
101
+ flex: 1;
102
  overflow-y: auto;
103
+ padding: 15px;
104
+ margin-bottom: 20px;
105
  border: 1px solid rgba(255, 255, 255, 0.1);
106
  border-radius: 8px;
107
+ background-color: rgba(30, 30, 30, 0.05);
 
108
  }
 
109
 
110
+ /* Input area stays at bottom */
111
+ .input-container {
112
+ position: sticky;
113
+ bottom: 0;
114
+ background: var(--background-color);
115
+ padding: 15px 0;
116
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
117
+ z-index: 100;
118
  }
119
 
120
+ /* Empty state styling */
121
+ .empty-state {
122
+ text-align: center;
123
+ color: #888;
124
+ padding: 60px 20px;
125
+ font-style: italic;
126
+ }
127
 
128
+ /* Smooth scrolling */
129
+ .chat-container {
130
+ scroll-behavior: smooth;
131
  }
132
+ </style>
133
  """, unsafe_allow_html=True)
134
 
135
  # ---------------- SESSION STATE ----------------
 
148
  if "uploader_key" not in st.session_state:
149
  st.session_state.uploader_key = 0
150
 
151
+ # Track last message count for scroll detection
152
+ if "last_message_count" not in st.session_state:
153
+ st.session_state.last_message_count = 0
154
 
155
  # ---------------- FUNCTIONS ----------------
156
  def clear_chat_history():
157
  st.session_state.chat = []
158
+ st.session_state.last_message_count = 0
159
 
160
  def clear_memory():
161
  st.session_state.vectorstore = None
 
282
  if uploaded and uploaded.name != st.session_state.uploaded_file_name:
283
  st.session_state.uploaded_file_name = None
284
  st.session_state.chat = []
285
+ st.session_state.last_message_count = 0
286
 
287
  with st.spinner(f"Processing '{uploaded.name}'..."):
288
  chunks_count = process_pdf(uploaded)
 
296
 
297
  st.rerun()
298
 
299
+ # Main chat interface
300
+ st.markdown('<div class="main-container">', unsafe_allow_html=True)
301
+
302
+ # Chat History Display
303
+ st.markdown("## Chat History")
304
+ st.markdown('<div class="chat-container" id="chat-container">', unsafe_allow_html=True)
305
+
306
+ if not st.session_state.chat:
307
+ st.markdown('<div class="empty-state">No messages yet. Ask a question to start chatting!</div>', unsafe_allow_html=True)
308
+ else:
309
+ # Display all messages
310
+ for i, (role, msg) in enumerate(st.session_state.chat):
311
+ if role == "user":
312
+ st.markdown(f"<div class='chat-user'>{msg}</div>", unsafe_allow_html=True)
313
+ else:
314
+ st.markdown(f"<div class='chat-bot'>{msg}</div>", unsafe_allow_html=True)
315
+
316
+ st.markdown('</div>', unsafe_allow_html=True)
317
+
318
+ # Input area at bottom (like ChatGPT)
319
+ st.markdown('<div class="input-container">', unsafe_allow_html=True)
320
+
321
  # Chat Input with form for better control
322
  disabled_input = st.session_state.uploaded_file_name is None or client is None
323
 
324
+ # Create a form for chat input
325
  with st.form(key="chat_form", clear_on_submit=True):
326
  col1, col2 = st.columns([6, 1])
327
  with col1:
 
330
  key="question_input",
331
  disabled=disabled_input,
332
  label_visibility="collapsed",
333
+ placeholder="Type your question here...",
334
+ help="Press Enter or click Send to ask"
335
  )
336
  with col2:
337
+ submit_button = st.form_submit_button("", disabled=disabled_input, use_container_width=True, help="Send message")
338
+
339
+ st.markdown('</div>', unsafe_allow_html=True) # Close input-container
340
+ st.markdown('</div>', unsafe_allow_html=True) # Close main-container
341
 
342
  # Handle form submission
343
  if submit_button and question:
 
354
  else:
355
  st.session_state.chat.append(("bot", f"🔴 **Error:** {error}"))
356
 
357
+ # Update message count
358
+ st.session_state.last_message_count = len(st.session_state.chat)
359
  st.rerun()
360
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  # Footer
362
  footer_html = """
363
  <div class="footer">
 
366
  """
367
  st.markdown(footer_html, unsafe_allow_html=True)
368
 
369
+ # AUTOSCROLL FIX: Check if new messages were added and trigger scroll
370
+ if len(st.session_state.chat) > st.session_state.last_message_count:
371
+ # Update the counter
372
+ st.session_state.last_message_count = len(st.session_state.chat)
373
+
374
+ # Inject JavaScript to scroll to bottom
375
+ st.markdown("""
376
+ <script>
377
+ // Wait a tiny bit for DOM to update, then scroll
378
+ setTimeout(() => {
379
+ const chatContainer = document.getElementById('chat-container');
380
+ if (chatContainer) {
381
+ chatContainer.scrollTop = chatContainer.scrollHeight;
382
+ }
383
+ }, 100);
384
+ </script>
385
+ """, unsafe_allow_html=True)
386
+ else:
387
+ # Initial scroll on load
388
+ st.markdown("""
389
+ <script>
390
+ // Initial scroll to bottom on page load
391
+ document.addEventListener('DOMContentLoaded', function() {
392
+ setTimeout(() => {
393
+ const chatContainer = document.getElementById('chat-container');
394
+ if (chatContainer) {
395
+ chatContainer.scrollTop = chatContainer.scrollHeight;
396
+ }
397
+ }, 300);
398
+ });
399
+ </script>
400
+ """, unsafe_allow_html=True)