cryogenic22 commited on
Commit
d56abf3
·
verified ·
1 Parent(s): 17b69f5

Update components/chat.py

Browse files
Files changed (1) hide show
  1. components/chat.py +112 -310
components/chat.py CHANGED
@@ -1,8 +1,8 @@
 
1
  import streamlit as st
2
- from backend import get_embeddings_model, initialize_qa_system
3
- from langchain.embeddings import HuggingFaceEmbeddings
4
- from langchain_core.messages import HumanMessage, AIMessage, BaseMessage
5
  from datetime import datetime
 
 
6
  from utils.persistence import PersistenceManager
7
 
8
  def ensure_embeddings_initialized():
@@ -15,327 +15,129 @@ def ensure_embeddings_initialized():
15
  return False
16
  return True
17
 
18
-
19
-
20
- def clean_ai_response(content):
21
- """Clean up AI response content and remove technical artifacts."""
22
- content = str(content)
23
-
24
- # Remove common technical artifacts
25
- if "content='" in content:
26
- content = content.split("content='")[1]
27
- if "additional_kwargs" in content:
28
- content = content.split("additional_kwargs")[0]
29
-
30
- # Clean up any remaining artifacts
31
- content = content.strip("'")
32
- content = content.replace('\\n', '\n')
33
- content = content.replace('\\t', '\t')
34
-
35
- return content
36
-
37
- def format_assistant_response(content):
38
- """Format the assistant's response into a structured layout."""
39
- try:
40
- # Clean the content first
41
- content = clean_ai_response(content)
42
-
43
- # Identify sections and structure
44
- lines = [line.strip() for line in content.split('\n') if line.strip()]
45
- formatted_sections = []
46
- current_section = []
47
-
48
- for line in lines:
49
- # Handle bullet points and lists
50
- if line.startswith(('•', '-', '*')):
51
- line = f"<li>{line.lstrip('•-* ')}</li>"
52
- if not current_section:
53
- current_section.append("<ul>")
54
- current_section.append(line)
55
- # Handle section headers
56
- elif line.startswith('**') and line.endswith('**'):
57
- if current_section:
58
- if current_section[0] == "<ul>":
59
- current_section.append("</ul>")
60
- formatted_sections.extend(current_section)
61
- current_section = []
62
- header = line.strip('**')
63
- formatted_sections.append(f'<h4 class="section-header">{header}</h4>')
64
- # Regular text
65
- else:
66
- if current_section and current_section[0] == "<ul>":
67
- current_section.append("</ul>")
68
- formatted_sections.extend(current_section)
69
- current_section = []
70
- formatted_sections.append(f'<p>{line}</p>')
71
-
72
- # Add any remaining content
73
- if current_section:
74
- if current_section[0] == "<ul>":
75
- current_section.append("</ul>")
76
- formatted_sections.extend(current_section)
77
-
78
- # Build the final HTML
79
- formatted_html = f"""
80
- <div class="response-content">
81
- {''.join(formatted_sections)}
82
- </div>
83
- """
84
-
85
- return formatted_html
86
- except Exception as e:
87
- st.error(f"Error formatting response: {str(e)}")
88
- return str(content) # Return raw content if formatting fails
89
-
90
  def display_chat_interface():
91
- """Display modern chat interface with clean formatting and persistence."""
92
 
93
- if not ensure_embeddings_initialized():
94
- st.error("Failed to initialize embeddings model. Please refresh the page or contact support.")
95
- return
96
  if 'persistence' not in st.session_state:
97
- st.session_state.persistence = PersistenceManager()
 
98
  # Add custom CSS for modern chat styling
