aamirhameed commited on
Commit
5787616
Β·
verified Β·
1 Parent(s): ebe9d57

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +265 -59
app.py CHANGED
@@ -1,9 +1,18 @@
1
  # ------------------- MUST BE FIRST -------------------
2
  import streamlit as st
 
 
3
  from pathlib import Path
4
 
5
- # Create folder if it doesn't exist
6
- KNOWLEDGE_DIR = Path("knowledge_base")
 
 
 
 
 
 
 
7
  KNOWLEDGE_DIR.mkdir(parents=True, exist_ok=True)
8
 
9
  st.set_page_config(
@@ -14,76 +23,175 @@ st.set_page_config(
14
  )
15
  # -----------------------------------------------------
16
 
17
- from knowledge_engine import KnowledgeManager, Config
18
 
 
 
 
 
19
 
20
  def initialize_lisa():
21
  """Initialize LISA knowledge manager"""
22
  if "lisa" not in st.session_state:
 
 
 
 
 
 
 
 
 
 
23
  with st.spinner("πŸ”„ Initializing knowledge engine..."):
24
  try:
25
  st.session_state.lisa = KnowledgeManager()
26
- if st.session_state.lisa.qa_chain:
 
 
27
  st.success("βœ… Knowledge engine initialized successfully!")
 
 
 
 
 
 
 
 
 
 
28
  else:
29
- st.error("❌ Failed to initialize knowledge engine. Please check your setup.")
 
 
30
  except Exception as e:
31
- st.error(f"❌ Error initializing system: {e}")
32
  st.session_state.lisa = None
33
-
 
 
 
 
 
34
 
35
  def render_sidebar():
36
  """Render the sidebar for knowledge management"""
37
  with st.sidebar:
38
  st.header("πŸ“š Knowledge Management")
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  # File upload section
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  uploaded_file = st.file_uploader(
42
- "Add knowledge file",
43
- type=["txt"],
44
  help="Upload text files to expand LISA's knowledge base"
45
  )
46
 
47
  if uploaded_file:
48
  if st.session_state.lisa:
49
- save_path = KNOWLEDGE_DIR / uploaded_file.name
50
  try:
51
- # Save the uploaded file into knowledge_base folder
52
- with open(save_path, "wb") as f:
53
- f.write(uploaded_file.getbuffer())
54
- st.success(f"βœ… Saved {uploaded_file.name} to knowledge_base folder")
55
- st.info("πŸ’‘ Click 'Rebuild Knowledge Base' to update the index")
 
 
 
 
 
 
 
56
  except Exception as e:
57
- st.error(f"❌ Error saving {uploaded_file.name}: {e}")
58
  else:
59
  st.error("❌ Knowledge engine not initialized")
60
 
61
- # Rebuild button
62
- if st.button("πŸ”„ Rebuild Knowledge Base", type="primary"):
63
- with st.spinner("πŸ”§ Rebuilding knowledge engine..."):
64
- try:
65
- st.session_state.lisa = KnowledgeManager()
66
- if st.session_state.lisa.qa_chain:
67
- st.success("βœ… Knowledge base rebuilt successfully!")
68
- st.experimental_rerun()
69
- else:
70
- st.error("❌ Failed to rebuild knowledge base")
71
- except Exception as e:
72
- st.error(f"❌ Error rebuilding: {e}")
 
 
 
73
 
74
  st.divider()
75
 
76
  # System info section
77
- st.subheader("πŸ”§ System Info")
78
- st.info("**Embedding Model:** `mxbai-embed-large`")
79
- st.info("**LLM Model:** `phi`")
80
- st.info("**Retrieval:** Hybrid (Vector + BM25)")
81
 
82
- # Knowledge base stats
83
  if st.session_state.lisa:
 
84
  file_count = st.session_state.lisa.get_knowledge_files_count()
85
  st.metric("πŸ“„ Knowledge Files", file_count)
86
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  def render_chat_interface():
89
  """Render the main chat interface"""
@@ -91,20 +199,50 @@ def render_chat_interface():
91
  if "messages" not in st.session_state:
92
  st.session_state.messages = []
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  # Display chat history
95
  for msg in st.session_state.messages:
96
  with st.chat_message(msg["role"]):
97
  st.write(msg["content"])
 
 
98
  if msg["role"] == "assistant" and msg.get("sources"):
99
- with st.expander("πŸ“– View Sources", expanded=False):
100
  for i, source in enumerate(msg["sources"]):
101
  st.markdown(f"**πŸ“„ Source {i+1}:**")
102
- st.text(source.page_content[:300] + "..." if len(source.page_content) > 300 else source.page_content)
 
 
 
 
 
 
 
103
  if hasattr(source, 'metadata') and source.metadata:
104
- st.caption(f"From: {source.metadata.get('source', 'Unknown')}")
 
 
 
 
105
 
106
  # Handle new user query
107
- if prompt := st.chat_input("Ask LISA about anything in the knowledge base..."):
108
  # Add user message
109
  st.session_state.messages.append({"role": "user", "content": prompt})
110
 
@@ -113,46 +251,114 @@ def render_chat_interface():
113
 
114
  # Generate response
115
  with st.chat_message("assistant"):
116
- if st.session_state.lisa and st.session_state.lisa.qa_chain:
117
  with st.spinner("πŸ€” Thinking..."):
118
- result = st.session_state.lisa.query(prompt)
119
-
120
- st.write(result["answer"])
121
-
122
- # Show processing time
123
- if result["processing_time"] > 0:
124
- st.caption(f"⚑ Processed in {result['processing_time']:.0f}ms")
125
-
126
- # Store message with sources
127
- st.session_state.messages.append({
128
- "role": "assistant",
129
- "content": result["answer"],
130
- "sources": result["source_chunks"] if result["source_chunks"] else None
131
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  else:
133
- error_msg = "❌ LISA is not properly initialized. Please try rebuilding the knowledge base."
134
  st.error(error_msg)
135
  st.session_state.messages.append({
136
  "role": "assistant",
137
  "content": error_msg
138
  })
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  def main():
142
  """Main application function"""
143
- # Header
144
- st.title("🧠 Sirraya xBrain - LISA")
145
- st.markdown("*Intelligent Assistant powered by Advanced RAG Technology*")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
  # Initialize LISA
148
  initialize_lisa()
149
 
 
 
 
 
 
 
150
  # Render sidebar
151
  render_sidebar()
152
 
153
  # Render chat interface
154
  render_chat_interface()
155
-
 
 
 
 
156
 
157
  if __name__ == "__main__":
158
- main()
 
1
  # ------------------- MUST BE FIRST -------------------
2
  import streamlit as st
3
+ import os
4
+ import tempfile
5
  from pathlib import Path
6
 
7
+ # Check if running in HuggingFace Spaces
8
+ IS_HF_SPACES = os.getenv("SPACE_ID") is not None
9
+
10
+ # Use temp directory for HF Spaces, local directory otherwise
11
+ if IS_HF_SPACES:
12
+ KNOWLEDGE_DIR = Path(tempfile.gettempdir()) / "knowledge_base"
13
+ else:
14
+ KNOWLEDGE_DIR = Path("knowledge_base")
15
+
16
  KNOWLEDGE_DIR.mkdir(parents=True, exist_ok=True)
17
 
18
  st.set_page_config(
 
23
  )
24
  # -----------------------------------------------------
25
 
26
+ from knowledge_engine import KnowledgeManager
27
 
28
+ def check_hf_token():
29
+ """Check if HuggingFace token is available"""
30
+ token = os.getenv("HUGGINGFACEHUB_API_TOKEN") or os.getenv("HF_TOKEN")
31
+ return token is not None
32
 
33
  def initialize_lisa():
34
  """Initialize LISA knowledge manager"""
35
  if "lisa" not in st.session_state:
36
+ # Check for HF token first
37
+ if not check_hf_token():
38
+ st.error("❌ HuggingFace API token not found. Please set HUGGINGFACEHUB_API_TOKEN or HF_TOKEN environment variable.")
39
+ if not IS_HF_SPACES:
40
+ st.info("πŸ’‘ For local development, you can set the token in your environment variables.")
41
+ else:
42
+ st.info("πŸ’‘ For HuggingFace Spaces, add your token in the Spaces settings > Repository secrets.")
43
+ st.session_state.lisa = None
44
+ return
45
+
46
  with st.spinner("πŸ”„ Initializing knowledge engine..."):
47
  try:
48
  st.session_state.lisa = KnowledgeManager()
49
+
50
+ # Check if initialization was successful
51
+ if hasattr(st.session_state.lisa, 'embeddings') and st.session_state.lisa.embeddings:
52
  st.success("βœ… Knowledge engine initialized successfully!")
53
+
54
+ # Show initialization status
55
+ if st.session_state.lisa.llm:
56
+ st.info("πŸ€– LLM model loaded successfully")
57
+ else:
58
+ st.warning("⚠️ LLM model failed to load - using fallback responses")
59
+
60
+ # Show knowledge base summary
61
+ summary = st.session_state.lisa.get_knowledge_summary()
62
+ st.info(f"πŸ“š {summary}")
63
  else:
64
+ st.error("❌ Failed to initialize embeddings. Check your internet connection.")
65
+ st.session_state.lisa = None
66
+
67
  except Exception as e:
68
+ st.error(f"❌ Error initializing system: {str(e)}")
69
  st.session_state.lisa = None
70
+
71
+ # Show debugging info
72
+ with st.expander("πŸ› Debug Information"):
73
+ st.code(f"Error: {e}")
74
+ st.code(f"HF Spaces: {IS_HF_SPACES}")
75
+ st.code(f"Token available: {check_hf_token()}")
76
 
77
  def render_sidebar():
78
  """Render the sidebar for knowledge management"""
79
  with st.sidebar:
80
  st.header("πŸ“š Knowledge Management")
81
 
82
+ # Show environment info
83
+ if IS_HF_SPACES:
84
+ st.info("πŸš€ Running on HuggingFace Spaces")
85
+ else:
86
+ st.info("πŸ’» Running locally")
87
+
88
+ # Token status
89
+ if check_hf_token():
90
+ st.success("βœ… HF Token detected")
91
+ else:
92
+ st.error("❌ HF Token missing")
93
+
94
+ st.divider()
95
+
96
  # File upload section
97
+ st.subheader("πŸ“„ Add Knowledge")
98
+
99
+ # Text input method (more reliable for HF Spaces)
100
+ st.markdown("**Method 1: Paste Text Content**")
101
+ filename = st.text_input("Filename", placeholder="my_document.txt")
102
+ content = st.text_area("Text Content", height=150, placeholder="Paste your text content here...")
103
+
104
+ if st.button("βž• Add Text Content", type="primary"):
105
+ if filename and content and st.session_state.lisa:
106
+ try:
107
+ success = st.session_state.lisa.add_text_content(filename, content)
108
+ if success:
109
+ st.success(f"βœ… Added {filename} to knowledge base!")
110
+ st.balloons()
111
+ else:
112
+ st.error("❌ Failed to add content")
113
+ except Exception as e:
114
+ st.error(f"❌ Error adding content: {e}")
115
+ elif not filename or not content:
116
+ st.warning("⚠️ Please provide both filename and content")
117
+ else:
118
+ st.error("❌ Knowledge engine not initialized")
119
+
120
+ st.divider()
121
+
122
+ # File upload method (backup)
123
+ st.markdown("**Method 2: Upload File**")
124
  uploaded_file = st.file_uploader(
125
+ "Upload text file",
126
+ type=["txt", "md", "csv"],
127
  help="Upload text files to expand LISA's knowledge base"
128
  )
129
 
130
  if uploaded_file:
131
  if st.session_state.lisa:
 
132
  try:
133
+ # Read file content
134
+ file_content = uploaded_file.read()
135
+
136
+ # Add to knowledge base using the new method
137
+ success = st.session_state.lisa.add_uploaded_file(file_content, uploaded_file.name)
138
+
139
+ if success:
140
+ st.success(f"βœ… Added {uploaded_file.name} to knowledge base!")
141
+ st.balloons()
142
+ else:
143
+ st.error("❌ Failed to add uploaded file")
144
+
145
  except Exception as e:
146
+ st.error(f"❌ Error processing upload: {e}")
147
  else:
148
  st.error("❌ Knowledge engine not initialized")
149
 
150
+ st.divider()
151
+
152
+ # Rebuild button (for troubleshooting)
153
+ if st.button("πŸ”„ Restart System", help="Reinitialize the entire system"):
154
+ # Clear session state
155
+ if "lisa" in st.session_state:
156
+ if hasattr(st.session_state.lisa, 'cleanup'):
157
+ st.session_state.lisa.cleanup()
158
+ del st.session_state.lisa
159
+
160
+ if "messages" in st.session_state:
161
+ del st.session_state.messages
162
+
163
+ st.success("πŸ”„ System restarted. Page will reload...")
164
+ st.rerun()
165
 
166
  st.divider()
167
 
168
  # System info section
169
+ st.subheader("πŸ”§ System Status")
 
 
 
170
 
 
171
  if st.session_state.lisa:
172
+ # Show system information
173
  file_count = st.session_state.lisa.get_knowledge_files_count()
174
  st.metric("πŸ“„ Knowledge Files", file_count)
175
+
176
+ # Show detailed status
177
+ with st.expander("πŸ“Š Detailed Status"):
178
+ st.text(f"Embeddings: {'βœ…' if st.session_state.lisa.embeddings else '❌'}")
179
+ st.text(f"Vector DB: {'βœ…' if st.session_state.lisa.vector_db else '❌'}")
180
+ st.text(f"BM25: {'βœ…' if st.session_state.lisa.bm25_retriever else '❌'}")
181
+ st.text(f"LLM: {'βœ…' if st.session_state.lisa.llm else '❌'}")
182
+ st.text(f"QA Chain: {'βœ…' if st.session_state.lisa.qa_chain else '❌'}")
183
+ else:
184
+ st.error("❌ System not initialized")
185
+
186
+ # Model info
187
+ with st.expander("πŸ€– Model Information"):
188
+ st.markdown("""
189
+ **Embeddings:** sentence-transformers/all-mpnet-base-v2
190
+ **LLM:** mistralai/Mistral-7B-Instruct-v0.1
191
+ **Fallbacks:** Multiple models available
192
+ **Retrieval:** Hybrid (Vector + BM25)
193
+ **Storage:** In-memory + temp files
194
+ """)
195
 
196
  def render_chat_interface():
197
  """Render the main chat interface"""
 
199
  if "messages" not in st.session_state:
200
  st.session_state.messages = []
201
 
202
+ # Show welcome message if no messages
203
+ if not st.session_state.messages:
204
+ with st.chat_message("assistant"):
205
+ welcome_msg = """
206
+ πŸ‘‹ Hello! I'm LISA, your intelligent assistant powered by Sirraya xBrain.
207
+
208
+ I can help you with questions about any knowledge you've added to my database.
209
+
210
+ **To get started:**
211
+ 1. Add some knowledge using the sidebar
212
+ 2. Ask me questions about that content
213
+ 3. I'll provide accurate answers with source citations
214
+
215
+ What would you like to know?
216
+ """
217
+ st.markdown(welcome_msg)
218
+
219
  # Display chat history
220
  for msg in st.session_state.messages:
221
  with st.chat_message(msg["role"]):
222
  st.write(msg["content"])
223
+
224
+ # Show sources if available
225
  if msg["role"] == "assistant" and msg.get("sources"):
226
+ with st.expander(f"πŸ“– View Sources ({len(msg['sources'])} found)", expanded=False):
227
  for i, source in enumerate(msg["sources"]):
228
  st.markdown(f"**πŸ“„ Source {i+1}:**")
229
+
230
+ # Truncate long content
231
+ content = source.page_content
232
+ if len(content) > 400:
233
+ content = content[:400] + "..."
234
+ st.text(content)
235
+
236
+ # Show metadata if available
237
  if hasattr(source, 'metadata') and source.metadata:
238
+ source_file = source.metadata.get('source', 'Unknown')
239
+ st.caption(f"πŸ“ From: {source_file}")
240
+
241
+ if i < len(msg["sources"]) - 1:
242
+ st.divider()
243
 
244
  # Handle new user query
245
+ if prompt := st.chat_input("Ask LISA about anything in your knowledge base..."):
246
  # Add user message
247
  st.session_state.messages.append({"role": "user", "content": prompt})
248
 
 
251
 
252
  # Generate response
253
  with st.chat_message("assistant"):
254
+ if st.session_state.lisa:
255
  with st.spinner("πŸ€” Thinking..."):
256
+ try:
257
+ result = st.session_state.lisa.query(prompt)
258
+
259
+ # Display answer
260
+ st.write(result["answer"])
261
+
262
+ # Show processing time and stats
263
+ col1, col2 = st.columns(2)
264
+ with col1:
265
+ if result["processing_time"] > 0:
266
+ st.caption(f"⚑ {result['processing_time']:.0f}ms")
267
+ with col2:
268
+ source_count = len(result["source_chunks"]) if result["source_chunks"] else 0
269
+ st.caption(f"πŸ“š {source_count} sources")
270
+
271
+ # Store message with sources
272
+ st.session_state.messages.append({
273
+ "role": "assistant",
274
+ "content": result["answer"],
275
+ "sources": result["source_chunks"] if result["source_chunks"] else None
276
+ })
277
+
278
+ except Exception as e:
279
+ error_msg = f"❌ Error processing query: {str(e)}"
280
+ st.error(error_msg)
281
+ st.session_state.messages.append({
282
+ "role": "assistant",
283
+ "content": error_msg
284
+ })
285
  else:
286
+ error_msg = "❌ LISA is not properly initialized. Please check the sidebar for system status and try restarting."
287
  st.error(error_msg)
288
  st.session_state.messages.append({
289
  "role": "assistant",
290
  "content": error_msg
291
  })
292
 
293
+ def render_sample_content():
294
+ """Render sample content section"""
295
+ with st.expander("πŸ’‘ Need sample content to test? Click here!", expanded=False):
296
+ st.markdown("**Here's some sample content you can add to test the system:**")
297
+
298
+ sample_content = """Artificial Intelligence (AI) is a rapidly evolving field that focuses on creating intelligent machines capable of performing tasks that typically require human intelligence. These tasks include learning, reasoning, problem-solving, perception, and language understanding.
299
+
300
+ Machine Learning is a subset of AI that enables computers to learn and improve from experience without being explicitly programmed. It uses algorithms and statistical models to analyze and draw inferences from patterns in data.
301
+
302
+ Deep Learning is a specialized subset of machine learning that uses artificial neural networks with multiple layers to model and understand complex patterns in data. It has been particularly successful in areas like image recognition, natural language processing, and speech recognition.
303
+
304
+ Natural Language Processing (NLP) is a branch of AI that helps computers understand, interpret, and generate human language in a valuable way. It combines computational linguistics with statistical, machine learning, and deep learning models."""
305
+
306
+ if st.button("πŸ“ Add Sample AI Content"):
307
+ if st.session_state.lisa:
308
+ success = st.session_state.lisa.add_text_content("ai_basics.txt", sample_content)
309
+ if success:
310
+ st.success("βœ… Sample AI content added! Try asking: 'What is machine learning?'")
311
+ else:
312
+ st.error("❌ Failed to add sample content")
313
+ else:
314
+ st.error("❌ Please initialize the system first")
315
 
316
  def main():
317
  """Main application function"""
318
+ # Header with better styling
319
+ st.title("🧠 Sirraya xBrain")
320
+ st.markdown("### *LISA - Intelligent Assistant powered by Advanced RAG Technology*")
321
+ st.markdown("*Created by Amir Hameed*")
322
+
323
+ # Show environment status
324
+ col1, col2, col3 = st.columns(3)
325
+ with col1:
326
+ if IS_HF_SPACES:
327
+ st.info("πŸš€ HF Spaces")
328
+ else:
329
+ st.info("πŸ’» Local")
330
+ with col2:
331
+ if check_hf_token():
332
+ st.success("πŸ”‘ Token OK")
333
+ else:
334
+ st.error("πŸ”‘ No Token")
335
+ with col3:
336
+ if "lisa" in st.session_state and st.session_state.lisa:
337
+ st.success("πŸ€– LISA Ready")
338
+ else:
339
+ st.warning("πŸ€– LISA Loading")
340
+
341
+ st.divider()
342
 
343
  # Initialize LISA
344
  initialize_lisa()
345
 
346
+ # Show sample content helper
347
+ if "lisa" in st.session_state and st.session_state.lisa:
348
+ file_count = st.session_state.lisa.get_knowledge_files_count()
349
+ if file_count <= 2: # Only default files
350
+ render_sample_content()
351
+
352
  # Render sidebar
353
  render_sidebar()
354
 
355
  # Render chat interface
356
  render_chat_interface()
357
+
358
+ # Footer
359
+ st.divider()
360
+ st.markdown("---")
361
+ st.markdown("*Powered by Sirraya xBrain | Advanced Hybrid RAG System*")
362
 
363
  if __name__ == "__main__":
364
+ main()