Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
-
# ------------------- MUST BE FIRST -------------------
|
2 |
import streamlit as st
|
3 |
import os
|
4 |
import tempfile
|
5 |
from pathlib import Path
|
|
|
6 |
|
7 |
-
#
|
8 |
IS_HF_SPACES = os.getenv("SPACE_ID") is not None
|
9 |
|
10 |
-
#
|
11 |
if IS_HF_SPACES:
|
12 |
KNOWLEDGE_DIR = Path(tempfile.gettempdir()) / "knowledge_base"
|
13 |
else:
|
@@ -16,349 +16,59 @@ else:
|
|
16 |
KNOWLEDGE_DIR.mkdir(parents=True, exist_ok=True)
|
17 |
|
18 |
st.set_page_config(
|
19 |
-
page_title="
|
20 |
-
layout="centered",
|
21 |
page_icon="🧠",
|
22 |
-
|
|
|
23 |
)
|
24 |
-
# -----------------------------------------------------
|
25 |
-
|
26 |
-
from knowledge_engine import KnowledgeManager
|
27 |
|
28 |
def check_hf_token():
|
29 |
-
"""Check if HuggingFace token is
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
""
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
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 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
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
|
69 |
-
st.
|
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"""
|
198 |
-
# Initialize chat history
|
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 |
-
|
249 |
-
with st.chat_message("user"):
|
250 |
-
st.write(prompt)
|
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 |
-
|
|
|
303 |
|
304 |
-
|
305 |
|
306 |
-
|
307 |
-
|
308 |
-
|
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 |
-
#
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
st.
|
362 |
-
|
363 |
-
|
364 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
import os
|
3 |
import tempfile
|
4 |
from pathlib import Path
|
5 |
+
from knowledge_engine import KnowledgeManager # Your class
|
6 |
|
7 |
+
# Determine if running on HF Spaces or locally
|
8 |
IS_HF_SPACES = os.getenv("SPACE_ID") is not None
|
9 |
|
10 |
+
# Set knowledge base directory depending on environment
|
11 |
if IS_HF_SPACES:
|
12 |
KNOWLEDGE_DIR = Path(tempfile.gettempdir()) / "knowledge_base"
|
13 |
else:
|
|
|
16 |
KNOWLEDGE_DIR.mkdir(parents=True, exist_ok=True)
|
17 |
|
18 |
st.set_page_config(
|
19 |
+
page_title="Simple Knowledge Assistant",
|
|
|
20 |
page_icon="🧠",
|
21 |
+
layout="centered",
|
22 |
+
initial_sidebar_state="collapsed",
|
23 |
)
|
|
|
|
|
|
|
24 |
|
25 |
def check_hf_token():
|
26 |
+
"""Check if HuggingFace API token is set in environment variables."""
|
27 |
+
return os.getenv("HUGGINGFACEHUB_API_TOKEN") or os.getenv("HF_TOKEN")
|
28 |
+
|
29 |
+
def initialize_knowledge_manager():
|
30 |
+
"""Initialize KnowledgeManager and handle errors."""
|
31 |
+
if "knowledge_manager" not in st.session_state:
|
32 |
+
token = check_hf_token()
|
33 |
+
if not token:
|
34 |
+
st.error("❌ HuggingFace API token not found.\n\n"
|
35 |
+
"Set HUGGINGFACEHUB_API_TOKEN or HF_TOKEN environment variable.")
|
36 |
+
st.stop()
|
37 |
+
|
38 |
+
with st.spinner("🔄 Initializing Knowledge Manager..."):
|
|
|
|
|
|
|
|
|
|
|
39 |
try:
|
40 |
+
km = KnowledgeManager()
|
41 |
+
if not hasattr(km, "embeddings") or not km.embeddings:
|
42 |
+
st.error("❌ Embeddings failed to initialize.")
|
43 |
+
st.stop()
|
44 |
+
st.session_state.knowledge_manager = km
|
45 |
+
st.success("✅ Knowledge Manager initialized successfully!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
except Exception as e:
|
47 |
+
st.error(f"❌ Error initializing Knowledge Manager:\n{e}")
|
48 |
+
st.stop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
+
# Initialize KnowledgeManager once
|
51 |
+
initialize_knowledge_manager()
|
52 |
|
53 |
+
km = st.session_state.get("knowledge_manager")
|
54 |
|
55 |
+
# If KnowledgeManager is initialized, show status and simple query input
|
56 |
+
if km:
|
57 |
+
st.info("🤖 Model & knowledge loaded and ready.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
+
# Show knowledge summary if available
|
60 |
+
if hasattr(km, "get_knowledge_summary"):
|
61 |
+
summary = km.get_knowledge_summary()
|
62 |
+
st.markdown(f"**Knowledge Summary:** {summary}")
|
63 |
+
|
64 |
+
# Simple input to ask a question and get an answer (assuming km has an 'ask' method)
|
65 |
+
question = st.text_input("Ask something from the knowledge base:")
|
66 |
+
if question:
|
67 |
+
with st.spinner("🧠 Thinking..."):
|
68 |
+
try:
|
69 |
+
answer = km.ask(question) # Replace with your actual query method
|
70 |
+
st.markdown(f"**Answer:** {answer}")
|
71 |
+
except Exception as e:
|
72 |
+
st.error(f"❌ Failed to get answer: {e}")
|
73 |
+
else:
|
74 |
+
st.warning("Knowledge Manager is not initialized yet.")
|