99
  st.markdown("""
100
  <style>
101
- /* Chat container */
102
- .chat-container {
103
- max-width: 800px;
104
- margin: auto;
105
- }
106
-
107
- /* User message */
108
- .user-message {
109
- background-color: #f0f2f6;
110
- padding: 1rem;
111
- border-radius: 10px;
112
- margin: 1rem 0;
113
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
114
- }
115
-
116
- /* Assistant message */
117
- .assistant-message {
118
- background-color: #ffffff;
119
- border: 1px solid #e0e0e0;
120
- padding: 1.5rem;
121
- border-radius: 10px;
122
- margin: 1rem 0;
123
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
124
- }
125
-
126
- /* Response content */
127
- .response-content {
128
- line-height: 1.6;
129
- }
130
-
131
- /* Section headers */
132
- .section-header {
133
- color: #0f52ba;
134
- margin: 1.5rem 0 1rem 0;
135
- font-size: 1.1rem;
136
- font-weight: 600;
137
- border-bottom: 2px solid #e0e0e0;
138
- padding-bottom: 0.5rem;
139
- }
140
-
141
- /* Lists */
142
- .response-content ul {
143
- margin: 1rem 0;
144
- padding-left: 1.5rem;
145
- list-style-type: none;
146
- }
147
-
148
- .response-content li {
149
- margin: 0.5rem 0;
150
- position: relative;
151
- padding-left: 1rem;
152
- }
153
-
154
- .response-content li:before {
155
- content: "•";
156
- position: absolute;
157
- left: -1rem;
158
- color: #0f52ba;
159
- }
160
-
161
- /* Paragraphs */
162
- .response-content p {
163
- margin: 1rem 0;
164
- color: #2c3e50;
165
- }
166
-
167
- /* Source citations */
168
- .source-citation {
169
- font-style: italic;
170
- color: #666;
171
- border-top: 1px solid #e0e0e0;
172
- margin-top: 1rem;
173
- padding-top: 0.5rem;
174
- font-size: 0.9rem;
175
- }
176
-
177
- /* Session selector */
178
- .session-selector {
179
- padding: 1rem;
180
- background-color: #f8f9fa;
181
- border-radius: 10px;
182
- margin-bottom: 1rem;
183
- }
184
  </style>
185
  """, unsafe_allow_html=True)
186
 
187
- sessions = persistence.list_available_sessions()
188
- if sessions:
189
- st.markdown('<div class="session-selector">', unsafe_allow_html=True)
190
- st.subheader("💾 Load Previous Chat")
191
- selected_session = st.selectbox(
192
- "Select a previous conversation:",
193
- options=[s['session_id'] for s in sessions],
194
- format_func=lambda x: f"Chat from {datetime.strptime(x.split('_')[1], '%Y%m%d_%H%M%S').strftime('%B %d, %Y %I:%M %p')}"
195
- )
196
-
197
- if selected_session:
198
- if st.button("Load Selected Chat"):
199
- with st.spinner("Loading previous chat..."):
200
- # Load previous chat state
201
- messages = persistence.load_chat_history(selected_session)
202
- if messages:
203
- st.session_state.messages = messages
204
-
205
- # Load vector store with existing embeddings
206
- vector_store = persistence.load_vector_store(selected_session)
207
- if vector_store:
208
- st.session_state.vector_store = vector_store
209
- st.session_state.qa_system = initialize_qa_system(vector_store)
210
- st.session_state.current_session_id = selected_session
211
- st.rerun()
212
- st.markdown('</div>', unsafe_allow_html=True)
213
-
214
- # Initialize chat history
215
- if 'messages' not in st.session_state:
216
- st.session_state.messages = []
217
-
218
- # Display current session info if available
219
- if 'current_session_id' in st.session_state:
220
- session_date = datetime.strptime(
221
- st.session_state.current_session_id.split('_')[1],
222
- '%Y%m%d_%H%M%S'
223
- ).strftime('%B %d, %Y %I:%M %p')
224
- st.info(f"📅 Current Session: {session_date}")
225
-
226
- # Display chat history
227
- for message in st.session_state.messages:
228
- if isinstance(message, HumanMessage):
229
- st.markdown(f"""
230
- <div class="user-message">
231
- 🧑‍💼 <strong>You:</strong><br>{message.content}
232
- </div>
233
- """, unsafe_allow_html=True)
234
- elif isinstance(message, AIMessage):
235
- st.markdown(f"""
236
- <div class="assistant-message">
237
- 🤖 <strong>Assistant:</strong>
238
- {format_assistant_response(message.content)}
239
- </div>
240
- """, unsafe_allow_html=True)
241
-
242
- # Chat input
243
- if prompt := st.chat_input("Ask about your documents..."):
244
- with st.spinner("Analyzing..."):
245
- # Validate input
246
- if not prompt.strip():
247
- st.warning("Please enter a valid question.")
248
- return
249
 
