bharathmunakala commited on
Commit
a73818e
·
verified ·
1 Parent(s): 56df456

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +328 -321
app.py CHANGED
@@ -1,321 +1,328 @@
1
- __import__('pysqlite3')
2
- import sys
3
- sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')
4
-
5
- import sqlite3
6
-
7
- import os
8
- import streamlit as st
9
- import chromadb
10
- from typing import Dict, Optional, Any
11
- from pathlib import Path
12
- from dotenv import load_dotenv
13
- from llama_index.core import VectorStoreIndex, StorageContext, Settings
14
- from llama_index.vector_stores.chroma import ChromaVectorStore
15
- from llama_index.llms.groq import Groq
16
- from llama_index.embeddings.cohere import CohereEmbedding
17
-
18
-
19
- from arize.otel import register
20
- from openinference.instrumentation.llama_index import LlamaIndexInstrumentor
21
-
22
- # Setup OTel via Arize's convenience function
23
- tracer_provider = register(
24
- space_id=os.getenv("ARIZE_SPACE_ID"),
25
- api_key=os.getenv("ARIZE_API_KEY"),
26
- project_name="rbacrag" # Choose a project name
27
- )
28
-
29
- # Instrument LlamaIndex
30
- LlamaIndexInstrumentor().instrument(tracer_provider=tracer_provider)
31
-
32
- # Import database module
33
- from database import db, initialize_users
34
-
35
- # Load environment variables
36
- load_dotenv()
37
-
38
- # Initialize default users
39
- initialize_users()
40
-
41
- # Role-based access control for documents
42
- ROLE_ACCESS = {
43
- "hr": ["hr", "general"],
44
- "engineering": ["engineering", "general"],
45
- "finance": ["finance", "general"],
46
- "marketing": ["marketing", "general"]
47
- }
48
-
49
- # Initialize session state
50
- def initialize_session_state():
51
- """Initialize or reset the session state"""
52
- if "authenticated" not in st.session_state:
53
- st.session_state.authenticated = False
54
- if "username" not in st.session_state:
55
- st.session_state.username = None
56
- if "role" not in st.session_state:
57
- st.session_state.role = None
58
- if "messages" not in st.session_state:
59
- st.session_state.messages = []
60
- if "vector_index" not in st.session_state:
61
- st.session_state.vector_index = None
62
- if "query_engine" not in st.session_state:
63
- st.session_state.query_engine = None
64
-
65
- # Set page config
66
- st.set_page_config(
67
- page_title="Departmental RAG System",
68
- page_icon="🔒",
69
- layout="centered",
70
- initial_sidebar_state="collapsed"
71
- )
72
-
73
- # Initialize session state
74
- initialize_session_state()
75
-
76
- # Authentication functions
77
- def login(username: str, password: str) -> bool:
78
- """
79
- Authenticate user and set session state
80
-
81
- Args:
82
- username: The username to authenticate
83
- password: The password to verify
84
-
85
- Returns:
86
- bool: True if authentication was successful, False otherwise
87
- """
88
- try:
89
- user = db.verify_user(username, password)
90
- if user:
91
- st.session_state.authenticated = True
92
- st.session_state.username = user["username"]
93
- st.session_state.role = user["role"]
94
- st.session_state.messages = [
95
- {"role": "assistant", "content": f"Welcome, {user['username']}! How can I assist you today?"}
96
- ]
97
- st.rerun() # Rerun to update the UI
98
- return True
99
- return False
100
- except Exception as e:
101
- st.error(f"An error occurred during login: {str(e)}")
102
- return False
103
-
104
- def logout():
105
- """
106
- Log out the current user and clear session state
107
- """
108
- username = st.session_state.get('username', 'Unknown')
109
- st.session_state.clear()
110
- initialize_session_state()
111
- st.success(f"Successfully logged out {username}")
112
- st.rerun() # Rerun to update the UI
113
-
114
- @st.cache_resource
115
- def load_vector_index(role: str):
116
- """Load the ChromaDB index for the user's role"""
117
- try:
118
- # Initialize Cohere embeddings
119
- cohere_api_key = os.getenv("COHERE_API_KEY")
120
- if not cohere_api_key:
121
- raise ValueError("COHERE_API_KEY not found in environment variables")
122
-
123
- embed_model = CohereEmbedding(
124
- cohere_api_key=cohere_api_key,
125
- model_name="embed-english-v3.0",
126
- input_type="search_document"
127
- )
128
- Settings.embed_model = embed_model
129
-
130
- # Initialize Chroma client
131
- persist_dir = f"./chroma_db/{role}"
132
- chroma_client = chromadb.PersistentClient(path=persist_dir)
133
-
134
- # Get the collection
135
- chroma_collection = chroma_client.get_collection("documents")
136
-
137
- # Create vector store
138
- vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
139
-
140
- # Create storage context
141
- storage_context = StorageContext.from_defaults(vector_store=vector_store)
142
-
143
- # Load the index
144
- index = VectorStoreIndex.from_vector_store(
145
- vector_store=vector_store,
146
- storage_context=storage_context,
147
- embed_model=embed_model
148
- )
149
-
150
- return index
151
- except Exception as e:
152
- st.error(f"Error loading vector index: {str(e)}")
153
- st.stop()
154
-
155
- def chat_interface():
156
- """Main chat interface"""
157
- # Add styled heading
158
- st.markdown(f"<h2 style='color: #1407fa;'>💬 {st.session_state.role.capitalize()} Department Chat</h3>", unsafe_allow_html=True)
159
-
160
- # Display chat messages
161
- for message in st.session_state.messages:
162
- with st.chat_message(message["role"]):
163
- st.markdown(message["content"])
164
-
165
- # Load the appropriate index for the user's role
166
- index = load_vector_index(st.session_state.role)
167
-
168
- # Initialize Groq LLM
169
- try:
170
- llm = Groq(
171
- model="llama3-8b-8192",
172
- api_key=os.getenv("GROQ_API_KEY"),
173
- temperature=0.5,
174
- system_prompt=f"You are a helpful assistant specialized in {st.session_state.role} department documents. Answer the user queries with the help of the provided context with high accuracy and precision."
175
- )
176
-
177
- # Create query engine with the LLM
178
- query_engine = index.as_query_engine(
179
- llm=llm,
180
- similarity_top_k=3,
181
- response_mode="compact"
182
- )
183
- except Exception as e:
184
- st.error(f"Error initializing LLM: {str(e)}")
185
- st.warning("Falling back to default LLM settings. Some features may be limited.")
186
- query_engine = index.as_query_engine(
187
- similarity_top_k=3,
188
- response_mode="compact"
189
- )
190
-
191
- # Chat input
192
- if prompt := st.chat_input(f"Ask about {st.session_state.role} documents..."):
193
- # Add user message to chat history
194
- st.session_state.messages.append({"role": "user", "content": prompt})
195
-
196
- # Display user message
197
- with st.chat_message("user"):
198
- st.markdown(prompt)
199
-
200
- # Get and display assistant response
201
- with st.chat_message("assistant"):
202
- message_placeholder = st.empty()
203
- full_response = ""
204
-
205
- try:
206
- # Get response from query engine
207
- response = query_engine.query(prompt)
208
- full_response = str(response)
209
- message_placeholder.markdown(full_response)
210
- except Exception as e:
211
- error_msg = f"Error generating response: {str(e)}"
212
- message_placeholder.error(error_msg)
213
- full_response = error_msg
214
-
215
- # Add assistant response to chat history
216
- st.session_state.messages.append({"role": "assistant", "content": full_response})
217
-
218
- def show_login_form():
219
- """Display the beautiful login form"""
220
- st.markdown(
221
- """
222
- <style>
223
- .main {
224
- background-color: #1a1a2e;
225
- color: white;
226
- }
227
- .stTextInput > div > div > input {
228
- background-color: #2a2a3e;
229
- color: white;
230
- border: 1px solid #4a4a6a;
231
- border-radius: 8px;
232
- }
233
- .stTextInput > div > div > input::placeholder {
234
- color: #a0a0b0 !important;
235
- opacity: 1 !important;
236
- }
237
- .stButton > button {
238
- background-color: #e94560;
239
- color: white;
240
- border: none;
241
- border-radius: 8px;
242
- padding: 10px 20px;
243
- font-size: 16px;
244
- width: 100%;
245
- }
246
- .stButton > button:hover {
247
- background-color: #d83450;
248
- }
249
- h1, h2, h3, h4, h5, h6 {
250
- color: white;
251
- }
252
- .st-emotion-cache-1r6slb0 {
253
- border: 1px solid #4a4a6a;
254
- border-radius: 12px;
255
- padding: 2rem;
256
- background-color: #232339;
257
- }
258
- </style>
259
- """,
260
- unsafe_allow_html=True
261
- )
262
- st.markdown('<div style="text-align: center; margin-top: -80px; margin-bottom: 30px;"><h1 style="font-size: 3rem;">🔒</h1></div>', unsafe_allow_html=True)
263
- st.markdown('<h1 style="text-align: center; margin-bottom: 20px;">Department Portal</h1>', unsafe_allow_html=True)
264
- st.markdown('<p style="text-align: center; color: #a0a0b0; margin-bottom: 30px;">Sign in to access your department\'s knowledge base</p>', unsafe_allow_html=True)
265
-
266
- with st.container():
267
- with st.form("login_form", border=True):
268
- username = st.text_input("Username", placeholder="Enter your username")
269
- password = st.text_input("Password", type="password", placeholder="Enter your password")
270
- login_button = st.form_submit_button("Sign In")
271
-
272
- if login_button:
273
- if not username or not password:
274
- st.error("Please enter both username and password")
275
- elif login(username, password):
276
- st.success(f"Welcome, {username}! Redirecting...")
277
- else:
278
- st.error("Invalid username or password")
279
-
280
- with st.expander("Need demo credentials?"):
281
- st.markdown("""
282
- - **Engineering:** `Tony` / `password123`
283
- - **Marketing:** `Bruce` / `securepass`
284
- - **Finance:** `Sam` / `financepass`
285
- - **HR:** `Natasha` / `hrpass123`
286
- """)
287
-
288
- st.markdown('<p style="text-align: center; margin-top: 2rem; color: #a0a0b0;">2025 Department RAG System</p>', unsafe_allow_html=True)
289
-
290
-
291
- def main():
292
- """
293
- Main application entry point
294
- Handles routing between login and main application
295
- """
296
- # Sidebar for logout and user info
297
- if st.session_state.authenticated:
298
- st.set_page_config(layout="wide", initial_sidebar_state="expanded")
299
- with st.sidebar:
300
- st.markdown(f"### Welcome, {st.session_state.username}")
301
- st.markdown(f"**Role:** {st.session_state.role.capitalize()}")
302
-
303
- if st.button("Logout", key="logout_btn"):
304
- logout()
305
- return
306
-
307
- st.markdown("---")
308
- st.markdown("### About")
309
- st.markdown("""
310
- This is a secure departmental RAG system that provides
311
- role-based access to information across different departments.
312
- """)
313
-
314
- # Main content area
315
- if not st.session_state.authenticated:
316
- show_login_form()
317
- else:
318
- chat_interface()
319
-
320
- if __name__ == "__main__":
321
- main()
 
 
 
 
 
 
 
 
1
+ __import__('pysqlite3')
2
+ import sys
3
+ sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')
4
+
5
+ import sqlite3
6
+
7
+ import os
8
+ import streamlit as st
9
+ import chromadb
10
+ from typing import Dict, Optional, Any
11
+ from pathlib import Path
12
+ from dotenv import load_dotenv
13
+ from llama_index.core import VectorStoreIndex, StorageContext, Settings
14
+ from llama_index.vector_stores.chroma import ChromaVectorStore
15
+ from llama_index.llms.groq import Groq
16
+ from llama_index.embeddings.cohere import CohereEmbedding
17
+
18
+
19
+ from arize.otel import register
20
+ from openinference.instrumentation.llama_index import LlamaIndexInstrumentor
21
+
22
+ # Setup OTel via Arize's convenience function
23
+ tracer_provider = register(
24
+ space_id=os.getenv("ARIZE_SPACE_ID"),
25
+ api_key=os.getenv("ARIZE_API_KEY"),
26
+ project_name="rbacrag" # Choose a project name
27
+ )
28
+
29
+ # Instrument LlamaIndex
30
+ LlamaIndexInstrumentor().instrument(tracer_provider=tracer_provider)
31
+
32
+ # Import database module
33
+ from database import db, initialize_users
34
+
35
+ # Load environment variables
36
+ load_dotenv()
37
+
38
+ # Initialize default users
39
+ initialize_users()
40
+
41
+ # Role-based access control for documents
42
+ ROLE_ACCESS = {
43
+ "hr": ["hr", "general"],
44
+ "engineering": ["engineering", "general"],
45
+ "finance": ["finance", "general"],
46
+ "marketing": ["marketing", "general"]
47
+ }
48
+
49
+ # Initialize session state
50
+ def initialize_session_state():
51
+ """Initialize or reset the session state"""
52
+ if "authenticated" not in st.session_state:
53
+ st.session_state.authenticated = False
54
+ if "username" not in st.session_state:
55
+ st.session_state.username = None
56
+ if "role" not in st.session_state:
57
+ st.session_state.role = None
58
+ if "messages" not in st.session_state:
59
+ st.session_state.messages = []
60
+ if "vector_index" not in st.session_state:
61
+ st.session_state.vector_index = None
62
+ if "query_engine" not in st.session_state:
63
+ st.session_state.query_engine = None
64
+
65
+ # Set page config
66
+ st.set_page_config(
67
+ page_title="Departmental RAG System",
68
+ page_icon="🔒",
69
+ layout="centered",
70
+ initial_sidebar_state="collapsed"
71
+ )
72
+
73
+ # Initialize session state
74
+ initialize_session_state()
75
+
76
+ # Authentication functions
77
+ def login(username: str, password: str) -> bool:
78
+ """
79
+ Authenticate user and set session state
80
+
81
+ Args:
82
+ username: The username to authenticate
83
+ password: The password to verify
84
+
85
+ Returns:
86
+ bool: True if authentication was successful, False otherwise
87
+ """
88
+ try:
89
+ user = db.verify_user(username, password)
90
+ if user:
91
+ st.session_state.authenticated = True
92
+ st.session_state.username = user["username"]
93
+ st.session_state.role = user["role"]
94
+ st.session_state.messages = [
95
+ {"role": "assistant", "content": f"Welcome, {user['username']}! How can I assist you today?"}
96
+ ]
97
+ st.rerun() # Rerun to update the UI
98
+ return True
99
+ return False
100
+ except Exception as e:
101
+ st.error(f"An error occurred during login: {str(e)}")
102
+ return False
103
+
104
+ def logout():
105
+ """
106
+ Log out the current user and clear session state
107
+ """
108
+ username = st.session_state.get('username', 'Unknown')
109
+ st.session_state.clear()
110
+ initialize_session_state()
111
+ st.success(f"Successfully logged out {username}")
112
+ st.rerun() # Rerun to update the UI
113
+
114
+ @st.cache_resource
115
+ def load_vector_index(role: str):
116
+ """Load the ChromaDB index for the user's role"""
117
+ try:
118
+ # Initialize Cohere embeddings
119
+ cohere_api_key = os.getenv("COHERE_API_KEY")
120
+ if not cohere_api_key:
121
+ raise ValueError("COHERE_API_KEY not found in environment variables")
122
+
123
+ embed_model = CohereEmbedding(
124
+ cohere_api_key=cohere_api_key,
125
+ model_name="embed-english-v3.0",
126
+ input_type="search_document"
127
+ )
128
+ Settings.embed_model = embed_model
129
+
130
+ # Detect read-only filesystem (e.g., Vercel) and use /tmp
131
+ if os.getenv("VERCEL") or os.access(".", os.W_OK) is False:
132
+ persist_dir = os.path.join("/tmp", "chroma_db", role)
133
+ else:
134
+ persist_dir = os.path.join("chroma_db", role)
135
+
136
+ os.makedirs(persist_dir, exist_ok=True)
137
+
138
+ # Initialize Chroma client
139
+ chroma_client = chromadb.PersistentClient(path=persist_dir)
140
+
141
+ # Get the collection
142
+ chroma_collection = chroma_client.get_collection("documents")
143
+
144
+ # Create vector store
145
+ vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
146
+
147
+ # Create storage context
148
+ storage_context = StorageContext.from_defaults(vector_store=vector_store)
149
+
150
+ # Load the index
151
+ index = VectorStoreIndex.from_vector_store(
152
+ vector_store=vector_store,
153
+ storage_context=storage_context,
154
+ embed_model=embed_model
155
+ )
156
+
157
+ return index
158
+
159
+ except Exception as e:
160
+ st.error(f"Error loading vector index: {str(e)}")
161
+ st.stop()
162
+ def chat_interface():
163
+ """Main chat interface"""
164
+ # Add styled heading
165
+ st.markdown(f"<h2 style='color: #1407fa;'>💬 {st.session_state.role.capitalize()} Department Chat</h3>", unsafe_allow_html=True)
166
+
167
+ # Display chat messages
168
+ for message in st.session_state.messages:
169
+ with st.chat_message(message["role"]):
170
+ st.markdown(message["content"])
171
+
172
+ # Load the appropriate index for the user's role
173
+ index = load_vector_index(st.session_state.role)
174
+
175
+ # Initialize Groq LLM
176
+ try:
177
+ llm = Groq(
178
+ model="llama3-8b-8192",
179
+ api_key=os.getenv("GROQ_API_KEY"),
180
+ temperature=0.5,
181
+ system_prompt=f"You are a helpful assistant specialized in {st.session_state.role} department documents. Answer the user queries with the help of the provided context with high accuracy and precision."
182
+ )
183
+
184
+ # Create query engine with the LLM
185
+ query_engine = index.as_query_engine(
186
+ llm=llm,
187
+ similarity_top_k=3,
188
+ response_mode="compact"
189
+ )
190
+ except Exception as e:
191
+ st.error(f"Error initializing LLM: {str(e)}")
192
+ st.warning("Falling back to default LLM settings. Some features may be limited.")
193
+ query_engine = index.as_query_engine(
194
+ similarity_top_k=3,
195
+ response_mode="compact"
196
+ )
197
+
198
+ # Chat input
199
+ if prompt := st.chat_input(f"Ask about {st.session_state.role} documents..."):
200
+ # Add user message to chat history
201
+ st.session_state.messages.append({"role": "user", "content": prompt})
202
+
203
+ # Display user message
204
+ with st.chat_message("user"):
205
+ st.markdown(prompt)
206
+
207
+ # Get and display assistant response
208
+ with st.chat_message("assistant"):
209
+ message_placeholder = st.empty()
210
+ full_response = ""
211
+
212
+ try:
213
+ # Get response from query engine
214
+ response = query_engine.query(prompt)
215
+ full_response = str(response)
216
+ message_placeholder.markdown(full_response)
217
+ except Exception as e:
218
+ error_msg = f"Error generating response: {str(e)}"
219
+ message_placeholder.error(error_msg)
220
+ full_response = error_msg
221
+
222
+ # Add assistant response to chat history
223
+ st.session_state.messages.append({"role": "assistant", "content": full_response})
224
+
225
+ def show_login_form():
226
+ """Display the beautiful login form"""
227
+ st.markdown(
228
+ """
229
+ <style>
230
+ .main {
231
+ background-color: #1a1a2e;
232
+ color: white;
233
+ }
234
+ .stTextInput > div > div > input {
235
+ background-color: #2a2a3e;
236
+ color: white;
237
+ border: 1px solid #4a4a6a;
238
+ border-radius: 8px;
239
+ }
240
+ .stTextInput > div > div > input::placeholder {
241
+ color: #a0a0b0 !important;
242
+ opacity: 1 !important;
243
+ }
244
+ .stButton > button {
245
+ background-color: #e94560;
246
+ color: white;
247
+ border: none;
248
+ border-radius: 8px;
249
+ padding: 10px 20px;
250
+ font-size: 16px;
251
+ width: 100%;
252
+ }
253
+ .stButton > button:hover {
254
+ background-color: #d83450;
255
+ }
256
+ h1, h2, h3, h4, h5, h6 {
257
+ color: white;
258
+ }
259
+ .st-emotion-cache-1r6slb0 {
260
+ border: 1px solid #4a4a6a;
261
+ border-radius: 12px;
262
+ padding: 2rem;
263
+ background-color: #232339;
264
+ }
265
+ </style>
266
+ """,
267
+ unsafe_allow_html=True
268
+ )
269
+ st.markdown('<div style="text-align: center; margin-top: -80px; margin-bottom: 30px;"><h1 style="font-size: 3rem;">🔒</h1></div>', unsafe_allow_html=True)
270
+ st.markdown('<h1 style="text-align: center; margin-bottom: 20px;">Department Portal</h1>', unsafe_allow_html=True)
271
+ st.markdown('<p style="text-align: center; color: #a0a0b0; margin-bottom: 30px;">Sign in to access your department\'s knowledge base</p>', unsafe_allow_html=True)
272
+
273
+ with st.container():
274
+ with st.form("login_form", border=True):
275
+ username = st.text_input("Username", placeholder="Enter your username")
276
+ password = st.text_input("Password", type="password", placeholder="Enter your password")
277
+ login_button = st.form_submit_button("Sign In")
278
+
279
+ if login_button:
280
+ if not username or not password:
281
+ st.error("Please enter both username and password")
282
+ elif login(username, password):
283
+ st.success(f"Welcome, {username}! Redirecting...")
284
+ else:
285
+ st.error("Invalid username or password")
286
+
287
+ with st.expander("Need demo credentials?"):
288
+ st.markdown("""
289
+ - **Engineering:** `Tony` / `password123`
290
+ - **Marketing:** `Bruce` / `securepass`
291
+ - **Finance:** `Sam` / `financepass`
292
+ - **HR:** `Natasha` / `hrpass123`
293
+ """)
294
+
295
+ st.markdown('<p style="text-align: center; margin-top: 2rem; color: #a0a0b0;">2025 Department RAG System</p>', unsafe_allow_html=True)
296
+
297
+
298
+ def main():
299
+ """
300
+ Main application entry point
301
+ Handles routing between login and main application
302
+ """
303
+ # Sidebar for logout and user info
304
+ if st.session_state.authenticated:
305
+ st.set_page_config(layout="wide", initial_sidebar_state="expanded")
306
+ with st.sidebar:
307
+ st.markdown(f"### Welcome, {st.session_state.username}")
308
+ st.markdown(f"**Role:** {st.session_state.role.capitalize()}")
309
+
310
+ if st.button("Logout", key="logout_btn"):
311
+ logout()
312
+ return
313
+
314
+ st.markdown("---")
315
+ st.markdown("### About")
316
+ st.markdown("""
317
+ This is a secure departmental RAG system that provides
318
+ role-based access to information across different departments.
319
+ """)
320
+
321
+ # Main content area
322
+ if not st.session_state.authenticated:
323
+ show_login_form()
324
+ else:
325
+ chat_interface()
326
+
327
+ if __name__ == "__main__":
328
+ main()