250
- # Create and append human message
251
- human_message = HumanMessage(content=prompt)
252
- st.session_state.messages.append(human_message)
253
 
254
- # Get response from QA system
255
- try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  response = st.session_state.qa_system.invoke({
257
  "input": prompt,
258
  "chat_history": st.session_state.messages
259
  })
260
- except Exception as e:
261
- st.error("An error occurred during chat processing.")
262
- st.error(f"Error details: {str(e)}")
263
- import traceback
264
- st.error(traceback.format_exc())
265
- return # Stop execution to prevent further errors
266
-
267
-
268
- # Handle response
269
- if response:
270
- ai_message = AIMessage(content=str(response))
271
- st.session_state.messages.append(ai_message)
272
-
273
- # Save chat history if we have a session
274
- if 'current_session_id' in st.session_state:
275
- persistence.save_chat_history(
276
- st.session_state.messages,
277
- st.session_state.current_session_id,
278
- metadata={
279
- 'document_count': len(st.session_state.get('processed_files', [])),
280
- 'last_question': prompt,
281
- 'last_updated': datetime.now().isoformat()
282
- }
283
- )
284
 
285
- st.rerun()
286
- else:
287
- st.error("No valid response received. Please try again.")
288
-
289
-
290
- def format_assistant_response(content):
291
- """Format the assistant's response into a structured layout."""
292
- try:
293
- # Clean the content first
294
- content = clean_ai_response(content)
295
-
296
- # Identify sections and structure
297
- lines = [line.strip() for line in content.split('\n') if line.strip()]
298
- formatted_sections = []
299
- current_section = []
300
-
301
- for line in lines:
302
- # Handle bullet points and lists
303
- if line.startswith(('•', '-', '*')):
304
- line = f"<li>{line.lstrip('•-* ')}</li>"
305
- if not current_section:
306
- current_section.append("<ul>")
307
- current_section.append(line)
308
- # Handle section headers
309
- elif line.startswith('**') and line.endswith('**'):
310
- if current_section:
311
- if current_section[0] == "<ul>":
312
- current_section.append("</ul>")
313
- formatted_sections.extend(current_section)
314
- current_section = []
315
- header = line.strip('**')
316
- formatted_sections.append(f'<h4 class="section-header">{header}</h4>')
317
- # Regular text
318
- else:
319
- if current_section and current_section[0] == "<ul>":
320
- current_section.append("</ul>")
321
- formatted_sections.extend(current_section)
322
- current_section = []
323
- formatted_sections.append(f'<p>{line}</p>')
324
-
325
- # Add any remaining content
326
- if current_section:
327
- if current_section[0] == "<ul>":
328
- current_section.append("</ul>")
329
- formatted_sections.extend(current_section)
330
-
331
- # Build the final HTML
332
- formatted_html = f"""
333
- <div class="response-content">
334
- {''.join(formatted_sections)}
335
- </div>
336
- """
337
-
338
- return formatted_html
339
  except Exception as e:
340
- st.error(f"Error formatting response: {str(e)}")
341
- return str(content) # Return raw content if formatting fails
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # components/chat.py
2
  import streamlit as st
 
 
 
3
  from datetime import datetime
4
+ from langchain_core.messages import HumanMessage, AIMessage
5
+ from backend import get_embeddings_model, initialize_qa_system
6
  from utils.persistence import PersistenceManager
7
 
8
  def ensure_embeddings_initialized():
 
15
  return False
16
  return True
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  def display_chat_interface():
19
+ """Display modern chat interface with clean formatting."""
20
 
21
+ # Initialize persistence if needed
 
 
22
  if 'persistence' not in st.session_state:
23
+ st.session_state.persistence = PersistenceManager()
24
+
25
  # Add custom CSS for modern chat styling
26
  st.markdown("""
27
  <style>
28
+ /* Your existing styles */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  </style>
30
  """, unsafe_allow_html=True)
31
 
32
+ try:
33
+ # Check if QA system is initialized
34
+ if 'qa_system' not in st.session_state or st.session_state.qa_system is None:
35
+ # Show available sessions if any
36
+ sessions = st.session_state.persistence.list_available_sessions()
37
+ if sessions:
38
+ st.markdown('<div class="session-selector">', unsafe_allow_html=True)
39
+ st.subheader("💾 Load Previous Chat")
40
+ selected_session = st.selectbox(
41
+ "Select a previous conversation:",
42
+ options=[s['session_id'] for s in sessions],
43
+ format_func=lambda x: f"Chat from {datetime.strptime(x.split('_')[1], '%Y%m%d_%H%M%S').strftime('%B %d, %Y %I:%M %p')}"
44
+ )
45
+
46
+ if selected_session and st.button("Load Selected Chat"):
47
+ with st.spinner("Loading previous chat..."):
48
+ messages = st.session_state.persistence.load_chat_history(selected_session)
49
+ if messages:
50
+ st.session_state.messages = messages
51
+
52
+ # Load vector store
53
+ vector_store = st.session_state.persistence.load_vector_store(selected_session)
54
+ if vector_store:
55
+ st.session_state.vector_store = vector_store
56
+ st.session_state.qa_system = initialize_qa_system(vector_store)
57
+ st.session_state.current_session_id = selected_session
58
+ st.rerun()
59
+ st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
+ st.warning("Please upload documents or select a previous chat to begin.")
62
+ return
 
63
 
64
+ # Initialize chat history
65
+ if 'messages' not in st.session_state:
66
+ st.session_state.messages = []
67
+
68
+ # Display current session info if available
69
+ if 'current_session_id' in st.session_state:
70
+ session_date = datetime.strptime(
71
+ st.session_state.current_session_id.split('_')[1],
72
+ '%Y%m%d_%H%M%S'
73
+ ).strftime('%B %d, %Y %I:%M %p')
74
+ st.info(f"📅 Current Session: {session_date}")
75
+
76
+ # Display chat history
77
+ for message in st.session_state.messages:
78
+ if isinstance(message, HumanMessage):
79
+ st.markdown(f"""
80
+ <div class="user-message">
81
+ 🧑‍💼 <strong>You:</strong><br>{message.content}
82
+ </div>
83
+ """, unsafe_allow_html=True)
84
+ elif isinstance(message, AIMessage):
85
+ st.markdown(f"""
86
+ <div class="assistant-message">
87
+ 🤖 <strong>Assistant:</strong>
88
+ {format_assistant_response(message.content)}
89
+ </div>
90
+ """, unsafe_allow_html=True)
91
+
92
+ # Chat input
93
+ if prompt := st.chat_input("Ask about your documents..."):
94
+ with st.spinner("Analyzing..."):
95
+ # Validate input
96
+ if not prompt.strip():
97
+ st.warning("Please enter a valid question.")
98
+ return
99
+
100
+ # Create and append human message
101
+ human_message = HumanMessage(content=prompt)
102
+ st.session_state.messages.append(human_message)
103
+
104
+ # Get response from QA system
105
  response = st.session_state.qa_system.invoke({
106
  "input": prompt,
107
  "chat_history": st.session_state.messages
108
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
+ # Handle response
111
+ if response:
112
+ ai_message = AIMessage(content=str(response))
113
+ st.session_state.messages.append(ai_message)
114
+
115
+ # Save chat history
116
+ if 'current_session_id' in st.session_state:
117
+ st.session_state.persistence.save_chat_history(
118
+ st.session_state.messages,
119
+ st.session_state.current_session_id,
120
+ metadata={
121
+ 'last_question': prompt,
122
+ 'last_updated': datetime.now().isoformat()
123
+ }
124
+ )
125
+
126
+ st.rerun()
127
+ else:
128
+ st.error("No valid response received. Please try again.")
129
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  except Exception as e:
131
+ st.error("An error occurred during chat processing.")
132
+ st.error(f"Error details: {str(e)}")
133
+ import traceback
134
+ st.error(traceback.format_exc())
135
+
136
+ # Your existing helper functions remain the same
137
+ def clean_ai_response(content):
138
+ # Your existing function...
139
+ pass
140
+
141
+ def format_assistant_response(content):
142
+ # Your existing function...
143
+ pass