Johan713 commited on
Commit
600acaa
Β·
verified Β·
1 Parent(s): 33dcba3

Upload 18 files

Browse files
pages/__pycache__/ai_buddy.cpython-311.pyc ADDED
Binary file (24.7 kB). View file
 
pages/__pycache__/chatbot.cpython-311.pyc ADDED
Binary file (25.4 kB). View file
 
pages/__pycache__/meditation.cpython-311.pyc ADDED
Binary file (9.58 kB). View file
 
pages/__pycache__/mind_palace.cpython-311.pyc ADDED
Binary file (20.5 kB). View file
 
pages/__pycache__/mnemonics_generation.cpython-311.pyc ADDED
Binary file (15.6 kB). View file
 
pages/__pycache__/notes_generation.cpython-311.pyc ADDED
Binary file (12.8 kB). View file
 
pages/__pycache__/sherlock_observation.cpython-311.pyc ADDED
Binary file (10.5 kB). View file
 
pages/__pycache__/study_roadmap.cpython-311.pyc ADDED
Binary file (28.1 kB). View file
 
pages/ai_buddy.py ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import random
3
+ from langchain.chat_models import ChatOpenAI
4
+ from langchain.schema import HumanMessage, SystemMessage
5
+ import os
6
+ from dotenv import load_dotenv
7
+ import pandas as pd
8
+ from datetime import datetime
9
+ import plotly.express as px
10
+ import json
11
+ import speech_recognition as sr
12
+ from gtts import gTTS
13
+ import pygame
14
+ from io import BytesIO
15
+
16
+ # Load environment variables
17
+ load_dotenv()
18
+
19
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
20
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
21
+
22
+ # Initialize the Falcon model
23
+ chat = ChatOpenAI(
24
+ model="tiiuae/falcon-180B-chat",
25
+ api_key=AI71_API_KEY,
26
+ base_url=AI71_BASE_URL,
27
+ streaming=True,
28
+ )
29
+
30
+ # Expanded Therapy techniques
31
+ THERAPY_TECHNIQUES = {
32
+ "CBT": "Use Cognitive Behavioral Therapy techniques to help the user identify and change negative thought patterns.",
33
+ "Mindfulness": "Guide the user through mindfulness exercises to promote present-moment awareness and reduce stress.",
34
+ "Solution-Focused": "Focus on the user's strengths and resources to help them find solutions to their problems.",
35
+ "Emotion-Focused": "Help the user identify, experience, and regulate their emotions more effectively.",
36
+ "Psychodynamic": "Explore the user's past experiences and unconscious patterns to gain insight into current issues.",
37
+ "ACT": "Use Acceptance and Commitment Therapy to help the user accept their thoughts and feelings while committing to positive changes.",
38
+ "DBT": "Apply Dialectical Behavior Therapy techniques to help the user manage intense emotions and improve relationships.",
39
+ "Gestalt": "Use Gestalt therapy techniques to focus on the present moment and increase self-awareness.",
40
+ "Existential": "Explore existential themes such as meaning, freedom, and responsibility to help the user find purpose.",
41
+ "Narrative": "Use storytelling and narrative techniques to help the user reframe their life experiences and create new meaning.",
42
+ }
43
+
44
+ def get_ai_response(user_input, buddy_config, therapy_technique=None):
45
+ system_message = f"You are {buddy_config['name']}, an AI companion with the following personality: {buddy_config['personality']}. "
46
+ system_message += f"Additional details about you: {buddy_config['details']}. "
47
+
48
+ if therapy_technique:
49
+ system_message += f"In this conversation, {THERAPY_TECHNIQUES[therapy_technique]}"
50
+
51
+ messages = [
52
+ SystemMessage(content=system_message),
53
+ HumanMessage(content=user_input)
54
+ ]
55
+ response = chat.invoke(messages).content
56
+ return response
57
+
58
+ def show_progress_dashboard():
59
+ st.subheader("Your Progress Dashboard")
60
+
61
+ # Placeholder data for demonstration
62
+ mood_logs = [{"date": "2023-08-01", "mood": 7}, {"date": "2023-08-02", "mood": 8}, {"date": "2023-08-03", "mood": 6}]
63
+
64
+ # Mood trend
65
+ if mood_logs:
66
+ df = pd.DataFrame(mood_logs)
67
+ fig = px.line(df, x="date", y="mood", title="Mood Trend")
68
+ st.plotly_chart(fig)
69
+ else:
70
+ st.info("No mood data available yet. Start logging your mood!")
71
+
72
+ # Journal entries
73
+ st.subheader("Recent Journal Entries")
74
+ journal_entries = [
75
+ {"date": "2023-08-03", "entry": "Had a productive day at work..."},
76
+ {"date": "2023-08-02", "entry": "Feeling a bit stressed about..."},
77
+ {"date": "2023-08-01", "entry": "Started a new book today..."}
78
+ ]
79
+ for entry in journal_entries[-5:]:
80
+ st.text(f"{entry['date']}: {entry['entry'][:50]}...")
81
+
82
+ # Goals progress
83
+ st.subheader("Goals Progress")
84
+ goals = [
85
+ {"description": "Exercise 3 times a week", "progress": 60},
86
+ {"description": "Read 2 books this month", "progress": 75},
87
+ {"description": "Learn Python programming", "progress": 40}
88
+ ]
89
+ for goal in goals:
90
+ st.progress(goal['progress'])
91
+ st.text(f"{goal['description']}: {goal['progress']}% complete")
92
+
93
+ def show_goal_setting_interface():
94
+ st.subheader("Set Your Goals")
95
+ goal_description = st.text_input("Describe your goal")
96
+ goal_progress = st.slider("Initial progress", 0, 100, 0)
97
+
98
+ if st.button("Add Goal"):
99
+ st.success("Goal added successfully!")
100
+
101
+ def show_meditation_timer():
102
+ st.subheader("Meditation Timer")
103
+ duration = st.slider("Select duration (minutes)", 1, 60, 5)
104
+ if st.button("Start Meditation"):
105
+ progress_bar = st.progress(0)
106
+ for i in range(duration * 60):
107
+ progress_bar.progress((i + 1) / (duration * 60))
108
+ st.empty().text(f"Time remaining: {duration - (i // 60)}:{59 - (i % 60):02d}")
109
+ time.sleep(1)
110
+ st.success("Meditation complete!")
111
+
112
+ def show_community_forum():
113
+ st.subheader("Community Forum")
114
+ st.warning("This feature is not yet implemented. Check back soon!")
115
+
116
+ def show_personalized_recommendations():
117
+ st.subheader("Personalized Recommendations")
118
+
119
+ # Placeholder for demonstration
120
+ avg_mood = 6
121
+
122
+ if avg_mood < 4:
123
+ st.markdown("Based on your recent mood, we recommend:")
124
+ st.markdown("- Practice daily gratitude journaling")
125
+ st.markdown("- Try a guided meditation for stress relief")
126
+ st.markdown("- Read 'The Happiness Trap' by Russ Harris")
127
+ elif avg_mood < 7:
128
+ st.markdown("To maintain and improve your mood, consider:")
129
+ st.markdown("- Start a new hobby or learn a new skill")
130
+ st.markdown("- Practice mindfulness meditation")
131
+ st.markdown("- Read 'Atomic Habits' by James Clear")
132
+ else:
133
+ st.markdown("Great job maintaining a positive mood! To keep it up:")
134
+ st.markdown("- Share your positivity with others")
135
+ st.markdown("- Set ambitious goals for personal growth")
136
+ st.markdown("- Read 'Flow' by Mihaly Csikszentmihalyi")
137
+
138
+ def start_voice_interaction():
139
+ st.subheader("Voice Interaction")
140
+ if st.button("Start Voice Recognition"):
141
+ r = sr.Recognizer()
142
+ with sr.Microphone() as source:
143
+ st.info("Listening... Speak now!")
144
+ audio = r.listen(source)
145
+ try:
146
+ text = r.recognize_google(audio)
147
+ st.success(f"You said: {text}")
148
+
149
+ # Get AI response
150
+ buddy_config = {
151
+ "name": st.session_state.buddy_name,
152
+ "personality": st.session_state.buddy_personality,
153
+ "details": st.session_state.buddy_details
154
+ }
155
+ response = get_ai_response(text, buddy_config)
156
+
157
+ # Convert response to speech
158
+ tts = gTTS(text=response, lang='en')
159
+ fp = BytesIO()
160
+ tts.write_to_fp(fp)
161
+ fp.seek(0)
162
+
163
+ # Play the response
164
+ pygame.mixer.init()
165
+ pygame.mixer.music.load(fp)
166
+ pygame.mixer.music.play()
167
+ while pygame.mixer.music.get_busy():
168
+ pygame.time.Clock().tick(10)
169
+
170
+ st.success(f"AI response: {response}")
171
+ except sr.UnknownValueError:
172
+ st.error("Sorry, I couldn't understand what you said.")
173
+ except sr.RequestError as e:
174
+ st.error(f"Could not request results; {e}")
175
+
176
+ def show_daily_challenge():
177
+ st.subheader("Daily Personal Growth Challenge")
178
+ challenges = [
179
+ "Write down three things you're grateful for today.",
180
+ "Reach out to a friend or family member you haven't spoken to in a while.",
181
+ "Try a new healthy recipe for dinner tonight.",
182
+ "Take a 15-minute walk in nature and practice mindfulness.",
183
+ "Learn five new words in a language you're interested in.",
184
+ "Declutter one area of your living space.",
185
+ "Practice active listening in your next conversation.",
186
+ "Try a new form of exercise or physical activity.",
187
+ "Write a short story or poem expressing your current emotions.",
188
+ "Perform a random act of kindness for someone."
189
+ ]
190
+
191
+ if 'daily_challenge' not in st.session_state:
192
+ st.session_state.daily_challenge = random.choice(challenges)
193
+
194
+ st.info(f"Your challenge for today: {st.session_state.daily_challenge}")
195
+
196
+ if st.button("Complete Challenge"):
197
+ st.success("Great job completing today's challenge! Keep up the good work.")
198
+ st.session_state.daily_challenge = random.choice(challenges)
199
+
200
+ def show_therapist_scheduling_interface():
201
+ st.subheader("Schedule a Video Therapy Session")
202
+ st.warning("This feature would integrate with a real therapist booking system. For demonstration purposes, we'll use a simplified version.")
203
+
204
+ therapists = ["Dr. Smith", "Dr. Johnson", "Dr. Williams", "Dr. Brown"]
205
+ selected_therapist = st.selectbox("Choose a therapist", therapists)
206
+
207
+ date = st.date_input("Select a date")
208
+ time = st.time_input("Select a time")
209
+
210
+ if st.button("Schedule Session"):
211
+ st.success(f"Session scheduled with {selected_therapist} on {date} at {time}. You will receive a confirmation email with further details.")
212
+
213
+ def main():
214
+ st.set_page_config(page_title="S.H.E.R.L.O.C.K. AI Buddy", page_icon="πŸ•΅οΈ", layout="wide")
215
+
216
+ # Custom CSS for improved styling
217
+ st.markdown("""
218
+ <style>
219
+ .stApp {
220
+ background-color: #f0f2f6;
221
+ }
222
+ .stButton>button {
223
+ background-color: #4CAF50;
224
+ color: white;
225
+ font-weight: bold;
226
+ }
227
+ .stTextInput>div>div>input {
228
+ background-color: #ffffff;
229
+ }
230
+ </style>
231
+ """, unsafe_allow_html=True)
232
+
233
+ st.title("πŸ•΅οΈ S.H.E.R.L.O.C.K. AI Buddy")
234
+ st.markdown("Your personalized AI companion for conversation, therapy, and personal growth.")
235
+
236
+ # Initialize session state
237
+ if 'buddy_name' not in st.session_state:
238
+ st.session_state.buddy_name = "Sherlock"
239
+ if 'buddy_personality' not in st.session_state:
240
+ st.session_state.buddy_personality = "Friendly, empathetic, and insightful"
241
+ if 'buddy_details' not in st.session_state:
242
+ st.session_state.buddy_details = "Knowledgeable about various therapy techniques and always ready to listen"
243
+ if 'messages' not in st.session_state:
244
+ st.session_state.messages = []
245
+
246
+ # Sidebar for AI Buddy configuration
247
+ with st.sidebar:
248
+ st.header("πŸ€– Configure Your AI Buddy")
249
+ st.session_state.buddy_name = st.text_input("Name your AI Buddy", value=st.session_state.buddy_name)
250
+ st.session_state.buddy_personality = st.text_area("Describe your buddy's personality", value=st.session_state.buddy_personality)
251
+ st.session_state.buddy_details = st.text_area("Additional details about your buddy", value=st.session_state.buddy_details)
252
+
253
+ st.header("🧘 Therapy Session")
254
+ therapy_mode = st.checkbox("Enable Therapy Mode")
255
+ if therapy_mode:
256
+ therapy_technique = st.selectbox("Select Therapy Technique", list(THERAPY_TECHNIQUES.keys()))
257
+ else:
258
+ therapy_technique = None
259
+
260
+ st.markdown("---")
261
+ st.markdown("Powered by Falcon-180B and Streamlit")
262
+
263
+ # Main content area
264
+ tab1, tab2, tab3, tab4, tab5 = st.tabs(["Chat", "Progress", "Goals", "Community", "Tools"])
265
+
266
+ with tab1:
267
+ # Chat interface
268
+ st.header("πŸ—¨οΈ Chat with Your AI Buddy")
269
+ chat_container = st.container()
270
+ with chat_container:
271
+ for message in st.session_state.messages[-5:]: # Display last 5 messages
272
+ with st.chat_message(message["role"]):
273
+ st.markdown(message["content"])
274
+
275
+ # User input
276
+ if prompt := st.chat_input("What's on your mind?"):
277
+ st.session_state.messages.append({"role": "user", "content": prompt})
278
+ with st.chat_message("user"):
279
+ st.markdown(prompt)
280
+
281
+ buddy_config = {
282
+ "name": st.session_state.buddy_name,
283
+ "personality": st.session_state.buddy_personality,
284
+ "details": st.session_state.buddy_details
285
+ }
286
+
287
+ with st.chat_message("assistant"):
288
+ message_placeholder = st.empty()
289
+ full_response = ""
290
+ for chunk in chat.stream(get_ai_response(prompt, buddy_config, therapy_technique)):
291
+ full_response += chunk.content
292
+ message_placeholder.markdown(full_response + "β–Œ")
293
+ message_placeholder.markdown(full_response)
294
+ st.session_state.messages.append({"role": "assistant", "content": full_response})
295
+
296
+ with tab2:
297
+ show_progress_dashboard()
298
+
299
+ with tab3:
300
+ show_goal_setting_interface()
301
+
302
+ with tab4:
303
+ show_community_forum()
304
+
305
+ with tab5:
306
+ tool_choice = st.selectbox("Select a tool", ["Meditation Timer", "Recommendations", "Voice Interaction", "Daily Challenge", "Schedule Therapy"])
307
+ if tool_choice == "Meditation Timer":
308
+ show_meditation_timer()
309
+ elif tool_choice == "Recommendations":
310
+ show_personalized_recommendations()
311
+ elif tool_choice == "Voice Interaction":
312
+ start_voice_interaction()
313
+ elif tool_choice == "Daily Challenge":
314
+ show_daily_challenge()
315
+ elif tool_choice == "Schedule Therapy":
316
+ show_therapist_scheduling_interface()
317
+
318
+ # Mood tracker
319
+ st.sidebar.markdown("---")
320
+ st.sidebar.header("😊 Mood Tracker")
321
+ mood = st.sidebar.slider("How are you feeling today?", 1, 10, 5)
322
+ if st.sidebar.button("Log Mood"):
323
+ st.sidebar.success(f"Mood logged: {mood}/10")
324
+ st.balloons()
325
+
326
+ # Journaling feature
327
+ st.sidebar.markdown("---")
328
+ st.sidebar.header("πŸ“” Daily Journal")
329
+ journal_entry = st.sidebar.text_area("Write your thoughts for today")
330
+ if st.sidebar.button("Save Journal Entry"):
331
+ st.sidebar.success("Journal entry saved!")
332
+ st.toast("Journal entry saved successfully!", icon="βœ…")
333
+
334
+ # Resources and Emergency Contact
335
+ st.sidebar.markdown("---")
336
+ st.sidebar.header("πŸ†˜ Resources")
337
+ st.sidebar.info("If you're in crisis, please reach out for help:")
338
+ st.sidebar.markdown("- [Mental Health Resources](https://www.mentalhealth.gov/get-help/immediate-help)")
339
+ st.sidebar.markdown("- Emergency Contact: 911 or your local emergency number")
340
+
341
+ # Inspiration Quote
342
+ st.sidebar.markdown("---")
343
+ st.sidebar.header("πŸ’‘ Daily Inspiration")
344
+ if st.sidebar.button("Get Inspirational Quote"):
345
+ quotes = [
346
+ "The only way to do great work is to love what you do. - Steve Jobs",
347
+ "Believe you can and you're halfway there. - Theodore Roosevelt",
348
+ "The future belongs to those who believe in the beauty of their dreams. - Eleanor Roosevelt",
349
+ "Strive not to be a success, but rather to be of value. - Albert Einstein",
350
+ "The only limit to our realization of tomorrow will be our doubts of today. - Franklin D. Roosevelt"
351
+ ]
352
+ random_quote = random.choice(quotes)
353
+ st.sidebar.success(random_quote)
354
+
355
+ # Chat Export
356
+ st.sidebar.markdown("---")
357
+ if st.sidebar.button("Export Chat History"):
358
+ chat_history = "\n".join([f"{msg['role']}: {msg['content']}" for msg in st.session_state.messages])
359
+ st.sidebar.download_button(
360
+ label="Download Chat History",
361
+ data=chat_history,
362
+ file_name="ai_buddy_chat_history.txt",
363
+ mime="text/plain"
364
+ )
365
+ st.sidebar.success("Chat history ready for download!")
366
+
367
+ if __name__ == "__main__":
368
+ main()
pages/chatbot.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import random
3
+ from langchain.chat_models import ChatOpenAI
4
+ from langchain.schema import HumanMessage, SystemMessage
5
+ from langchain.document_loaders import TextLoader
6
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
+ from langchain.embeddings import HuggingFaceEmbeddings
8
+ from langchain_community.vectorstores import FAISS
9
+ from langchain.chains import RetrievalQA
10
+ import os
11
+ from dotenv import load_dotenv
12
+ import requests
13
+ from bs4 import BeautifulSoup
14
+ import pandas as pd
15
+ from googleapiclient.discovery import build
16
+ from googleapiclient.errors import HttpError
17
+ import time
18
+ from langchain.schema import Document
19
+ from docx import Document as DocxDocument
20
+ from PyPDF2 import PdfReader
21
+ import io
22
+
23
+ # Load environment variables
24
+ load_dotenv()
25
+
26
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
27
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
28
+
29
+ # Initialize session state variables
30
+ if "custom_personality" not in st.session_state:
31
+ st.session_state.custom_personality = ""
32
+ if "messages" not in st.session_state:
33
+ st.session_state.messages = []
34
+
35
+ # Initialize the Falcon model
36
+ @st.cache_resource
37
+ def get_llm():
38
+ return ChatOpenAI(
39
+ model="tiiuae/falcon-180B-chat",
40
+ api_key=AI71_API_KEY,
41
+ base_url=AI71_BASE_URL,
42
+ streaming=True,
43
+ )
44
+
45
+ # Initialize embeddings
46
+ @st.cache_resource
47
+ def get_embeddings():
48
+ return HuggingFaceEmbeddings()
49
+
50
+ def process_documents(uploaded_files):
51
+ documents = []
52
+ for uploaded_file in uploaded_files:
53
+ file_extension = os.path.splitext(uploaded_file.name)[1].lower()
54
+ try:
55
+ if file_extension in [".txt", ".md"]:
56
+ content = uploaded_file.getvalue().decode("utf-8")
57
+ documents.append(Document(page_content=content, metadata={"source": uploaded_file.name}))
58
+ elif file_extension == ".docx":
59
+ docx_file = io.BytesIO(uploaded_file.getvalue())
60
+ doc = DocxDocument(docx_file)
61
+ content = "\n".join([para.text for para in doc.paragraphs])
62
+ documents.append(Document(page_content=content, metadata={"source": uploaded_file.name}))
63
+ elif file_extension == ".pdf":
64
+ pdf_file = io.BytesIO(uploaded_file.getvalue())
65
+ pdf_reader = PdfReader(pdf_file)
66
+ content = ""
67
+ for page in pdf_reader.pages:
68
+ content += page.extract_text()
69
+ documents.append(Document(page_content=content, metadata={"source": uploaded_file.name}))
70
+ else:
71
+ st.warning(f"Unsupported file type: {file_extension}")
72
+ except Exception as e:
73
+ st.error(f"Error processing file {uploaded_file.name}: {str(e)}")
74
+
75
+ if not documents:
76
+ return None
77
+
78
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
79
+ texts = text_splitter.split_documents(documents)
80
+
81
+ vectorstore = FAISS.from_documents(texts, get_embeddings())
82
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
83
+
84
+ qa_chain = RetrievalQA.from_chain_type(
85
+ llm=get_llm(),
86
+ chain_type="stuff",
87
+ retriever=retriever,
88
+ return_source_documents=True,
89
+ )
90
+
91
+ return qa_chain
92
+
93
+ def get_chatbot_response(user_input, qa_chain=None, personality="default", web_search=False):
94
+ system_message = get_personality_prompt(personality)
95
+
96
+ web_info = ""
97
+ if web_search:
98
+ web_results = search_web_duckduckgo(user_input)
99
+ web_info = "\n\n".join([f"Title: {result['title']}\nLink: {result['link']}\nSnippet: {result['snippet']}" for result in web_results])
100
+ user_input += f"\n\nWeb search results:\n{web_info}"
101
+
102
+ if qa_chain:
103
+ result = qa_chain({"query": user_input})
104
+ response = result['result']
105
+ source_docs = result.get('source_documents', [])
106
+ else:
107
+ messages = [
108
+ SystemMessage(content=system_message),
109
+ HumanMessage(content=user_input)
110
+ ]
111
+ response = get_llm().invoke(messages).content
112
+ source_docs = []
113
+
114
+ return response, source_docs, web_results if web_search else None
115
+
116
+ def get_personality_prompt(personality):
117
+ personalities = {
118
+ "default": "You are a helpful assistant.",
119
+ "sherlock": "You are Sherlock Holmes, the world's greatest detective. Respond with keen observation and deductive reasoning.",
120
+ "yoda": "Wise and cryptic, you are. Like Yoda from Star Wars, speak you must.",
121
+ "shakespeare": "Thou art the Bard himself. In iambic pentameter, respond with eloquence and poetic flair.",
122
+ "custom": st.session_state.custom_personality
123
+ }
124
+ return personalities.get(personality, personalities["default"])
125
+
126
+ def search_web_duckduckgo(query: str, num_results: int = 3, max_retries: int = 3):
127
+ api_key = "AIzaSyD-1OMuZ0CxGAek0PaXrzHOmcDWFvZQtm8"
128
+ cse_id = "877170db56f5c4629"
129
+
130
+ for attempt in range(max_retries):
131
+ try:
132
+ service = build("customsearch", "v1", developerKey=api_key)
133
+ res = service.cse().list(q=query, cx=cse_id, num=num_results).execute()
134
+ results = []
135
+ if "items" in res:
136
+ for item in res["items"]:
137
+ result = {
138
+ "title": item["title"],
139
+ "link": item["link"],
140
+ "snippet": item.get("snippet", "")
141
+ }
142
+ results.append(result)
143
+ return results
144
+ except HttpError as e:
145
+ print(f"HTTP error occurred: {e}. Attempt {attempt + 1} of {max_retries}")
146
+ except Exception as e:
147
+ print(f"An unexpected error occurred: {e}. Attempt {attempt + 1} of {max_retries}")
148
+ time.sleep(2 ** attempt)
149
+ print("Max retries reached. No results found.")
150
+ return []
151
+
152
+ def main():
153
+ st.set_page_config(page_title="S.H.E.R.L.O.C.K. Chatbot", page_icon="πŸ•΅οΈ", layout="wide")
154
+
155
+ st.title("S.H.E.R.L.O.C.K. Chatbot")
156
+
157
+ # Sidebar
158
+ with st.sidebar:
159
+ st.image("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QEBUQEBAVFRUVFRYXFhcVFhUVFRUXFRUWFhUYGBYYHSggGBolGxcVITEhJSkrLi4uFx8zODYtNygtLisBCgoKDg0OGhAQGismHSUtLS0tLS0tLS0tLjArLS0rLS8vLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tKy0tLS0tK//AABEIALcBEwMBIgACEQEDEQH/xAAcAAABBQEBAQAAAAAAAAAAAAAAAQIDBAUGBwj/xABAEAABAwIDBQUFBgUDBAMAAAABAAIRAyEEEjEFQVFhcQYTIoGRMkKhscEHFCNSctEzYoKy8JKi4VNjc8IVJJP/xAAZAQADAQEBAAAAAAAAAAAAAAAAAQIDBAX/xAAtEQACAgEDBAEBBwUAAAAAAAAAAQIRAxIhMQRBUWETIjJxsdHh8PEFFCNikf/aAAwDAQACEQMRAD8A8gQhKukxESoQgAhCEIAEqEIAEJWtJsASeQlTswNZ2lJ5/pd+ydCK6FtN2EXYapWa4l1KC5uWBk3uDp1GpHAFYyGqBOwSpE5jCTABJOgFyegSGIpaFBzzDRPHcBzJNgOZVqjgmtvUMn8rSP8Ac7QdBJ/SVcD7AAAAaNFgOfM8zJ5qlGwI8PgqbLu8bv8AYPLV3nA5FXZJ1P8AwOAG4clCwKZqtKhFTbf8Ol+ur/bQUWxAczjBsBPK8SeCl23/AA6f66v9tBQ7EfleYMGLRrz+aUfthLg6RgcDTIN4sQYn8R8gHjfRPrFjnOD/AAGXXAtr7zd3VvoUwkHKCCDFyBA/iP8AaaNOo9EzE17vDhmEujiNdDw5GQt2ZRZo43EVGueyqGvGZ4aTfKcxnI8GQAfdmOIlUGlS42oW1aoa6QXvm387tQbTwKgaUkqNNVlzD0/ERIEB+vJrlbwLGBxFWm5wyOMsuWw10OEGHNBgnprrNGm8ZydxD/i1wHzVrZ20H0ScsEOa5pafZOZpb9fgm7rYEMmD4SbGx0PI8lZD2lozC8nxDXRuo37+CpzwUoJyjhJ9YbP09UxovtYW0ybFvHxEe0BedDY6QdVEGg6GDwP0P7/FSYKtkBdE2IIvcFzdZtv3cLqSq2i4ZmHKd4P7ft6JWVRBBFjZT92YkXHEfXgoXNI18t4PQpzDCLGkStUrUtE03WdLTucLt82/UehTqlFzLm4Ojhdp6H6apat6L09wQkQmFHjaVCFyGQIQhABCVCEAC0djbIfiXZWkNAjM4zYHfA1jVZy2djYeu2S0hoc286mQQCBusT6qoq2TK62NRuFZgnGn7VVpuYsOBAOtuNr2B1TnY+o7V7o4ZiqAoYh9YUiHPquIgTmc6RIud0eg4Qu52Ps7AYamKlUNr1MxaXOP4Ac0AuFNp/iBtvFGvDRaoznl0r36MXZfZuvjmltKi8tMkvaQweriGv8A0/LVGH7H0/x8PiWihVpsBY4ugEn2XSf4jD1t106LbHas1WdzRc5skZiyWANbcgEXvCXbG2D/APG0quIcC+niCxrnQahb3eaAdZ0vyBOkoa7syU5v0eUtwLmn8XwRu1eejfqYHCVYa8NEMGUHXe4/qdw5CByUdaqXvc86ucXHq4yfmnNWaR1WSMUzVGwKVqoRKwKVoUbFK1MaKe2x+HS/XV/toLJaYuCtfbn8Ol+ur/bQWQFk+SmauD2w5uUPkhuhGovP1PqtB1YPzOabGT6rm1JRquaZaY+R6jetY5PJDh4O2rmi+pUD5pu7x8OElh8Rs5uo6iddFTIgkawYtp5cll4XaTXWfY8dx893mtFpWip8EtlqlUEQ5sjiLOH7+flCk7q0tOYctR1G7rpzU+DxDe67upSm1QsdcXDS4j4buUqCm2TNMmeHveRHteV+SYJ2I0qxSrkDLYtmYOkmB1Gg0T/vFOp/Fbld+dgsT/OzTzEHkVHVolu8EHQtMgwAeu8agJJ9maUX2NDqZy21sTr4mzG7hwmRqq2inZkdTPumNY8J8Q4S718oCWjUyWqMD2kcbxxY8f8AI5JXRaQ2lUI6bxuPkpm5TpY8Dp5H9/VSfcQ8TQdn4sNqo8vf6t9AqrUKSfBWlonClaVA0qRpTGTITZQmB4+hCFyGIIQhAChCEIAVuq9CxmJod2DT91rHQTcHMGOETYEOH+gLzwCVpsxzw3K6DoOcDSdyuNCZ1+1K7WYem9kCpXz03PYIIpUzJY3SJc+535YWNTpHc4H4H0KtbaxDn08Jmv8A/Xzk8O8qOj4NCrUCtkc8FSLeEYRcq12sBGz8O25L69SpxMNYGT8UuzcI+q8NG8rfoPo4l7qTxk7lwpsdGWtSgjJUEkh7S4THNog6qcstMS4Q1zS/fo8uYpWhd52own3nMHUWDEsJZmpCDVe0xBE+IOEEbxmGtweHdTc0lrgWkGCCCCCNQQbgqS1fdUxzQpmqNgUzAgZI1SsUbQp6bCdEykZ+3v4dL9dX+2isdae2sSxwYxjg7KXkkaS8MEA74yai11lrJ8jY9ASBKgQqtYXGvp2FxwP04KoHDj/g1TgqTobVnT7M2oCTlNyCC12hlpGmjomVeo0w8wC1hO5xhun5jp5+q4sLSwe1XNs/xDj7w/daqfkjTR02JbUactQEOHEXI3X94cDfkm5zAG4En1gH5BJgdp5mZQRUZ+V3uzw3sPTXmiLTFiSBv0gx6EKlfce3Yu067C2HAydXCN1x4bT6gqUVHNDdHNAji10ucbg6HxEcbWWe1WWVyMpbYtaR1lznekOiEmi4stjI67Dkd+Um39L93Q+pT8TiXvgVLuHvEQ86RmO/zVY1Gu3ZTy9k+XunpbkE6nVtBuOB3dDu+SlLua2PaVK0puGoOqEhjSTBMb4HAbz0QFVhRNKE0ITGeRoQhcpzghCEACsChEF5yzcD3iOMbhzPlKrO0PQq9jzNap/5H/3FADAdzRHxJ8966HC9kMQQHPygb2gy+N40gHzWNgKdMmakkcGmCf6oMLrNm4DuMmMwZe6jmLcRScZLbEkzvsCRvkRvhRk1pfSb4Fjb+v8Aj37MXaOMqMLWvpAtYA0NdbIBoGPbDvUuE81s7MGCfT711Z1MAw5rruDomGua2X24CeS3ttbOwjnsrWqUz7TQSDEeLS+niHNsb1xlfDCmXU2OzNDjB3OvE9SAFfT5vkjqX/DPqun+LJp7c/ebGP7RNYzJg6bmXBNV1nGCD4W3MGNSdJEBaeOxQxBw+LaMhewsqnRssAIcTuA4ncBwWRtDGfeG02Npgd2HXi5zRYngI+JVHbtYNw1HDbw51Q/2j5u9FtJOjGD3TaOlr7Vp16uZr5ZNiBvDWtJte+UKDav3TFuHeOLKosHt8bnjc17d8bjIgW4Rx2EqugsBIvI6xBHmPkFcwFnibSD8kopaVFGkpXLWyGpRLHFpixi2h5hPYFLtHK12ZxABA84GWw1JssqvtI6U5aOPvn09nyvzSbolGjXxDKXtm/5R7Xnub534ArKxe0H1PD7LfyjTlmOrj18gFUQobsoEIQkIexpJAAJJIAAEkkmAAN5JXY9lKOz8K9lXaNM1ZuKYAcGc3MNnc58tFzew8R3ddr5gjNB4FzHNB+PkYKKtYueSTefluRLZG2KKfJ79gcIzaLs/eYPEbPygMo9we8Y7+aXeAi27yGq4r7QPsxZSpvxWzw6GAuqUCS4hupfTcbkC5ymbaaZVyvY/tJUwGIbVa7wEgVG7nNm8jeRqP+V6Jt6pWrPx2z6tV1XNQbi8G7wtOVviNMFoEgwW3kwLyslJmzxpnixw7w3MWmOMcePBMC3KVYHW8gg8wRBWIWkWIWmOerkyy4tFUPpVHNMtJB5Lawm2pAZUtBJzDiQ0GRu9kLDCVaptGNHY0HtMGZHIj4K45hIaWkOAbu1AzOPibqNddNLri8Lin0z4T1BuD5LdwG1KbyA7wnhMT0ctFKxo1TG74pzSrFBjC3xaS3xNALwPFMtm/wAOJTq+Ac1udpFSn+dlwJ/MNWHr8UOSTpmkVa2HYJjXGDUyH3SQcs8yLt6wVo1qhkNxTCSdKjYzEccw8NQdfULGaruFxr2DLZzDqx12ny3HmIKzlF8msWWfuYPs1qZG6SWnzaRZCYX0DeKjeQLSB0JukRcv2h7HjqEIWZxglSJUANfoehV3Hfxan/kf/cVTdoei1amGc6o9+U5e8eZ4+I258EDoTZ7SINwdea6vYWLM1mmwdSc525uendro059SszBYVpjPb5qvR2w/vRTYQKZe1ptJc0uuCTo2STAhXlVQpBha+RNnUbPk0abSIlrBHCQBCzcW2m94c2YLWSIiHZQHeUhLj9q5PCyQ+SNJiLE9Vm0sQ8kC3kCD6FYdJFx1OS5Ovr5wk4xi7pGrSgQNJMW5rB2/m+8vDhEQAL+yAMuvEX810WzsBWqPGUXF76N4F3ASqfbygKL6Fy6KLWZtM5YTMn+oLaeaOpROddPLQ59kc9TB6c9I89y7TbG2cPVouyvEio0Nc5pgSYLgNSMua68+fWLiJ0BmBop3Yy0AW+vPiOSiUIyab7BjyyhGUVwzR7XiiMRlovLgGAOJ4y4gC2mUhYiVziTJMk6pFTdsyWyBCEJDBCVCAA6LvcVsOlXY0s8JDQA4DcBoRvC4OF6v2YoMxeEbA9psGGg+NvhcYcIJzCbhZ5ZaVZ29HFSbTOB2ls12Ge0PMgiQYgW1Hlb1Xp+Bc/ucFjHgitTodyzK5ozMnLmfnEG8tDd9+S08f2Sw1TCFlTMDl9wCZF2hrQLutoF5ue39UYdtBuHbmptNNlR7iSGhxLc1GI7xsm8xyO8xNPcfUfQ9jLxlFtGtUogginUewdGuI+iVjwdQCN4NwscV3akyTckkkknUk71Yw2JF80RHqplifIQzR4ZW6JU1OC6TjHBOCYE8IGaGB2pUp2nM21ibiNIK6jZW2g45mPIdviz435m6PH+SuICewkGQYI3jVVfZlLY77E1g90hjW2vlkNJn2g33egskYCdFzWA20R4aokfmGvmN66PB4sEZmOBHI6fUFNV2NE7JJQmOeJSJlnlqEqRYHGCVCVADXaHousxUsc4OGh063HzC5N2i7ftGAWUakXLIPOGtI+ZSbVqLXJpCMqcovdGPicSDTcGyDF40IsCJ81FsBrPvDDUALQ5sg6eIhonoTPkoSPC7p/7NUeHNiNMwgdQQf3VuNqiIyqWo7TF0MPVcWYgFlRpguBgui0mZBBtqPNPoYLA4cZ34gvG5oIvHJpJPlC5urtbEFw8QLratDiToLEEHpC6HEPqVqXc1WsbiWtFVvdtDJDblj2i2fKMwjpvXJHFljs3t6O+fUYJO4xWr3+hNS2u51QMYCymXtBFgQHHKNNLkc+ay8ZjS+pXe6o0jvC0UXNLmva05egED16qPA4c942o9w8Lg4+RBsqW0fDiKo/7j/wDc6VvGMI5KXg58ksk8Ny4bMjaWHFOq5rfZsW/ocA5nnlcPOVWWptttqc65XD+mczZHV7vRWOzPZTGbQflw9Pwgw6o61NvnvPIfBW1TOW0lbMNdr2Q+zbG46KlQGhR/M8eNw/lZ9THQrusJ2J2fsei3EYhv3iuTDc3hbmAk5W6NA43O6brrOzfaU1srHUWAF+QZDGURI8J13aHidyVOrROpvjY4P7SeyGC2dskDD0hn76mDVdDqh1nxbuggX0XkC+gftpw1SrgWUqTC9zsRThouT4XH05rzCj2No0mj77iSyoRIZSGctG7MYv8ADqU4pyQ47bM45C0dq7LNBxyu7xm54Bb/AKmn2T6jms9FGhYwGFdWqspN1e4DoN58hJ8l7Zs+h3OHIoCCxoFMa2br1JuvPexOyHtecRVaW2hgNic3tOjda3mV3wxmUQNfkFksfyzt8L8f0O7HP4If7S/BfmXNgYlz64qYioSQCGTZocbWAsLTdQ/aL2DoVI2gykM7ROIpguaKo/6hyEHM3eQRIudL6XZnEMFSHMbJu10CQRrdab8VnqOJvci/DSPRYTl8DTZvOH9xxtR4ljOy7Kl8I7K7/o1HDxcqdUxf+V/H2iuZr0X03Fj2lrmmC1wIIPMHRel7bwIoYh9NvszLf0uEgeWnks7a2FbiaeWpdzR4H+83kT7zeR8oXeqkrR50sTicGnBNIIJB1Fj5JwSIFCcE0JwQMcE4JgTgmMepsPiH0zmY4g/PqN6hSoKRfqbWrOM5gOQAj4oVFCY7MZCAhZGAqEITAQhdhjsfSr4djZh1MgERNvZJHHpyXIJ/eO4nyt8lLim0/BcZuKaXdUaeNqimzuxlLjcuAeCBaxzRa3DeswklIhW3Zmkarmk02VGm8C+8OBj5iVNhcW8PFTMe8Ds2bU5pmTxuoNl1vw3s841kGM0DkWtKfs5ryT3YvxsCJMWJ39E07HJad0aON2mW1nN7toBALBMRIktPMSR/SqVA1alUugtJkkmQGiNSdR+8cVQrkFxN+AnW1vnKdSruFs0DfrB4SBqohjjB2jTJmnkjpkw2uCKrmH3LTx3z8V7Z9h9UHZrm/lrP+IB+q8KqmSTxXtP2I1IwVUf94/Fo/ZU1dnPk+ybvavDYipi2OcD3dIEsOWWw5rRM7zmBPLwrR7N4QMcaz2gADw7ogRm9LTzTdudscNhAWF+d4H8NpEj9btGDrfkVwWMr7T2qZfUFDCn2YDgHji1vtVt17M5hCtxolRbeo3O2/bPDktZRIqvY8uJB8A8Lmxm3+1u4Lg8dtB+IfneGzEDKItc+eq7PZ2yMNhRDKIeSCHOqwXvabOAOlMXjw3Fpc7Rc1t3Ypw7u8phzqDz4HEeyde7fweINt8SLLWDSVG0YrkpUKRfaJ48PNSYPZGFov7zKC4XAuQ39Ldx/wQjD4hwhrRr6k8eanLHtPjaQdYcCDffBWU4uWz4O3HpW/LKO0e2FJvhpMc4yM2YFkAG9jfN1AW5g8SHw4GQ6CDxB0WRtHY9LEDxeF8WeNeh/MP8ALKLCUqmGptZUIMSARoRJLfhFuSrBFQWlGXUvJKWtnc7Pc4OB4ELaNTxSN91weC208awfgfVdLsfG96HcQRbhI/4XJ/UYf49Xg7ugyXPT5M3tgPx2O40x8HOWFiHQx3T5kD6rb7Vn8Vn6P/YrnNp1MtInmPhf6LTpneGJn1Cqcji6zpc48XE+pKaEgSrc84cnBNCUJFDk4JoTgmMcnBNShBSFQhCBmOhCVQYAhCEACVIlCAFCUJE6nqOo+aYEzPDpqN+9WHY18RmO/wCO88SnVcLq4G2sR4tdI9b6WVZtJzvdMb+QS1IbhIkpUczZm4PrPyP7ow+Eq1H93Tpuc7gB89wHM2Wv2d2KMQ8uc/K1sSBGZ3rYC3xXfYLC06TctNoaOA/y61jik/uMpZopV3OFGwW4dzRiG5nOEhod+HwMkQSRbfF960MftmtggcLhH9zTqhj3EAlwJBBDXXIbbdfUSrvarCB1am4uc05CAWxuM6EEbxuVgdmKeJw7cry2o0uOZ3izzlHi0IENERESbKHikp7cGyyQliSa3NfZHZXCYXLVcRiXvaHtqvymkQ6HB1KmZDt3jfmvuatl9V1R8NzPe7hLnH14c7DeYIWH2VoYvDNOFxdJ1ShJdTqUXMc+i/UhofEsdvBEA34ldfs6g6uwhpGHoSQadF+au8ixFauLtP8AKwyPzRZD+lbhDHrexVpUWtf3b2mvWEfgUTanpBrVjanbdMkEjxhag2N3mU41zXhplmHpiKDDe5BvVdc3dA4NCv4SgykwU6LAxo3NEa6nrzRiK9OkAajoJ9kCS5x4NaLuPRZObZ1LEol2iWkAQBFgBuA+QWftXYuFxbvxRmewAS1xDgDJAdG7WJ5podWrazRZ+VpHeu/U4WZ0bJ/mCuUxSoM91jRfqTqeJPxKXBSKGH7HYBpnui79T3n4AwrWOpYDD0nMqUqQY4QWZW+Icx9SuP7QfadQY/uMLNR+hc0Ahsa3Nvn5Lkm4ivjcZTDqpGZtUgm4GXLfLOu6Sq07apOkiG23pW7IsXhB94LMO0kOLixupa3MYBPIRcrrNi7NNBpzOlzomNBEwBx11VepTdhz3eHYyY8dSoSST0Fz6gCVibVxeMa/LUrWIkBgyNPpfyJWOeObqI/Sqh75Z0dPLD07qTufrhFntZtCm0ucbim1oMcS68f6lyu18YypQmm4EX01HgdqNRqtB2DbWYWPmDwMGQZBXOY/ZL8NmkhzS05SNehbu+S6IRUIqC7HPllJty7MykqQJVRyihOCaE4JlIcEoSBKEDHBKE1OCBoVKkQgoyEqEKDAEqEIoYJYTSUkoESMbJhW6dIDcqmHMOCugqomc2xXYl7RlOm4/sdx6Kdm0R3ZDhLoI5Hmog7dqOB0TO5Z/N0kfNKeJT5NMfUOF0TYPHvpnOwwRcjcRMfVdXhu0L6gDB4XcYmf2/zRchU9kgCBbTrvO9TsJFwtk3wc7rmjrq2y8XXLZzSDYvPhE6/TRdXsTBOo08r3BziZJFhusFxew+0r6UMqeJvxC7zAYunVbmpuBHxHVWkGtvYvU08UXB/e0nZKm8xLXgaCo33hwNiNxF5bTVliiRtB09ib7/iXjK2m2kfeeSKn/wCYET1dH6Sp8JhWsJfcuPtPeZeerjoOQgDcFnbT2vQwlPvK9QMG6dXHg0auPILzHtN9otfEE08NNKnPtH23fRvxPRYOKXB1fJe8mejdpu3WEwIy5s9Tcxtz58BzMDqvO8f2qxGPGZ7srTIyA2HInfu4DkuFcSSSSSSZJNySdSTvK1NhVLuZxgjysfp6KscUnuRPK2qWyL+ApAVKvHOB5ZQfmStvYlUtxVFw1FOp8cqwGPLMU4HSoAR1A/4cFbxYeKfes93K13IPdr6tA81pSdpkptK1ydnidpU6cl7pdrA18+CoY/O9or1w2jSE5XVDlDp/KDd56BcXS7Q1aZmk1rXDRxAcRzANgesrPxeNq1nmpWqOqPIgueS4xMwJ0HIWTlO9kZxWl2ufJvbQ7SMHhw7Sf53jL/pZr6+iwziH1M7nuJOU69dw3KtCkpe9+krNsttvkjCVIE5AgCcE0JwQMUJQkCUIGOCVNCcgYqEiEx2ZaEIUGYqQlCQoYAhCEhApqVchQoQI0GPBTws5riFapV+KtSM5Q8E9X2T/AJvUrVDUcMuvD5hSGq0a+itE02iw1WMFtx+FdNN0neBp/nJY9bEudYWHD91Chz8FrGu565sXtpharR3jgx2+SA0czJsPhzVXtF9o9GlNPAt71+hrPBFNvHIzV55mBvuvLv8APiEilystRLO0MfWxFQ1a9R1R53uPwA0aOQsq8ISqShWMJIABJNgBqSul2PssU35arHh5Eh4g0wBctzDQ9fLnibKxncVRUyh0SI013g7itDavaB9ZpYxuRp1vLnDhyCuOlbsiV3SL9emyvUbXh4w9EwXsaXFxkE5QPcEXd1hS18c2lQqM1NQBreGrpd5W+CbsztcyjQbT7klzGgC4DDG8nUTroudqYh1R+ZxuZPIW0A3BU2uUON00ysE4BKGp4asyhoansAuOR+RShieGoAgyJIVktTSxFDIEqeWJsIARKkSoGKnJqVMBUJEIGZqEIUGYFIlQkAiEqEACEoanAIoKEa1PQhMYqVNSpgKhCUIAB9PqEJR9PqEIEASoSoASEsJQE8NTAYApGC48/iE5rU8NQMaGp4anAJYTAQBOhEJYQMSEQnQiExjCEwsU0JIQIrlibCswmliVDK6VPLE2EACRLCRAzOlCEKDMEIQkgFhKAhCoBUqEIGCVCEDFSoQgTBKhCYhR9PqEqEIAUJwCEIAkaE4BCEAPATgEITGOShCExipQhCBioQhAhEQhCYwhJCEIAQhNLUISAbkQhCBn/9k=", use_column_width=True)
160
+
161
+ st.subheader("πŸ“ Document Upload")
162
+ uploaded_files = st.file_uploader("Upload documents", type=["txt", "md", "docx", "pdf"], accept_multiple_files=True)
163
+
164
+ st.subheader("🎭 Chatbot Personality")
165
+ personality = st.selectbox("Choose chatbot personality", ["default", "sherlock", "yoda", "shakespeare", "custom"])
166
+
167
+ if personality == "custom":
168
+ st.session_state.custom_personality = st.text_area("Enter custom personality details:", value=st.session_state.custom_personality)
169
+
170
+ st.subheader("🌐 Web Search")
171
+ web_search = st.checkbox("Enable web search")
172
+
173
+ st.subheader("πŸ’¬ Chat Mode")
174
+ chat_mode = st.radio("Select chat mode", ["General Chat", "Document Chat"])
175
+
176
+ if st.button("Clear Chat History"):
177
+ st.session_state.messages = []
178
+ st.rerun()
179
+
180
+ # Main content
181
+ if uploaded_files:
182
+ qa_chain = process_documents(uploaded_files)
183
+ if qa_chain:
184
+ st.success("Documents processed successfully!")
185
+ else:
186
+ st.warning("No valid documents were uploaded or processed.")
187
+ else:
188
+ qa_chain = None
189
+
190
+ # Chat interface
191
+ for message in st.session_state.messages:
192
+ with st.chat_message(message["role"]):
193
+ st.markdown(message["content"])
194
+
195
+ if prompt := st.chat_input("What is your question?"):
196
+ st.chat_message("user").markdown(prompt)
197
+ st.session_state.messages.append({"role": "user", "content": prompt})
198
+
199
+ if chat_mode == "General Chat" or not qa_chain:
200
+ response, _, web_results = get_chatbot_response(prompt, personality=personality, web_search=web_search)
201
+ else:
202
+ response, source_docs, web_results = get_chatbot_response(prompt, qa_chain, personality, web_search)
203
+
204
+ with st.chat_message("assistant"):
205
+ st.markdown(response)
206
+ if chat_mode == "Document Chat" and qa_chain and source_docs:
207
+ with st.expander("Source Documents"):
208
+ for doc in source_docs:
209
+ st.markdown(f"**Source:** {doc.metadata.get('source', 'Unknown')}")
210
+ st.markdown(doc.page_content[:200] + "...")
211
+
212
+ if web_search and web_results:
213
+ with st.expander("Web Search Results"):
214
+ for result in web_results:
215
+ st.markdown(f"**[{result['title']}]({result['link']})**")
216
+ st.markdown(result['snippet'])
217
+
218
+ st.session_state.messages.append({"role": "assistant", "content": response})
219
+
220
+ # Chat history and download
221
+ with st.sidebar:
222
+ st.subheader("πŸ“œ Chat History")
223
+ history_expander = st.expander("View Chat History")
224
+ with history_expander:
225
+ for message in st.session_state.messages:
226
+ st.text(f"{message['role']}: {message['content'][:50]}...")
227
+
228
+ if st.session_state.messages:
229
+ chat_history_df = pd.DataFrame(st.session_state.messages)
230
+ csv = chat_history_df.to_csv(index=False)
231
+ st.download_button(
232
+ label="πŸ“₯ Download Chat History",
233
+ data=csv,
234
+ file_name="chat_history.csv",
235
+ mime="text/csv",
236
+ )
237
+
238
+ st.sidebar.markdown("---")
239
+ st.sidebar.markdown("Powered by Falcon-180B and Streamlit")
240
+
241
+ if __name__ == "__main__":
242
+ main()
pages/exam_prepration.py ADDED
@@ -0,0 +1,325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import random
3
+ import time
4
+ from typing import List, Dict
5
+ from langchain_openai import ChatOpenAI
6
+ from langchain.schema import HumanMessage, SystemMessage
7
+ from langchain_community.document_loaders import PyPDFLoader, TextLoader, UnstructuredWordDocumentLoader
8
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
9
+ from langchain_huggingface import HuggingFaceEmbeddings
10
+ from langchain_community.vectorstores import FAISS
11
+ from langchain.chains import RetrievalQA
12
+ from langchain_community.graphs import NetworkxEntityGraph
13
+ from googleapiclient.discovery import build
14
+ from googleapiclient.errors import HttpError
15
+ import os
16
+ from dotenv import load_dotenv
17
+ import requests
18
+ from bs4 import BeautifulSoup
19
+
20
+ # Load environment variables
21
+ load_dotenv()
22
+
23
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
24
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
25
+ GOOGLE_API_KEY = "AIzaSyD-1OMuZ0CxGAek0PaXrzHOmcDWFvZQtm8"
26
+ GOOGLE_CSE_ID = "877170db56f5c4629"
27
+ YOUTUBE_API_KEY = "AIzaSyD-1OMuZ0CxGAek0PaXrzHOmcDWFvZQtm8"
28
+
29
+ # Initialize the Falcon model
30
+ chat = ChatOpenAI(
31
+ model="tiiuae/falcon-180B-chat",
32
+ api_key=AI71_API_KEY,
33
+ base_url=AI71_BASE_URL,
34
+ streaming=True,
35
+ )
36
+
37
+ # Initialize embeddings
38
+ embeddings = HuggingFaceEmbeddings()
39
+
40
+ FIELDS = [
41
+ "Mathematics", "Physics", "Chemistry", "Biology", "Computer Science",
42
+ "History", "Geography", "Literature", "Philosophy", "Psychology",
43
+ "Sociology", "Economics", "Business", "Finance", "Accounting",
44
+ "Law", "Political Science", "Environmental Science", "Astronomy", "Geology",
45
+ "Linguistics", "Anthropology", "Art History", "Music Theory", "Film Studies",
46
+ "Medical Science", "Nursing", "Public Health", "Nutrition", "Physical Education",
47
+ "Engineering", "Architecture", "Urban Planning", "Agriculture", "Veterinary Science",
48
+ "Oceanography", "Meteorology", "Statistics", "Data Science", "Artificial Intelligence",
49
+ "Cybersecurity", "Renewable Energy", "Quantum Physics", "Neuroscience", "Genetics",
50
+ "Biotechnology", "Nanotechnology", "Robotics", "Space Exploration", "Cryptography"
51
+ ]
52
+
53
+ # List of educational resources
54
+ EDUCATIONAL_RESOURCES = [
55
+ "https://www.coursera.org",
56
+ "https://www.khanacademy.org",
57
+ "https://scholar.google.com",
58
+ "https://www.edx.org",
59
+ "https://www.udacity.com",
60
+ "https://www.udemy.com",
61
+ "https://www.futurelearn.com",
62
+ "https://www.lynda.com",
63
+ "https://www.skillshare.com",
64
+ "https://www.codecademy.com",
65
+ "https://www.brilliant.org",
66
+ "https://www.duolingo.com",
67
+ "https://www.ted.com/talks",
68
+ "https://ocw.mit.edu",
69
+ "https://www.open.edu/openlearn",
70
+ "https://www.coursebuffet.com",
71
+ "https://www.academicearth.org",
72
+ "https://www.edutopia.org",
73
+ "https://www.saylor.org",
74
+ "https://www.openculture.com",
75
+ "https://www.gutenberg.org",
76
+ "https://www.archive.org",
77
+ "https://www.wolframalpha.com",
78
+ "https://www.quizlet.com",
79
+ "https://www.mathway.com",
80
+ "https://www.symbolab.com",
81
+ "https://www.lessonplanet.com",
82
+ "https://www.teacherspayteachers.com",
83
+ "https://www.brainpop.com",
84
+ "https://www.ck12.org"
85
+ ]
86
+
87
+ def search_web(query: str, num_results: int = 30, max_retries: int = 3) -> List[Dict[str, str]]:
88
+ user_agents = [
89
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
90
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15',
91
+ 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36'
92
+ ]
93
+
94
+ for attempt in range(max_retries):
95
+ try:
96
+ headers = {'User-Agent': random.choice(user_agents)}
97
+ service = build("customsearch", "v1", developerKey=GOOGLE_API_KEY)
98
+ res = service.cse().list(q=query, cx=GOOGLE_CSE_ID, num=num_results).execute()
99
+
100
+ results = []
101
+ if "items" in res:
102
+ for item in res["items"]:
103
+ result = {
104
+ "title": item["title"],
105
+ "link": item["link"],
106
+ "snippet": item.get("snippet", "")
107
+ }
108
+ results.append(result)
109
+
110
+ return results
111
+ except Exception as e:
112
+ print(f"An error occurred: {e}. Attempt {attempt + 1} of {max_retries}")
113
+ time.sleep(2 ** attempt)
114
+
115
+ print("Max retries reached. No results found.")
116
+ return []
117
+
118
+ def scrape_webpage(url: str) -> str:
119
+ try:
120
+ response = requests.get(url, timeout=10)
121
+ soup = BeautifulSoup(response.content, 'html.parser')
122
+ return soup.get_text()
123
+ except Exception as e:
124
+ print(f"Error scraping {url}: {e}")
125
+ return ""
126
+
127
+ def process_documents(uploaded_files):
128
+ documents = []
129
+ for uploaded_file in uploaded_files:
130
+ file_extension = os.path.splitext(uploaded_file.name)[1].lower()
131
+
132
+ if file_extension == '.pdf':
133
+ loader = PyPDFLoader(uploaded_file)
134
+ elif file_extension in ['.txt', '.md']:
135
+ loader = TextLoader(uploaded_file)
136
+ elif file_extension in ['.doc', '.docx']:
137
+ loader = UnstructuredWordDocumentLoader(uploaded_file)
138
+ else:
139
+ st.warning(f"Unsupported file type: {file_extension}")
140
+ continue
141
+
142
+ documents.extend(loader.load())
143
+
144
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
145
+ texts = text_splitter.split_documents(documents)
146
+
147
+ vectorstore = FAISS.from_documents(texts, embeddings)
148
+ graph = NetworkxEntityGraph()
149
+ graph.add_documents(texts)
150
+
151
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
152
+
153
+ qa_chain = RetrievalQA.from_chain_type(
154
+ llm=chat,
155
+ chain_type="stuff",
156
+ retriever=retriever,
157
+ return_source_documents=True
158
+ )
159
+
160
+ return qa_chain, graph
161
+
162
+ def generate_questions(topic, difficulty, num_questions, include_answers, qa_chain=None, graph=None):
163
+ system_prompt = f"""You are an expert exam question generator. Generate {num_questions} {difficulty}-level questions about {topic}.
164
+ {"Each question should be followed by its correct answer." if include_answers else "Do not include answers."}
165
+ Format your response as follows:
166
+
167
+ Q1. [Question]
168
+ {"A1. [Answer]" if include_answers else ""}
169
+
170
+ Q2. [Question]
171
+ {"A2. [Answer]" if include_answers else ""}
172
+
173
+ ... and so on.
174
+ """
175
+
176
+ if qa_chain and graph:
177
+ context = graph.get_relevant_documents(topic)
178
+ context_text = "\n".join([doc.page_content for doc in context])
179
+
180
+ result = qa_chain({"query": system_prompt, "context": context_text})
181
+ questions = result['result']
182
+ else:
183
+ messages = [
184
+ SystemMessage(content=system_prompt),
185
+ HumanMessage(content=f"Please generate {num_questions} {difficulty} questions about {topic}.")
186
+ ]
187
+ questions = chat(messages).content
188
+
189
+ return questions
190
+
191
+ def gather_resources(field: str) -> List[Dict[str, str]]:
192
+ resources = []
193
+ for resource_url in EDUCATIONAL_RESOURCES:
194
+ search_results = search_web(f"site:{resource_url} {field}", num_results=1)
195
+ if search_results:
196
+ result = search_results[0]
197
+ content = scrape_webpage(result['link'])
198
+ resources.append({
199
+ "title": result['title'],
200
+ "link": result['link'],
201
+ "content": content[:500] + "..." if len(content) > 500 else content
202
+ })
203
+
204
+ # YouTube search
205
+ youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY)
206
+ youtube_results = youtube.search().list(q=field, type='video', part='id,snippet', maxResults=5).execute()
207
+ for item in youtube_results.get('items', []):
208
+ video_id = item['id']['videoId']
209
+ resources.append({
210
+ "title": item['snippet']['title'],
211
+ "link": f"https://www.youtube.com/watch?v={video_id}",
212
+ "content": item['snippet']['description'],
213
+ "thumbnail": item['snippet']['thumbnails']['medium']['url']
214
+ })
215
+
216
+ return resources
217
+
218
+ def main():
219
+ st.set_page_config(page_title="Advanced Exam Preparation System", layout="wide")
220
+
221
+ st.sidebar.title("Advanced Exam Prep")
222
+ st.sidebar.markdown("""
223
+ Welcome to our advanced exam preparation system!
224
+ Here you can generate practice questions, explore educational resources,
225
+ and interact with an AI tutor to enhance your learning experience.
226
+ """)
227
+
228
+ # Main area tabs
229
+ tab1, tab2, tab3 = st.tabs(["Question Generator", "Resource Explorer", "Academic Tutor"])
230
+
231
+ with tab1:
232
+ st.header("Question Generator")
233
+ col1, col2 = st.columns(2)
234
+ with col1:
235
+ topic = st.text_input("Enter the exam topic:")
236
+ exam_type = st.selectbox("Select exam type:", ["General", "STEM", "Humanities", "Business", "Custom"])
237
+ with col2:
238
+ difficulty = st.select_slider(
239
+ "Select difficulty level:",
240
+ options=["Super Easy", "Easy", "Beginner", "Intermediate", "Higher Intermediate", "Master", "Advanced"]
241
+ )
242
+ num_questions = st.number_input("Number of questions:", min_value=1, max_value=50, value=5)
243
+ include_answers = st.checkbox("Include answers", value=True)
244
+
245
+ if st.button("Generate Questions", key="generate_questions"):
246
+ if topic:
247
+ with st.spinner("Generating questions..."):
248
+ questions = generate_questions(topic, difficulty, num_questions, include_answers)
249
+ st.success("Questions generated successfully!")
250
+ st.markdown(questions)
251
+ else:
252
+ st.warning("Please enter a topic.")
253
+
254
+ with tab2:
255
+ st.header("Resource Explorer")
256
+ selected_field = st.selectbox("Select a field to explore:", FIELDS)
257
+ if st.button("Explore Resources", key="explore_resources"):
258
+ with st.spinner("Gathering resources..."):
259
+ resources = gather_resources(selected_field)
260
+ st.success(f"Found {len(resources)} resources!")
261
+
262
+ for i, resource in enumerate(resources):
263
+ col1, col2 = st.columns([1, 3])
264
+ with col1:
265
+ if "thumbnail" in resource:
266
+ st.image(resource["thumbnail"], use_column_width=True)
267
+ else:
268
+ st.image("https://via.placeholder.com/150", use_column_width=True)
269
+ with col2:
270
+ st.subheader(f"[{resource['title']}]({resource['link']})")
271
+ st.write(resource['content'])
272
+ st.markdown("---")
273
+
274
+ with tab3:
275
+ st.header("Academic Tutor")
276
+ uploaded_files = st.file_uploader("Upload documents (PDF, TXT, MD, DOC, DOCX)", type=["pdf", "txt", "md", "doc", "docx"], accept_multiple_files=True)
277
+
278
+ if uploaded_files:
279
+ qa_chain, graph = process_documents(uploaded_files)
280
+ st.success("Documents processed successfully!")
281
+ else:
282
+ qa_chain, graph = None, None
283
+
284
+ st.subheader("Chat with AI Tutor")
285
+ if 'chat_history' not in st.session_state:
286
+ st.session_state.chat_history = []
287
+
288
+ chat_container = st.container()
289
+ with chat_container:
290
+ for i, (role, message) in enumerate(st.session_state.chat_history):
291
+ with st.chat_message(role):
292
+ st.write(message)
293
+
294
+ user_input = st.chat_input("Ask a question or type 'search: your query' to perform a web search:")
295
+ if user_input:
296
+ st.session_state.chat_history.append(("user", user_input))
297
+ with st.chat_message("user"):
298
+ st.write(user_input)
299
+
300
+ with st.chat_message("assistant"):
301
+ if user_input.lower().startswith("search:"):
302
+ search_query = user_input[7:].strip()
303
+ search_results = search_web(search_query, num_results=3)
304
+ response = f"Here are some search results for '{search_query}':\n\n"
305
+ for result in search_results:
306
+ response += f"- [{result['title']}]({result['link']})\n {result['snippet']}\n\n"
307
+ else:
308
+ response = chat([HumanMessage(content=user_input)]).content
309
+ st.write(response)
310
+ st.session_state.chat_history.append(("assistant", response))
311
+
312
+ # Scroll to bottom of chat
313
+ js = f"""
314
+ <script>
315
+ function scroll_to_bottom() {{
316
+ var chatElement = window.parent.document.querySelector('.stChatFloatingInputContainer');
317
+ chatElement.scrollIntoView({{behavior: 'smooth'}});
318
+ }}
319
+ scroll_to_bottom();
320
+ </script>
321
+ """
322
+ st.components.v1.html(js)
323
+
324
+ if __name__ == "__main__":
325
+ main()
pages/interview_prepration.py ADDED
@@ -0,0 +1,560 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import random
3
+ from langchain_community.chat_models import ChatOpenAI
4
+ from langchain.schema import HumanMessage, SystemMessage
5
+ import os
6
+ from dotenv import load_dotenv
7
+ import base64
8
+ import cv2
9
+ import numpy as np
10
+ from PIL import Image
11
+ import io
12
+ import time
13
+ import PyPDF2
14
+ import docx
15
+ import markdown
16
+
17
+ # Load environment variables
18
+ load_dotenv()
19
+
20
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
21
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
22
+
23
+ # Initialize the Falcon model
24
+ chat = ChatOpenAI(
25
+ model="tiiuae/falcon-180B-chat",
26
+ api_key=AI71_API_KEY,
27
+ base_url=AI71_BASE_URL,
28
+ streaming=True,
29
+ timeout=60,
30
+ )
31
+
32
+ # Expanded list of roles
33
+ roles = [
34
+ "Software Engineer", "Data Scientist", "Product Manager", "UX Designer", "Marketing Manager",
35
+ "Sales Representative", "Human Resources Manager", "Financial Analyst", "Project Manager",
36
+ "Business Analyst", "Content Writer", "Graphic Designer", "Customer Service Representative",
37
+ "Operations Manager", "Research Scientist", "Legal Counsel", "Network Administrator",
38
+ "Quality Assurance Tester", "Supply Chain Manager", "Public Relations Specialist"
39
+ ]
40
+
41
+ def generate_interview_questions(role):
42
+ system_message = f"""You are an experienced interviewer for the role of {role}.
43
+ Generate 5 challenging and relevant interview questions for this position.
44
+ The questions should cover a range of skills and experiences required for the role."""
45
+
46
+ messages = [
47
+ SystemMessage(content=system_message),
48
+ HumanMessage(content="Please provide 5 interview questions for this role.")
49
+ ]
50
+
51
+ response = chat.invoke(messages).content
52
+ questions = response.split('\n')
53
+ return [q.strip() for q in questions if q.strip()]
54
+
55
+ def get_interview_response(role, question, answer):
56
+ system_message = f"""You are an experienced interviewer for the role of {role}.
57
+ Your task is to evaluate the candidate's response to the following question: '{question}'
58
+
59
+ The candidate's answer was: '{answer}'
60
+
61
+ Please provide:
62
+ 1. A brief evaluation of the answer (2-3 sentences)
63
+ 2. Specific feedback on how to improve (if needed) or praise for a good answer
64
+ 3. A follow-up question based on their response
65
+ 4. A score out of 10 for their answer
66
+
67
+ Format your response as follows:
68
+ Evaluation: [Your evaluation here]
69
+ Feedback: [Your specific feedback or praise here]
70
+ Follow-up: [Your follow-up question here]
71
+ Score: [Score out of 10]
72
+ """
73
+
74
+ messages = [
75
+ SystemMessage(content=system_message),
76
+ HumanMessage(content="Please provide your evaluation, feedback, follow-up question, and score.")
77
+ ]
78
+
79
+ response = chat.invoke(messages).content
80
+ return response
81
+
82
+ def analyze_appearance(image):
83
+ # Convert PIL Image to OpenCV format
84
+ cv_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
85
+
86
+ # Load pre-trained face detection model
87
+ face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
88
+
89
+ # Convert to grayscale for face detection
90
+ gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY)
91
+
92
+ # Detect faces
93
+ faces = face_cascade.detectMultiScale(gray, 1.3, 5)
94
+
95
+ analysis = []
96
+
97
+ if len(faces) == 0:
98
+ analysis.append("No face detected in the image. Please ensure your face is clearly visible.")
99
+ else:
100
+ analysis.append(f"Detected {len(faces)} face(s) in the image.")
101
+
102
+ # Analyze facial positioning
103
+ for (x, y, w, h) in faces:
104
+ face_center = (x + w//2, y + h//2)
105
+ image_center = (cv_image.shape[1]//2, cv_image.shape[0]//2)
106
+
107
+ if abs(face_center[0] - image_center[0]) > cv_image.shape[1]//8:
108
+ analysis.append("Your face is not centered horizontally. Try to position yourself in the middle of the frame.")
109
+
110
+ if abs(face_center[1] - image_center[1]) > cv_image.shape[0]//8:
111
+ analysis.append("Your face is not centered vertically. Adjust your camera or seating position.")
112
+
113
+ if w * h < (cv_image.shape[0] * cv_image.shape[1]) // 16:
114
+ analysis.append("Your face appears too small in the frame. Consider moving closer to the camera.")
115
+ elif w * h > (cv_image.shape[0] * cv_image.shape[1]) // 4:
116
+ analysis.append("Your face appears too large in the frame. Consider moving slightly away from the camera.")
117
+
118
+ # Analyze image brightness
119
+ brightness = np.mean(gray)
120
+ if brightness < 100:
121
+ analysis.append("The image appears too dark. Consider improving your lighting for better visibility.")
122
+ elif brightness > 200:
123
+ analysis.append("The image appears too bright. You might want to reduce harsh lighting or adjust your camera settings.")
124
+
125
+ # Analyze image contrast
126
+ contrast = np.std(gray)
127
+ if contrast < 20:
128
+ analysis.append("The image lacks contrast. This might make it difficult to see details. Consider adjusting your lighting or camera settings.")
129
+
130
+ return "\n".join(analysis)
131
+
132
+ def extract_text_from_file(file):
133
+ file_extension = file.name.split('.')[-1].lower()
134
+
135
+ if file_extension == 'pdf':
136
+ pdf_reader = PyPDF2.PdfReader(file)
137
+ text = ""
138
+ for page in pdf_reader.pages:
139
+ text += page.extract_text()
140
+ elif file_extension == 'docx':
141
+ doc = docx.Document(file)
142
+ text = "\n".join([paragraph.text for paragraph in doc.paragraphs])
143
+ elif file_extension == 'txt':
144
+ text = file.read().decode()
145
+ elif file_extension == 'md':
146
+ md_text = file.read().decode()
147
+ text = markdown.markdown(md_text)
148
+ else:
149
+ raise ValueError(f"Unsupported file format: {file_extension}")
150
+
151
+ return text
152
+
153
+ def analyze_cv(cv_text):
154
+ system_message = """You are an expert CV reviewer with extensive experience in various industries.
155
+ Analyze the given CV and provide:
156
+ 1. An overall assessment of the CV's strengths
157
+ 2. Areas that need improvement
158
+ 3. Specific suggestions for enhancing the CV
159
+ 4. Tips for tailoring the CV to specific job applications
160
+
161
+ Be thorough, constructive, and provide actionable advice."""
162
+
163
+ messages = [
164
+ SystemMessage(content=system_message),
165
+ HumanMessage(content=f"Here's the text of the CV to review:\n\n{cv_text}\n\nPlease provide your analysis and suggestions.")
166
+ ]
167
+
168
+ response = chat.invoke(messages).content
169
+ return response
170
+
171
+ def resize_image(image, max_size=800):
172
+ """Resize image while maintaining aspect ratio"""
173
+ ratio = max_size / max(image.size)
174
+ new_size = tuple([int(x*ratio) for x in image.size])
175
+ return image.resize(new_size, Image.LANCZOS)
176
+
177
+ def get_mock_interview_tips():
178
+ tips = [
179
+ "Research the company and role thoroughly before the interview.",
180
+ "Practice common interview questions with a friend or family member.",
181
+ "Prepare specific examples to illustrate your skills and experiences.",
182
+ "Dress professionally and ensure your background is tidy for video interviews.",
183
+ "Have questions prepared to ask the interviewer about the role and company.",
184
+ "Use the STAR method (Situation, Task, Action, Result) to structure your answers.",
185
+ "Be aware of your body language and maintain good eye contact.",
186
+ "Listen carefully to each question and take a moment to gather your thoughts before answering.",
187
+ "Be honest about your experiences and skills, but focus on your strengths.",
188
+ "Follow up with a thank-you note or email after the interview.",
189
+ ]
190
+ return tips
191
+
192
+ def get_interview_resources():
193
+ resources = [
194
+ {"name": "Glassdoor Interview Questions & Reviews", "url": "https://www.glassdoor.com/Interview/index.htm"},
195
+ {"name": "LinkedIn Interview Preparation", "url": "https://www.linkedin.com/interview-prep/"},
196
+ {"name": "Indeed Career Guide", "url": "https://www.indeed.com/career-advice"},
197
+ {"name": "Coursera - How to Succeed in an Interview", "url": "https://www.coursera.org/learn/interview-preparation"},
198
+ {"name": "Harvard Business Review - Interview Tips", "url": "https://hbr.org/topic/interviewing"},
199
+ ]
200
+ return resources
201
+
202
+ def main():
203
+ st.set_page_config(page_title="S.H.E.R.L.O.C.K. Interview Preparation", page_icon="πŸŽ™οΈ", layout="wide")
204
+
205
+ st.title("πŸŽ™οΈ S.H.E.R.L.O.C.K. Interview Preparation")
206
+ st.markdown("### Streamlined Help for Enhancing Responsive Learning and Optimizing Career Knowledge")
207
+
208
+ # Sidebar for user details and interview settings
209
+ with st.sidebar:
210
+ st.header("Interview Settings")
211
+ name = st.text_input("Your Name")
212
+ role = st.selectbox("Interview Role", roles)
213
+ experience = st.slider("Years of Experience", 0, 20, 5)
214
+
215
+ st.header("Quick Tips")
216
+ if st.button("Get Mock Interview Tips"):
217
+ tips = get_mock_interview_tips()
218
+ for tip in tips:
219
+ st.info(tip)
220
+
221
+ st.header("Useful Resources")
222
+ resources = get_interview_resources()
223
+ for resource in resources:
224
+ st.markdown(f"[{resource['name']}]({resource['url']})")
225
+
226
+ # Appearance Analysis
227
+ st.header("Appearance Analysis")
228
+ uploaded_image = st.file_uploader("Upload your interview outfit image", type=["jpg", "jpeg", "png"])
229
+ if uploaded_image is not None:
230
+ try:
231
+ image = Image.open(uploaded_image)
232
+ image = resize_image(image)
233
+ st.image(image, caption="Your uploaded image", use_column_width=True)
234
+ if st.button("Analyze Appearance"):
235
+ with st.spinner("Analyzing your appearance..."):
236
+ appearance_feedback = analyze_appearance(image)
237
+ st.write(appearance_feedback)
238
+
239
+ st.write("\nGeneral tips for professional appearance in video interviews:")
240
+ tips = [
241
+ "Dress professionally from head to toe, even if only your upper body is visible.",
242
+ "Choose solid colors over busy patterns for a less distracting appearance.",
243
+ "Ensure your background is tidy and professional.",
244
+ "Position your camera at eye level for the most flattering angle.",
245
+ "Use soft, diffused lighting to avoid harsh shadows.",
246
+ "Make eye contact by looking directly into the camera when speaking.",
247
+ ]
248
+ for tip in tips:
249
+ st.write(f"- {tip}")
250
+ except Exception as e:
251
+ st.error(f"An error occurred while processing the image: {str(e)}")
252
+ st.info("Please make sure you've uploaded a valid image file.")
253
+
254
+ # CV Analysis
255
+ st.header("CV Analysis")
256
+ uploaded_cv = st.file_uploader("Upload your CV", type=["pdf", "docx", "txt", "md"])
257
+ if uploaded_cv is not None:
258
+ try:
259
+ cv_text = extract_text_from_file(uploaded_cv)
260
+ if st.button("Analyze CV"):
261
+ with st.spinner("Analyzing your CV..."):
262
+ cv_feedback = analyze_cv(cv_text)
263
+ st.write(cv_feedback)
264
+ except Exception as e:
265
+ st.error(f"An error occurred while processing the CV: {str(e)}")
266
+
267
+ # Initialize session state variables
268
+ if 'interview_started' not in st.session_state:
269
+ st.session_state.interview_started = False
270
+ if 'current_question' not in st.session_state:
271
+ st.session_state.current_question = 0
272
+ if 'questions' not in st.session_state:
273
+ st.session_state.questions = []
274
+ if 'answers' not in st.session_state:
275
+ st.session_state.answers = []
276
+ if 'feedback' not in st.session_state:
277
+ st.session_state.feedback = []
278
+ if 'scores' not in st.session_state:
279
+ st.session_state.scores = []
280
+ if 'chat_history' not in st.session_state:
281
+ st.session_state.chat_history = []
282
+
283
+ # Start Interview button
284
+ if not st.session_state.interview_started:
285
+ if st.button("Start Mock Interview"):
286
+ if name and role:
287
+ st.session_state.interview_started = True
288
+ with st.spinner("Generating interview questions..."):
289
+ st.session_state.questions = generate_interview_questions(role)
290
+ st.rerun()
291
+ else:
292
+ st.warning("Please enter your name and select a role before starting the interview.")
293
+
294
+ # Interview in progress
295
+ if st.session_state.interview_started:
296
+ st.header("Mock Interview")
297
+ if st.session_state.current_question < len(st.session_state.questions):
298
+ st.subheader(f"Question {st.session_state.current_question + 1}")
299
+ st.write(st.session_state.questions[st.session_state.current_question])
300
+
301
+ # Display chat history
302
+ for i, (q, a, f) in enumerate(st.session_state.chat_history):
303
+ with st.expander(f"Question {i+1}"):
304
+ st.write(f"Q: {q}")
305
+ st.write(f"Your Answer: {a}")
306
+ st.write(f"Feedback: {f}")
307
+
308
+ answer = st.text_area("Your Answer", key=f"answer_{st.session_state.current_question}")
309
+
310
+ col1, col2 = st.columns(2)
311
+ with col1:
312
+ if st.button("Submit Answer"):
313
+ if answer:
314
+ with st.spinner("Evaluating your answer..."):
315
+ response = get_interview_response(role, st.session_state.questions[st.session_state.current_question], answer)
316
+ st.session_state.answers.append(answer)
317
+ st.session_state.feedback.append(response)
318
+
319
+ # Extract score from response
320
+ score_lines = [line for line in response.split('\n') if line.startswith('Score:')]
321
+ if score_lines:
322
+ score_str = score_lines[0].split(':')[1].strip()
323
+ try:
324
+ score = int(score_str)
325
+ except ValueError:
326
+ # If the score is a fraction like "6/10", extract the numerator
327
+ score = int(score_str.split('/')[0])
328
+ else:
329
+ # If no score is found, use a default value
330
+ score = 5 # or any other default value you prefer
331
+ st.warning("No score was provided in the response. Using a default score of 5.")
332
+
333
+ st.session_state.scores.append(score)
334
+
335
+ # Update chat history
336
+ st.session_state.chat_history.append((
337
+ st.session_state.questions[st.session_state.current_question],
338
+ answer,
339
+ response
340
+ ))
341
+
342
+ st.session_state.current_question += 1
343
+ if st.session_state.current_question < len(st.session_state.questions):
344
+ st.rerun()
345
+ else:
346
+ st.warning("Please provide an answer before submitting.")
347
+ with col2:
348
+ if st.button("Skip Question"):
349
+ st.session_state.current_question += 1
350
+ if st.session_state.current_question < len(st.session_state.questions):
351
+ st.rerun()
352
+
353
+ else:
354
+ st.success("Interview Completed!")
355
+ total_score = sum(st.session_state.scores)
356
+ average_score = total_score / len(st.session_state.scores)
357
+
358
+ st.header("Interview Summary")
359
+ st.subheader(f"Overall Score: {average_score:.2f}/10")
360
+
361
+ for i, (q, a, f) in enumerate(st.session_state.chat_history):
362
+ with st.expander(f"Question {i+1}"):
363
+ st.write(f"Q: {q}")
364
+ st.write(f"Your Answer: {a}")
365
+ st.write(f"Feedback: {f}")
366
+
367
+ # Generate overall feedback
368
+ overall_feedback_prompt = f"""
369
+ You are an experienced career coach. Based on the candidate's performance in the interview for the role of {role},
370
+ with {experience} years of experience, please provide:
371
+ 1. A summary of their strengths (2-3 points)
372
+ 2. Areas for improvement (2-3 points)
373
+ 3. Advice for future interviews (2-3 tips)
374
+ 4. Personalized tips for improving their professional appearance and body language
375
+ 5. Strategies for managing interview anxiety
376
+
377
+ Their overall score was {average_score:.2f}/10.
378
+
379
+ Format your response as follows:
380
+ Strengths:
381
+ - [Strength 1]
382
+ - [Strength 2]
383
+ - [Strength 3]
384
+
385
+ Areas for Improvement:
386
+ - [Area 1]
387
+ - [Area 2]
388
+ - [Area 3]
389
+
390
+ Tips for Future Interviews:
391
+ - [Tip 1]
392
+ - [Tip 2]
393
+ - [Tip 3]
394
+
395
+ Professional Appearance and Body Language:
396
+ - [Tip 1]
397
+ - [Tip 2]
398
+ - [Tip 3]
399
+
400
+ Managing Interview Anxiety:
401
+ - [Strategy 1]
402
+ - [Strategy 2]
403
+ - [Strategy 3]
404
+ """
405
+
406
+ messages = [
407
+ SystemMessage(content=overall_feedback_prompt),
408
+ HumanMessage(content="Please provide the overall feedback for the interview.")
409
+ ]
410
+
411
+ with st.spinner("Generating overall feedback..."):
412
+ overall_feedback = chat.invoke(messages).content
413
+
414
+ st.subheader("Overall Feedback")
415
+ st.write(overall_feedback)
416
+
417
+ if st.button("Start New Interview"):
418
+ st.session_state.interview_started = False
419
+ st.session_state.current_question = 0
420
+ st.session_state.questions = []
421
+ st.session_state.answers = []
422
+ st.session_state.feedback = []
423
+ st.session_state.scores = []
424
+ st.session_state.chat_history = []
425
+ st.rerun()
426
+
427
+ # Footer
428
+ st.markdown("---")
429
+ st.markdown("Powered by Falcon-180B and Streamlit")
430
+
431
+ # Interview Preparation Checklist
432
+ st.sidebar.header("Interview Preparation Checklist")
433
+ checklist_items = [
434
+ "Research the company",
435
+ "Review the job description",
436
+ "Prepare your elevator pitch",
437
+ "Practice common interview questions",
438
+ "Prepare questions for the interviewer",
439
+ "Choose appropriate attire",
440
+ "Test your technology (for virtual interviews)",
441
+ "Gather necessary documents (resume, portfolio, etc.)",
442
+ "Plan your route or set up your interview space",
443
+ "Get a good night's sleep"
444
+ ]
445
+ for item in checklist_items:
446
+ st.sidebar.checkbox(item)
447
+
448
+ # Interview Timer
449
+ if st.session_state.interview_started:
450
+ st.sidebar.header("Interview Timer")
451
+ if 'start_time' not in st.session_state:
452
+ st.session_state.start_time = time.time()
453
+
454
+ elapsed_time = int(time.time() - st.session_state.start_time)
455
+ minutes, seconds = divmod(elapsed_time, 60)
456
+ st.sidebar.write(f"Elapsed Time: {minutes:02d}:{seconds:02d}")
457
+
458
+ # Confidence Boost
459
+ st.sidebar.header("Confidence Boost")
460
+ if st.sidebar.button("Get a Confidence Boost"):
461
+ confidence_boosters = [
462
+ "You've got this! Your preparation will pay off.",
463
+ "Remember, the interviewer wants you to succeed too.",
464
+ "Take deep breaths and stay calm. You're well-prepared.",
465
+ "Your unique experiences make you a valuable candidate.",
466
+ "Every interview is a learning opportunity. Embrace it!",
467
+ "Believe in yourself. Your skills and knowledge are valuable.",
468
+ "Stay positive and confident. Your attitude shines through.",
469
+ "You've overcome challenges before. This is just another opportunity to shine.",
470
+ "Focus on your strengths and what you can bring to the role.",
471
+ "Remember your past successes. You're capable of greatness!"
472
+ ]
473
+ st.sidebar.success(random.choice(confidence_boosters))
474
+
475
+ # Interview Do's and Don'ts
476
+ st.sidebar.header("Interview Do's and Don'ts")
477
+ dos_and_donts = {
478
+ "Do": [
479
+ "Arrive early or log in on time",
480
+ "Maintain good eye contact",
481
+ "Listen actively and ask thoughtful questions",
482
+ "Show enthusiasm for the role and company",
483
+ "Provide specific examples to support your answers"
484
+ ],
485
+ "Don't": [
486
+ "Speak negatively about past employers",
487
+ "Interrupt the interviewer",
488
+ "Use filler words excessively (um, like, you know)",
489
+ "Check your phone or watch frequently",
490
+ "Provide vague or generic answers"
491
+ ]
492
+ }
493
+ dos_tab, donts_tab = st.sidebar.tabs(["Do's", "Don'ts"])
494
+ with dos_tab:
495
+ for do_item in dos_and_donts["Do"]:
496
+ st.write(f"βœ… {do_item}")
497
+ with donts_tab:
498
+ for dont_item in dos_and_donts["Don't"]:
499
+ st.write(f"❌ {dont_item}")
500
+
501
+ # Personal Notes
502
+ st.sidebar.header("Personal Notes")
503
+ personal_notes = st.sidebar.text_area("Jot down your thoughts or reminders here:")
504
+
505
+ # Initialize session state for saved notes if it doesn't exist
506
+ if 'saved_notes' not in st.session_state:
507
+ st.session_state.saved_notes = []
508
+
509
+ # Save Notes button
510
+ if st.sidebar.button("Save Notes"):
511
+ if personal_notes.strip(): # Check if the note is not empty
512
+ st.session_state.saved_notes.append(personal_notes)
513
+ st.sidebar.success("Note saved successfully!")
514
+ # Clear the text area after saving
515
+ personal_notes = ""
516
+ else:
517
+ st.sidebar.warning("Please enter a note before saving.")
518
+
519
+ # Display saved notes as checkboxes
520
+ st.sidebar.subheader("Saved Notes")
521
+ for i, note in enumerate(st.session_state.saved_notes):
522
+ col1, col2 = st.sidebar.columns([3, 1])
523
+ with col1:
524
+ st.checkbox(note, key=f"note_{i}")
525
+ with col2:
526
+ if st.button("Delete", key=f"delete_{i}"):
527
+ del st.session_state.saved_notes[i]
528
+ st.rerun()
529
+
530
+ # Follow-up Email Template
531
+ if st.session_state.interview_started and st.session_state.current_question >= len(st.session_state.questions):
532
+ st.header("Follow-up Email Template")
533
+ interviewer_name = st.text_input("Interviewer's Name")
534
+ company_name = st.text_input("Company Name")
535
+ specific_topic = st.text_input("Specific topic discussed during the interview")
536
+
537
+ if interviewer_name and company_name and specific_topic:
538
+ email_template = f"""
539
+ Subject: Thank you for the interview - {role} position
540
+
541
+ Dear {interviewer_name},
542
+
543
+ I hope this email finds you well. I wanted to express my sincere gratitude for taking the time to interview me for the {role} position at {company_name}. I thoroughly enjoyed our conversation and learning more about the role and the company.
544
+
545
+ Our discussion about {specific_topic} was particularly interesting, and it reinforced my enthusiasm for the position. I am excited about the possibility of bringing my skills and experience to your team and contributing to {company_name}'s success.
546
+
547
+ If you need any additional information or have any further questions, please don't hesitate to contact me. I look forward to hearing about the next steps in the process.
548
+
549
+ Thank you again for your time and consideration.
550
+
551
+ Best regards,
552
+ {name}
553
+ """
554
+ st.text_area("Follow-up Email Template", email_template, height=300)
555
+ if st.button("Copy to Clipboard"):
556
+ st.write("Email template copied to clipboard!")
557
+ # Note: In a web app, you'd use JavaScript to copy to clipboard
558
+
559
+ if __name__ == "__main__":
560
+ main()
pages/meditation.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import time
3
+ import random
4
+ from pydub import AudioSegment
5
+ from pydub.generators import Sine
6
+ import io
7
+ import base64
8
+
9
+ # Function to generate binaural beats
10
+ def generate_binaural_beat(freq1, freq2, duration_ms):
11
+ beat1 = Sine(freq1).to_audio_segment(duration=duration_ms)
12
+ beat2 = Sine(freq2).to_audio_segment(duration=duration_ms)
13
+
14
+ stereo_beat = AudioSegment.from_mono_audiosegments(beat1, beat2)
15
+
16
+ buffer = io.BytesIO()
17
+ stereo_beat.export(buffer, format="wav")
18
+ return buffer.getvalue()
19
+
20
+ # Function to get binary audio data as base64
21
+ def get_binary_file_downloader_html(bin_file, file_label='File'):
22
+ bin_str = base64.b64encode(bin_file).decode()
23
+ href = f'<a href="data:application/octet-stream;base64,{bin_str}" download="{file_label}.wav">Download {file_label}</a>'
24
+ return href
25
+
26
+ # Streamlit app
27
+ def main():
28
+ st.set_page_config(page_title="Meditation & Mindfulness Hub", layout="wide")
29
+
30
+ st.title("🧘 Meditation & Mindfulness Hub")
31
+ st.markdown("Improve your mental health and focus with our holistic learning experience.")
32
+
33
+ # Sidebar for navigation
34
+ menu = st.sidebar.selectbox("Choose a Practice", ["Meditation", "Mindfulness Exercises", "Binaural Beats", "Positive Affirmations"])
35
+
36
+ if menu == "Meditation":
37
+ meditation_page()
38
+ elif menu == "Mindfulness Exercises":
39
+ mindfulness_page()
40
+ elif menu == "Binaural Beats":
41
+ binaural_beats_page()
42
+ elif menu == "Positive Affirmations":
43
+ affirmations_page()
44
+
45
+ def meditation_page():
46
+ st.header("Guided Meditation")
47
+
48
+ meditation_types = {
49
+ "Breath Awareness": "Focus on your breath, observing each inhale and exhale...",
50
+ "Body Scan": "Starting from your toes, gradually move your attention up through your body...",
51
+ "Loving-Kindness": "Direct feelings of love and compassion towards yourself and others...",
52
+ "Visualization": "Imagine a peaceful scene, like a serene beach or a tranquil forest..."
53
+ }
54
+
55
+ selected_meditation = st.selectbox("Choose a meditation type:", list(meditation_types.keys()))
56
+ duration = st.slider("Meditation duration (minutes):", 5, 30, 10)
57
+
58
+ if st.button("Start Meditation"):
59
+ with st.spinner(f"Meditating for {duration} minutes..."):
60
+ st.text(meditation_types[selected_meditation])
61
+ meditation_progress = st.progress(0)
62
+ for i in range(duration * 60):
63
+ time.sleep(1)
64
+ meditation_progress.progress((i + 1) / (duration * 60))
65
+ st.success("Meditation complete. How do you feel?")
66
+
67
+ def mindfulness_exercises_page():
68
+ st.header("Mindfulness Exercises")
69
+
70
+ exercises = [
71
+ "Take three deep breaths, focusing on the sensation of air entering and leaving your body.",
72
+ "Notice five things you can see, four things you can touch, three things you can hear, two things you can smell, and one thing you can taste.",
73
+ "Spend one minute focusing solely on the present moment, acknowledging thoughts without judgment.",
74
+ "Practice mindful walking by paying attention to each step and the sensations in your feet.",
75
+ "Eat a small snack mindfully, noticing the taste, texture, and aroma with each bite."
76
+ ]
77
+
78
+ selected_exercise = st.selectbox("Choose a mindfulness exercise:", exercises)
79
+
80
+ if st.button("Start Exercise"):
81
+ with st.spinner("Practicing mindfulness..."):
82
+ st.text(selected_exercise)
83
+ time.sleep(60) # Give the user a minute to practice
84
+ st.success("Exercise complete. Remember to carry this mindfulness with you throughout your day.")
85
+
86
+ def binaural_beats_page():
87
+ st.header("Binaural Beats Generator")
88
+
89
+ st.write("Binaural beats are created when two slightly different frequencies are played in each ear, potentially influencing brainwave activity.")
90
+
91
+ base_freq = st.slider("Base Frequency (Hz):", 100, 500, 200)
92
+ beat_freq = st.slider("Desired Beat Frequency (Hz):", 1, 40, 10)
93
+ duration = st.slider("Duration (seconds):", 30, 300, 60)
94
+
95
+ if st.button("Generate Binaural Beat"):
96
+ with st.spinner("Generating binaural beat..."):
97
+ audio_data = generate_binaural_beat(base_freq, base_freq + beat_freq, duration * 1000)
98
+ st.audio(audio_data, format='audio/wav')
99
+ st.markdown(get_binary_file_downloader_html(audio_data, f"binaural_beat_{base_freq}_{beat_freq}Hz"), unsafe_allow_html=True)
100
+
101
+ def affirmations_page():
102
+ st.header("Positive Affirmations")
103
+
104
+ predefined_affirmations = [
105
+ "I am capable of achieving great things.",
106
+ "Every day, I'm getting stronger and more confident.",
107
+ "I trust in my abilities and embrace new challenges.",
108
+ "I radiate positivity and attract positive experiences.",
109
+ "I am worthy of love, respect, and success."
110
+ ]
111
+
112
+ affirmation_type = st.radio("Choose affirmation type:", ["Predefined", "Custom"])
113
+
114
+ if affirmation_type == "Predefined":
115
+ affirmation = st.selectbox("Select an affirmation:", predefined_affirmations)
116
+ else:
117
+ affirmation = st.text_input("Enter your custom affirmation:")
118
+
119
+ repetitions = st.slider("Number of repetitions:", 1, 50, 10)
120
+ interval = st.slider("Interval between repetitions (seconds):", 1, 10, 3)
121
+
122
+ if st.button("Start Affirmations"):
123
+ with st.spinner(f"Repeating affirmation {repetitions} times..."):
124
+ for i in range(repetitions):
125
+ st.write(affirmation)
126
+ time.sleep(interval)
127
+ st.success("Affirmation session complete. Carry this positive energy with you!")
128
+
129
+ if __name__ == "__main__":
130
+ main()
pages/mind_palace.py ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import random
3
+ from langchain_community.chat_models import ChatOpenAI
4
+ from langchain.schema import HumanMessage, SystemMessage
5
+ from langchain.document_loaders import TextLoader, UnstructuredFileLoader
6
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
+ from langchain.embeddings import HuggingFaceEmbeddings
8
+ from langchain.vectorstores import FAISS
9
+ import os
10
+ from dotenv import load_dotenv
11
+ import json
12
+ from tenacity import retry, stop_after_attempt, wait_fixed
13
+ from streamlit_chat import message
14
+ from gtts import gTTS
15
+ import io
16
+ from PyPDF2 import PdfReader
17
+ import docx2txt
18
+ import logging
19
+ import tempfile
20
+
21
+ logging.basicConfig(level=logging.INFO)
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # Load environment variables
25
+ load_dotenv()
26
+
27
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
28
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
29
+
30
+ # Initialize the models
31
+ chat = ChatOpenAI(
32
+ model="tiiuae/falcon-180B-chat",
33
+ api_key=AI71_API_KEY,
34
+ base_url=AI71_BASE_URL,
35
+ streaming=True,
36
+ )
37
+
38
+ # Use SentenceTransformers for embeddings
39
+ embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
40
+
41
+ def process_document(file):
42
+ content = ""
43
+ file_extension = file.name.split('.')[-1].lower()
44
+
45
+ if file_extension == 'txt':
46
+ content = file.getvalue().decode('utf-8')
47
+ elif file_extension == 'pdf':
48
+ try:
49
+ pdf_reader = PdfReader(io.BytesIO(file.getvalue()))
50
+ for page in pdf_reader.pages:
51
+ content += page.extract_text()
52
+ except Exception as e:
53
+ st.error(f"Error processing PDF: {str(e)}")
54
+ return None
55
+ elif file_extension == 'docx':
56
+ content = docx2txt.process(io.BytesIO(file.getvalue()))
57
+ else:
58
+ st.error(f"Unsupported file type: {file_extension}")
59
+ return None
60
+
61
+ if not content.strip():
62
+ st.warning("The uploaded file appears to be empty or unreadable. Please check the file and try again.")
63
+ return None
64
+
65
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
66
+ chunks = text_splitter.split_text(content)
67
+
68
+ if not chunks:
69
+ st.warning("Unable to extract meaningful content from the file. Please try a different file.")
70
+ return None
71
+
72
+ vectorstore = FAISS.from_texts(chunks, embeddings)
73
+
74
+ return vectorstore, content
75
+
76
+ @retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
77
+ def generate_mind_palace(topic, learning_style, user_preferences, content=None):
78
+ system_message = f"""
79
+ You are an expert in creating memorable and personalized mind palaces to aid in learning and retention.
80
+ The user wants to learn about '{topic}' and their preferred learning style is '{learning_style}'.
81
+ Their personal preferences are: {user_preferences}
82
+ Create a vivid and easy-to-remember mind palace description that incorporates the topic, caters to the user's learning style, and aligns with their preferences.
83
+ The mind palace should have 5-7 interconnected rooms or areas, each representing a key aspect of the topic.
84
+ For each room, provide:
85
+ 1. A catchy and memorable name related to the topic
86
+ 2. A vivid description that incorporates the user's preferences and makes use of multiple senses
87
+ 3. 3-5 key elements or objects in the room that represent important information
88
+ 4. How these elements relate to the topic
89
+ 5. A simple and effective memory technique or association specific to the user's learning style
90
+
91
+ Ensure that the mind palace is coherent, with a logical flow between rooms. Use vivid imagery, familiar concepts, and emotional connections to make it more memorable.
92
+
93
+ Format your response as a JSON object with the following structure:
94
+ {{
95
+ "palace_name": "Catchy Name of the Mind Palace",
96
+ "rooms": [
97
+ {{
98
+ "name": "Memorable Room Name",
99
+ "description": "Vivid description of the room",
100
+ "elements": [
101
+ {{
102
+ "name": "Striking Element Name",
103
+ "description": "How this element relates to the topic",
104
+ "memory_technique": "A simple and effective memory technique or association"
105
+ }}
106
+ ]
107
+ }}
108
+ ]
109
+ }}
110
+
111
+ Ensure that your response is a valid JSON object. Do not include any text before or after the JSON object.
112
+ """
113
+
114
+ messages = [
115
+ SystemMessage(content=system_message),
116
+ HumanMessage(content=f"Create a memorable mind palace for the topic: {topic}")
117
+ ]
118
+
119
+ if content:
120
+ messages.append(HumanMessage(content=f"Use this additional context to enhance the mind palace, focusing on the most important and memorable aspects: {content[:2000]}"))
121
+
122
+ try:
123
+ response = chat.invoke(messages)
124
+ json_response = json.loads(response.content)
125
+ return json_response
126
+ except json.JSONDecodeError as e:
127
+ st.error(f"Error decoding JSON response: {str(e)}")
128
+ st.error("Raw response content:")
129
+ st.error(response.content)
130
+ raise
131
+
132
+ def generate_audio_description(mind_palace_data):
133
+ description = f"Welcome to your personalized and memorable mind palace: {mind_palace_data['palace_name']}. Let's take a journey through your palace, using vivid imagery and your preferred learning style to make it unforgettable. "
134
+ for room in mind_palace_data['rooms']:
135
+ description += f"We're entering the {room['name']}. {room['description']} "
136
+ for element in room['elements']:
137
+ description += f"Focus on the {element['name']}. {element['description']} To remember this, use this simple technique: {element['memory_technique']} Take a moment to really visualize and feel this connection. "
138
+ description += "Now, let's move to the next room, carrying these vivid images with us. "
139
+ description += "We've completed our tour of your mind palace. Take a deep breath and recall the journey we've just taken, visualizing each room and its striking elements."
140
+
141
+ tts = gTTS(text=description, lang='en', slow=False)
142
+ fp = io.BytesIO()
143
+ tts.write_to_fp(fp)
144
+ fp.seek(0)
145
+
146
+ return fp
147
+
148
+ def main():
149
+ st.set_page_config(page_title="S.H.E.R.L.O.C.K. Memorable Mind Palace Generator", layout="wide")
150
+
151
+ # Custom CSS for dark theme
152
+ st.markdown("""
153
+ <style>
154
+ .main {
155
+ background-color: #1E1E1E;
156
+ color: #FFFFFF;
157
+ }
158
+ .stButton>button {
159
+ background-color: #4CAF50;
160
+ color: white;
161
+ font-weight: bold;
162
+ }
163
+ .stTextInput>div>div>input, .stTextArea textarea {
164
+ background-color: #2E2E2E;
165
+ color: #FFFFFF;
166
+ }
167
+ .room-expander {
168
+ background-color: #2E2E2E;
169
+ border-radius: 5px;
170
+ padding: 10px;
171
+ margin-bottom: 10px;
172
+ }
173
+ .stSelectbox>div>div>select {
174
+ background-color: #2E2E2E;
175
+ color: #FFFFFF;
176
+ }
177
+ </style>
178
+ """, unsafe_allow_html=True)
179
+
180
+ # Sidebar
181
+ with st.sidebar:
182
+ st.title("S.H.E.R.L.O.C.K.")
183
+ st.subheader("Memorable Mind Palace Generator")
184
+
185
+ st.markdown("---")
186
+ st.markdown("How to use your Memorable Mind Palace:")
187
+ st.markdown("""
188
+ 1. Choose to enter a topic or upload a document.
189
+ 2. Select your learning style and enter your preferences.
190
+ 3. Generate your personalized, easy-to-remember mind palace.
191
+ 4. Listen to the vivid audio description and imagine each room.
192
+ 5. Explore the detailed text description, focusing on the striking elements.
193
+ 6. Use the chat to reinforce your understanding of the mind palace.
194
+ 7. Practice recalling information by mentally walking through your palace, using the memory techniques provided.
195
+ """)
196
+
197
+ st.markdown("---")
198
+ st.markdown("Powered by Falcon-180B and SentenceTransformers")
199
+
200
+ # Main content
201
+ st.title("S.H.E.R.L.O.C.K. Memorable Mind Palace Generator")
202
+
203
+ st.write("""
204
+ Welcome to the Memorable Mind Palace Generator! This tool will help you create a vivid and easy-to-remember
205
+ mind palace to enhance your learning and memory retention. Choose to enter a topic or upload a document,
206
+ select your preferred learning style, and enter your personal preferences. We'll generate a unique,
207
+ unforgettable mind palace tailored just for you.
208
+ """)
209
+
210
+ input_method = st.radio("Choose your input method:", ["Enter a topic", "Upload a document"])
211
+
212
+ if input_method == "Enter a topic":
213
+ topic = st.text_input("Enter the topic you want to learn:")
214
+ uploaded_file = None
215
+ else:
216
+ topic = None
217
+ uploaded_file = st.file_uploader("Upload a document to memorize", type=['txt', 'md', 'pdf', 'docx'])
218
+
219
+ learning_style = st.selectbox("Choose your preferred learning style:",
220
+ ["Visual", "Auditory", "Kinesthetic", "Reading/Writing"])
221
+
222
+ st.write("""
223
+ Learning Styles:
224
+ - Visual: You learn best through images, diagrams, and spatial understanding. We'll create vivid mental pictures.
225
+ - Auditory: You prefer learning through listening and speaking. We'll focus on memorable sounds and verbal associations.
226
+ - Kinesthetic: You learn by doing, moving, and touching. We'll incorporate imaginary physical sensations and movements.
227
+ - Reading/Writing: You learn best through words. We'll use powerful written descriptions and word associations.
228
+ """)
229
+
230
+ user_preferences = st.text_area("Enter your personal preferences (e.g., favorite places, hobbies, movies, or anything that resonates with you):")
231
+
232
+ if st.button("Generate Memorable Mind Palace"):
233
+ with st.spinner("Crafting your unforgettable mind palace..."):
234
+ content = None
235
+ if uploaded_file is not None:
236
+ vectorstore, content = process_document(uploaded_file)
237
+ if vectorstore is None:
238
+ st.error("Failed to process the uploaded document. Please try again with a different file.")
239
+ return
240
+ topic = "Document Content"
241
+ elif topic is None or topic.strip() == "":
242
+ st.error("Please enter a topic or upload a document.")
243
+ return
244
+
245
+ try:
246
+ mind_palace_data = generate_mind_palace(topic, learning_style, user_preferences, content)
247
+ if mind_palace_data is None:
248
+ st.error("Failed to generate the mind palace. Please try again.")
249
+ return
250
+
251
+ st.session_state.mind_palace = mind_palace_data
252
+ st.session_state.chat_history = []
253
+
254
+ # Generate audio description with selected voice
255
+ with st.spinner("Creating a vivid audio guide for your mind palace..."):
256
+ audio_fp = generate_audio_description(mind_palace_data)
257
+ st.session_state.mind_palace_audio = audio_fp
258
+ except Exception as e:
259
+ logger.error(f"An error occurred while generating the mind palace: {str(e)}")
260
+ st.error(f"An error occurred while generating the mind palace. Please try again.")
261
+ return
262
+
263
+ if 'mind_palace' in st.session_state:
264
+ mind_palace_data = st.session_state.mind_palace
265
+
266
+ st.subheader(f"Your Memorable Mind Palace: {mind_palace_data['palace_name']}")
267
+
268
+ # Audio player
269
+ if 'mind_palace_audio' in st.session_state:
270
+ try:
271
+ st.audio(st.session_state.mind_palace_audio, format='audio/wav')
272
+ st.write("πŸ‘† Listen to the vivid audio guide and imagine your mind palace. Close your eyes and immerse yourself in this mental journey.")
273
+ except Exception as e:
274
+ logger.error(f"Error playing audio: {str(e)}")
275
+ st.warning("There was an issue playing the audio. You can still explore the text description of your mind palace.")
276
+
277
+ # Text description
278
+ for room in mind_palace_data['rooms']:
279
+ with st.expander(f"Room: {room['name']}", expanded=True):
280
+ st.markdown(f"**Description:** {room['description']}")
281
+ st.markdown("**Key Elements:**")
282
+ for element in room['elements']:
283
+ st.markdown(f"- **{element['name']}:** {element['description']}")
284
+ st.markdown(f" *Memory Technique:* {element['memory_technique']}")
285
+
286
+ st.success("Your memorable mind palace has been generated successfully! Take some time to walk through it mentally, focusing on the vivid details and connections.")
287
+
288
+ # Chat interface
289
+ st.subheader("Reinforce Your Mind Palace")
290
+
291
+ # Initialize input key if not present
292
+ if 'input_key' not in st.session_state:
293
+ st.session_state.input_key = 0
294
+
295
+ # Display chat history
296
+ if 'chat_history' not in st.session_state:
297
+ st.session_state.chat_history = []
298
+
299
+ for i, (sender, message_text) in enumerate(st.session_state.chat_history):
300
+ if sender == "user":
301
+ message(message_text, is_user=True, key=f"{i}_user")
302
+ else:
303
+ message(message_text, key=f"{i}_assistant")
304
+
305
+ # User input text box with dynamic key
306
+ user_input = st.text_input("Ask a question or request a memory reinforcement exercise:", key=f"user_input_{st.session_state.input_key}")
307
+
308
+ # Ask button below the text input
309
+ ask_button = st.button("Ask")
310
+
311
+ if ask_button and user_input:
312
+ with st.spinner("Generating response to enhance your memory..."):
313
+ # Prepare context for the AI
314
+ context = f"Mind Palace Data: {json.dumps(mind_palace_data)}\n\n"
315
+ if 'uploaded_content' in st.session_state:
316
+ context += f"Uploaded Document Content: {st.session_state.uploaded_content}\n\n"
317
+
318
+ system_message = f"""
319
+ You are an AI assistant helping the user understand and remember their personalized mind palace.
320
+ Use the following context to provide responses that reinforce the vivid imagery and memory techniques used in the mind palace.
321
+ If asked about specific content from the uploaded document, refer to it in your response.
322
+
323
+ {context}
324
+ """
325
+
326
+ response = chat.invoke([
327
+ SystemMessage(content=system_message),
328
+ HumanMessage(content=user_input)
329
+ ])
330
+
331
+ st.session_state.chat_history.append(("user", user_input))
332
+ st.session_state.chat_history.append(("assistant", response.content))
333
+
334
+ # Increment the input key to reset the input field
335
+ st.session_state.input_key += 1
336
+
337
+ # Force a rerun to update the chat history display and reset the input
338
+ st.experimental_rerun()
339
+
340
+ if __name__ == "__main__":
341
+ main()
pages/mnemonics_generation.py ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import random
3
+ from langchain_community.chat_models import ChatOpenAI
4
+ from langchain.schema import HumanMessage, SystemMessage
5
+ from langchain_community.document_loaders import PyPDFLoader, TextLoader, UnstructuredMarkdownLoader, UnstructuredWordDocumentLoader
6
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
+ from langchain_huggingface import HuggingFaceEmbeddings
8
+ from langchain_community.vectorstores import FAISS
9
+ from langchain.chains import RetrievalQA
10
+ import os
11
+ from dotenv import load_dotenv
12
+ import tempfile
13
+ from PIL import Image
14
+ import io
15
+
16
+ # Load environment variables
17
+ load_dotenv()
18
+
19
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
20
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
21
+
22
+ # Initialize the Falcon model
23
+ chat = ChatOpenAI(
24
+ model="tiiuae/falcon-180B-chat",
25
+ api_key=AI71_API_KEY,
26
+ base_url=AI71_BASE_URL,
27
+ streaming=True,
28
+ )
29
+
30
+ # Initialize embeddings
31
+ embeddings = HuggingFaceEmbeddings()
32
+
33
+ def process_documents(uploaded_files):
34
+ documents = []
35
+ for uploaded_file in uploaded_files:
36
+ file_extension = os.path.splitext(uploaded_file.name)[1].lower()
37
+ with tempfile.NamedTemporaryFile(delete=False, suffix=file_extension) as temp_file:
38
+ temp_file.write(uploaded_file.getvalue())
39
+ temp_file_path = temp_file.name
40
+
41
+ if file_extension == '.pdf':
42
+ loader = PyPDFLoader(temp_file_path)
43
+ elif file_extension == '.txt':
44
+ loader = TextLoader(temp_file_path)
45
+ elif file_extension == '.md':
46
+ loader = UnstructuredMarkdownLoader(temp_file_path)
47
+ elif file_extension in ['.doc', '.docx']:
48
+ loader = UnstructuredWordDocumentLoader(temp_file_path)
49
+ else:
50
+ st.warning(f"Unsupported file type: {file_extension}")
51
+ continue
52
+
53
+ documents.extend(loader.load())
54
+ os.unlink(temp_file_path)
55
+
56
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
57
+ texts = text_splitter.split_documents(documents)
58
+
59
+ vectorstore = FAISS.from_documents(texts, embeddings)
60
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
61
+
62
+ qa_chain = RetrievalQA.from_chain_type(
63
+ llm=chat,
64
+ chain_type="stuff",
65
+ retriever=retriever,
66
+ return_source_documents=True
67
+ )
68
+
69
+ return qa_chain
70
+
71
+ def generate_mnemonic(topic, user_preferences):
72
+ prompt = f"""
73
+ Generate a memorable mnemonic for the topic: {topic}.
74
+ Consider the user's preferences: {user_preferences}.
75
+ The mnemonic should be easy to remember and relate to the topic.
76
+ Also provide a brief explanation of how the mnemonic relates to the topic.
77
+ """
78
+ response = chat.invoke([HumanMessage(content=prompt)])
79
+ return response.content
80
+
81
+ def generate_quiz_question(mnemonic):
82
+ quiz_prompt = f"""
83
+ Create a quiz question based on the mnemonic: {mnemonic}
84
+ Format your response as follows:
85
+ Question: [Your question here]
86
+ Answer: [Your answer here]
87
+ """
88
+ quiz_response = chat.invoke([HumanMessage(content=quiz_prompt)])
89
+ content = quiz_response.content.strip()
90
+
91
+ try:
92
+ question_part, answer_part = content.split("Answer:", 1)
93
+ question = question_part.replace("Question:", "").strip()
94
+ answer = answer_part.strip()
95
+ except ValueError:
96
+ question = content
97
+ answer = "Unable to generate a specific answer. Please refer to the mnemonic."
98
+
99
+ return question, answer
100
+
101
+ def generate_image_prompt(mnemonic):
102
+ prompt = f"""
103
+ Create a detailed image prompt for Midjourney based on the mnemonic: {mnemonic}
104
+ The image should visually represent the key elements of the mnemonic.
105
+ """
106
+ response = chat.invoke([HumanMessage(content=prompt)])
107
+ return response.content
108
+
109
+ def main():
110
+ st.set_page_config(page_title="S.H.E.R.L.O.C.K. Mnemonic Generator", page_icon="🧠", layout="wide")
111
+
112
+ # Custom CSS
113
+ st.markdown("""
114
+ <style>
115
+ .stApp {
116
+ background-color: #f0f2f6;
117
+ }
118
+ .main .block-container {
119
+ padding-top: 2rem;
120
+ }
121
+ .stButton>button {
122
+ background-color: #4CAF50;
123
+ color: white;
124
+ font-weight: bold;
125
+ }
126
+ .stTextInput>div>div>input {
127
+ background-color: #ffffff;
128
+ }
129
+ </style>
130
+ """, unsafe_allow_html=True)
131
+
132
+ st.title("🧠 S.H.E.R.L.O.C.K. Mnemonic Generator")
133
+
134
+ # Initialize session state
135
+ if 'generated_mnemonic' not in st.session_state:
136
+ st.session_state.generated_mnemonic = None
137
+ if 'quiz_question' not in st.session_state:
138
+ st.session_state.quiz_question = None
139
+ if 'quiz_answer' not in st.session_state:
140
+ st.session_state.quiz_answer = None
141
+ if 'image_prompt' not in st.session_state:
142
+ st.session_state.image_prompt = None
143
+
144
+ # Sidebar
145
+ with st.sidebar:
146
+ st.header("πŸ“š Document Upload")
147
+ uploaded_files = st.file_uploader("Upload documents (optional)", type=["pdf", "txt", "md", "doc", "docx"], accept_multiple_files=True)
148
+ if uploaded_files:
149
+ qa_chain = process_documents(uploaded_files)
150
+ st.success(f"{len(uploaded_files)} document(s) processed successfully!")
151
+ else:
152
+ qa_chain = None
153
+
154
+ st.header("🎨 User Preferences")
155
+ user_preferences = st.text_area("Enter your interests or preferences:")
156
+
157
+ # Main area
158
+ col1, col2 = st.columns([2, 1])
159
+
160
+ with col1:
161
+ st.header("πŸ” Generate Mnemonic")
162
+ topic = st.text_input("Enter the topic for your mnemonic:")
163
+
164
+ if st.button("Generate Mnemonic"):
165
+ if topic:
166
+ with st.spinner("Generating mnemonic..."):
167
+ mnemonic = generate_mnemonic(topic, user_preferences)
168
+ st.session_state.generated_mnemonic = mnemonic
169
+
170
+ with st.spinner("Generating quiz question..."):
171
+ question, answer = generate_quiz_question(mnemonic)
172
+ st.session_state.quiz_question = question
173
+ st.session_state.quiz_answer = answer
174
+
175
+ with st.spinner("Generating image prompt..."):
176
+ image_prompt = generate_image_prompt(mnemonic)
177
+ st.session_state.image_prompt = image_prompt
178
+ else:
179
+ st.warning("Please enter a topic to generate a mnemonic.")
180
+
181
+ with col2:
182
+ if st.session_state.generated_mnemonic:
183
+ st.header("πŸ“ Generated Mnemonic")
184
+ st.write(st.session_state.generated_mnemonic)
185
+
186
+ # Quiz section
187
+ if st.session_state.quiz_question:
188
+ st.header("🧠 Mnemonic Quiz")
189
+ st.write(st.session_state.quiz_question)
190
+ user_answer = st.text_input("Your answer:")
191
+ if st.button("Submit Answer"):
192
+ if user_answer.lower() == st.session_state.quiz_answer.lower():
193
+ st.success("πŸŽ‰ Correct! Well done.")
194
+ else:
195
+ st.error(f"❌ Not quite. The correct answer is: {st.session_state.quiz_answer}")
196
+
197
+ # Image prompt section
198
+ if st.session_state.image_prompt:
199
+ st.header("πŸ–ΌοΈ Image Prompt")
200
+ st.write(st.session_state.image_prompt)
201
+ st.info("You can use this prompt with Midjourney or other image generation tools to create a visual representation of your mnemonic.")
202
+
203
+ # Document Q&A section
204
+ if qa_chain:
205
+ st.header("πŸ“š Document Q&A")
206
+ user_question = st.text_input("Ask a question about the uploaded document(s):")
207
+ if st.button("Get Answer"):
208
+ with st.spinner("Searching for the answer..."):
209
+ result = qa_chain({"query": user_question})
210
+ st.subheader("Answer:")
211
+ st.write(result["result"])
212
+ st.subheader("Sources:")
213
+ for source in result["source_documents"]:
214
+ st.write(source.page_content)
215
+
216
+ # Mnemonic visualization
217
+ if st.session_state.generated_mnemonic:
218
+ st.header("🎨 Mnemonic Visualization")
219
+ visualization_type = st.selectbox("Choose visualization type:", ["Word Cloud", "Mind Map"])
220
+ if st.button("Generate Visualization"):
221
+ with st.spinner("Generating visualization..."):
222
+ visualization_prompt = f"""
223
+ Create a detailed description of a {visualization_type} based on the mnemonic:
224
+ {st.session_state.generated_mnemonic}
225
+ Describe the layout, key elements, and their relationships.
226
+ """
227
+ visualization_description = chat.invoke([HumanMessage(content=visualization_prompt)]).content
228
+ st.write(visualization_description)
229
+ st.info("You can use this description to create a visual representation of your mnemonic using tools like Canva or Mindmeister.")
230
+
231
+ # Export options
232
+ if st.session_state.generated_mnemonic:
233
+ st.header("πŸ“€ Export Options")
234
+ export_format = st.selectbox("Choose export format:", ["Text", "PDF", "Markdown"])
235
+ if st.button("Export Mnemonic"):
236
+ export_content = f"""
237
+ Topic: {topic}
238
+
239
+ Mnemonic:
240
+ {st.session_state.generated_mnemonic}
241
+
242
+ Quiz Question:
243
+ {st.session_state.quiz_question}
244
+
245
+ Quiz Answer:
246
+ {st.session_state.quiz_answer}
247
+
248
+ Image Prompt:
249
+ {st.session_state.image_prompt}
250
+ """
251
+
252
+ if export_format == "Text":
253
+ st.download_button("Download Text", export_content, file_name="mnemonic_export.txt")
254
+ elif export_format == "PDF":
255
+ # You'd need to implement PDF generation here, for example using reportlab
256
+ st.warning("PDF export not implemented in this example.")
257
+ elif export_format == "Markdown":
258
+ st.download_button("Download Markdown", export_content, file_name="mnemonic_export.md")
259
+
260
+ # Footer
261
+ st.sidebar.markdown("---")
262
+ st.sidebar.markdown("Powered by Falcon-180B and Streamlit")
263
+
264
+ if __name__ == "__main__":
265
+ main()
pages/notes_generation.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ from dotenv import load_dotenv
4
+ from langchain_community.chat_models import ChatOpenAI
5
+ from langchain_community.document_loaders import PyPDFLoader, TextLoader, UnstructuredMarkdownLoader, Docx2txtLoader
6
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
+ from langchain_community.embeddings import HuggingFaceEmbeddings
8
+ from langchain_community.vectorstores import FAISS
9
+ from langchain.chains import RetrievalQA
10
+ from langchain.prompts import PromptTemplate
11
+ import tempfile
12
+ from typing import List, Dict
13
+ import json
14
+ from datetime import datetime
15
+
16
+ # Load environment variables
17
+ load_dotenv()
18
+
19
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
20
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
21
+
22
+ # Initialize the Falcon model
23
+ @st.cache_resource
24
+ def get_llm():
25
+ return ChatOpenAI(
26
+ model="tiiuae/falcon-180B-chat",
27
+ api_key=AI71_API_KEY,
28
+ base_url=AI71_BASE_URL,
29
+ streaming=True,
30
+ )
31
+
32
+ # Initialize embeddings
33
+ @st.cache_resource
34
+ def get_embeddings():
35
+ return HuggingFaceEmbeddings()
36
+
37
+ def process_document(file_content, file_type):
38
+ with tempfile.NamedTemporaryFile(delete=False, suffix=f'.{file_type}') as tmp_file:
39
+ if isinstance(file_content, str):
40
+ tmp_file.write(file_content.encode('utf-8'))
41
+ else:
42
+ tmp_file.write(file_content)
43
+ tmp_file_path = tmp_file.name
44
+
45
+ if file_type == 'pdf':
46
+ loader = PyPDFLoader(tmp_file_path)
47
+ elif file_type == 'txt':
48
+ loader = TextLoader(tmp_file_path)
49
+ elif file_type == 'md':
50
+ loader = UnstructuredMarkdownLoader(tmp_file_path)
51
+ elif file_type == 'docx':
52
+ loader = Docx2txtLoader(tmp_file_path)
53
+ else:
54
+ raise ValueError(f"Unsupported file type: {file_type}")
55
+
56
+ documents = loader.load()
57
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
58
+ texts = text_splitter.split_documents(documents)
59
+
60
+ vectorstore = FAISS.from_documents(texts, get_embeddings())
61
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
62
+
63
+ os.unlink(tmp_file_path)
64
+ return retriever
65
+
66
+ def generate_notes(retriever, topic, style, length):
67
+ prompt_template = f"""
68
+ You are an expert note-taker and summarizer. Your task is to create {style} and {length} notes on the given topic.
69
+ Use the following guidelines:
70
+ 1. Focus on key concepts and important details.
71
+ 2. Use bullet points or numbered lists for clarity.
72
+ 3. Include relevant examples or explanations where necessary.
73
+ 4. Organize the information in a logical and easy-to-follow structure.
74
+ 5. Aim for clarity without sacrificing important information.
75
+
76
+ Context: {{context}}
77
+ Topic: {{question}}
78
+
79
+ Notes:
80
+ """
81
+
82
+ PROMPT = PromptTemplate(
83
+ template=prompt_template,
84
+ input_variables=["context", "question"]
85
+ )
86
+
87
+ chain_type_kwargs = {"prompt": PROMPT}
88
+ qa_chain = RetrievalQA.from_chain_type(
89
+ llm=get_llm(),
90
+ chain_type="stuff",
91
+ retriever=retriever,
92
+ chain_type_kwargs=chain_type_kwargs
93
+ )
94
+
95
+ result = qa_chain({"query": topic})
96
+ return result['result']
97
+
98
+ def save_notes(notes: str, topic: str):
99
+ notes_data = load_notes_data()
100
+ timestamp = datetime.now().isoformat()
101
+ notes_data.append({"topic": topic, "notes": notes, "timestamp": timestamp})
102
+ with open("saved_notes.json", "w") as f:
103
+ json.dump(notes_data, f)
104
+
105
+ def load_notes_data() -> List[Dict]:
106
+ try:
107
+ with open("saved_notes.json", "r") as f:
108
+ return json.load(f)
109
+ except FileNotFoundError:
110
+ return []
111
+
112
+ def main():
113
+ st.set_page_config(page_title="S.H.E.R.L.O.C.K. Notes Generator", layout="wide")
114
+
115
+ st.title("S.H.E.R.L.O.C.K. Notes Generator")
116
+
117
+ st.markdown("""
118
+ This tool helps you generate concise and relevant notes on specific topics.
119
+ You can upload a document or enter text directly.
120
+ """)
121
+
122
+ # Sidebar content
123
+ st.sidebar.title("About S.H.E.R.L.O.C.K.")
124
+ st.sidebar.markdown("""
125
+ S.H.E.R.L.O.C.K. (Summarizing Helper & Effective Research Liaison for Organizing Comprehensive Knowledge)
126
+ is an advanced AI-powered tool designed to assist you in generating comprehensive notes from various sources.
127
+
128
+ Key Features:
129
+ - Multi-format support (PDF, TXT, MD, DOCX)
130
+ - Customizable note generation
131
+ - Intelligent text processing
132
+ - Save and retrieve notes
133
+
134
+ How to use:
135
+ 1. Choose your input method
136
+ 2. Process your document or text
137
+ 3. Enter a topic and customize note style
138
+ 4. Generate and save your notes
139
+
140
+ Enjoy your enhanced note-taking experience!
141
+ """)
142
+
143
+ input_method = st.radio("Choose input method:", ("Upload Document", "Enter Text"))
144
+
145
+ if input_method == "Upload Document":
146
+ uploaded_file = st.file_uploader("Upload a document", type=["pdf", "txt", "md", "docx"])
147
+ if uploaded_file:
148
+ file_type = uploaded_file.name.split('.')[-1].lower()
149
+ file_content = uploaded_file.read()
150
+ st.success("Document uploaded successfully!")
151
+
152
+ with st.spinner("Processing document..."):
153
+ retriever = process_document(file_content, file_type)
154
+ st.session_state.retriever = retriever
155
+ st.success("Document processed!")
156
+ elif input_method == "Enter Text":
157
+ text_input = st.text_area("Enter your text here:", height=200)
158
+ if text_input:
159
+ with st.spinner("Processing text..."):
160
+ retriever = process_document(text_input, 'txt')
161
+ st.session_state.retriever = retriever
162
+ st.success("Text processed!")
163
+
164
+ topic = st.text_input("Enter the topic for note generation:")
165
+
166
+ col1, col2 = st.columns(2)
167
+ with col1:
168
+ style = st.selectbox("Note Style", ["Concise", "Detailed", "Academic", "Casual"])
169
+ with col2:
170
+ length = st.selectbox("Note Length", ["Short", "Medium", "Long"])
171
+
172
+ if st.button("Generate Notes"):
173
+ if topic and hasattr(st.session_state, 'retriever'):
174
+ with st.spinner("Generating notes..."):
175
+ try:
176
+ notes = generate_notes(st.session_state.retriever, topic, style, length)
177
+ st.subheader("Generated Notes:")
178
+ st.markdown(notes)
179
+
180
+ # Download button for the generated notes
181
+ st.download_button(
182
+ label="Download Notes",
183
+ data=notes,
184
+ file_name=f"{topic.replace(' ', '_')}_notes.txt",
185
+ mime="text/plain"
186
+ )
187
+
188
+ # Save notes
189
+ if st.button("Save Notes"):
190
+ save_notes(notes, topic)
191
+ st.success("Notes saved successfully!")
192
+ except Exception as e:
193
+ st.error(f"An error occurred while generating notes: {str(e)}")
194
+ else:
195
+ st.warning("Please upload a document or enter text, and specify a topic before generating notes.")
196
+
197
+ # Display saved notes
198
+ st.sidebar.subheader("Saved Notes")
199
+ saved_notes = load_notes_data()
200
+ for i, note in enumerate(saved_notes):
201
+ if st.sidebar.button(f"{note['topic']} - {note['timestamp'][:10]}", key=f"saved_note_{i}"):
202
+ st.subheader(f"Saved Notes: {note['topic']}")
203
+ st.markdown(note['notes'])
204
+
205
+ st.sidebar.markdown("---")
206
+ st.sidebar.markdown("Powered by Falcon-180B and Streamlit")
207
+
208
+ # Add a footer
209
+ st.markdown("---")
210
+ st.markdown("Created by Your Team Name | Β© 2024")
211
+
212
+ if __name__ == "__main__":
213
+ main()
pages/sherlock_observation.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import random
3
+ from langchain_community.chat_models import ChatOpenAI
4
+ from langchain.schema import HumanMessage, SystemMessage
5
+ from langchain_community.document_loaders import PyPDFLoader, TextLoader
6
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
+ from langchain_huggingface import HuggingFaceEmbeddings
8
+ from langchain_community.vectorstores import FAISS
9
+ from langchain.chains import RetrievalQA
10
+ import os
11
+ from dotenv import load_dotenv
12
+ import tempfile
13
+
14
+ # Load environment variables
15
+ load_dotenv()
16
+
17
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
18
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
19
+
20
+ # Initialize the Falcon model
21
+ chat = ChatOpenAI(
22
+ model="tiiuae/falcon-180B-chat",
23
+ api_key=AI71_API_KEY,
24
+ base_url=AI71_BASE_URL,
25
+ streaming=True,
26
+ )
27
+
28
+ # Initialize embeddings
29
+ embeddings = HuggingFaceEmbeddings()
30
+
31
+ # Expanded list of predefined topics
32
+ PREDEFINED_TOPICS = [
33
+ "Quantum Computing", "Artificial Intelligence Ethics", "Blockchain Technology",
34
+ "Neuroscience", "Climate Change Mitigation", "Space Exploration",
35
+ "Renewable Energy", "Genetic Engineering", "Cybersecurity",
36
+ "Machine Learning", "Nanotechnology", "Robotics",
37
+ "Virtual Reality", "Augmented Reality", "Internet of Things",
38
+ "5G Technology", "Autonomous Vehicles", "Bioinformatics",
39
+ "Cloud Computing", "Data Science", "Artificial General Intelligence",
40
+ "Quantum Cryptography", "3D Printing", "Smart Cities",
41
+ "Biotechnology", "Fusion Energy", "Sustainable Agriculture",
42
+ "Space Tourism", "Quantum Sensors", "Brain-Computer Interfaces",
43
+ "Personalized Medicine", "Synthetic Biology", "Exoplanets",
44
+ "Dark Matter", "CRISPR Technology", "Quantum Internet",
45
+ "Deep Learning", "Edge Computing", "Humanoid Robots",
46
+ "Drone Technology", "Quantum Supremacy", "Neuromorphic Computing",
47
+ "Asteroid Mining", "Bionic Implants", "Smart Materials",
48
+ "Quantum Dots", "Lab-grown Meat", "Vertical Farming",
49
+ "Hyperloop Transportation", "Molecular Nanotechnology", "Quantum Metrology",
50
+ "Artificial Photosynthesis", "Cognitive Computing", "Swarm Robotics",
51
+ "Metamaterials", "Neuroplasticity", "Quantum Machine Learning",
52
+ "Green Hydrogen", "Organ-on-a-Chip", "Bioprinting",
53
+ "Plasma Physics", "Quantum Simulation", "Soft Robotics",
54
+ "Geoengineering", "Exoskeletons", "Programmable Matter",
55
+ "Graphene Applications", "Quantum Sensing", "Neuralink",
56
+ "Holographic Displays", "Quantum Error Correction", "Synthetic Genomes",
57
+ "Carbon Capture and Storage", "Quantum Memory", "Organoids",
58
+ "Artificial Synapses", "Quantum Imaging", "Biosensors",
59
+ "Memristors", "Quantum Annealing", "DNA Data Storage",
60
+ "Cultured Meat", "Quantum Radar", "Neuromorphic Hardware",
61
+ "Quantum Entanglement", "Phytomining", "Biohacking",
62
+ "Topological Quantum Computing", "Neuroprosthetics", "Optogenetics",
63
+ "Quantum Gravity", "Molecular Machines", "Biomimicry",
64
+ "Quantum Teleportation", "Neurogenesis", "Bioelectronics",
65
+ "Quantum Tunneling", "Tissue Engineering", "Bioremediation",
66
+ "Quantum Photonics", "Synthetic Neurobiology", "Nanomedicine",
67
+ "Quantum Biology", "Biogeochemistry", "Molecular Gastronomy",
68
+ "Quantum Thermodynamics", "Nutrigenomics", "Biomechatronics",
69
+ "Quantum Chemistry", "Psychoneuroimmunology", "Nanophotonics",
70
+ "Quantum Optics", "Neuroeconomics", "Bionanotechnology"
71
+ ]
72
+
73
+ def process_document(file):
74
+ with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(file.name)[1]) as temp_file:
75
+ temp_file.write(file.getvalue())
76
+ temp_file_path = temp_file.name
77
+
78
+ if file.name.endswith('.pdf'):
79
+ loader = PyPDFLoader(temp_file_path)
80
+ else:
81
+ loader = TextLoader(temp_file_path)
82
+
83
+ documents = loader.load()
84
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
85
+ texts = text_splitter.split_documents(documents)
86
+
87
+ vectorstore = FAISS.from_documents(texts, embeddings)
88
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
89
+
90
+ qa_chain = RetrievalQA.from_chain_type(
91
+ llm=chat,
92
+ chain_type="stuff",
93
+ retriever=retriever,
94
+ return_source_documents=True
95
+ )
96
+
97
+ os.unlink(temp_file_path)
98
+ return qa_chain
99
+
100
+ def get_sherlock_analysis(topic, qa_chain=None):
101
+ system_prompt = """
102
+ You are Sherlock Holmes, the world's greatest detective and master of observation and deduction.
103
+ Your task is to provide an in-depth analysis of the given topic, offering unique insights on how to approach learning it from the ground up.
104
+ Your analysis should:
105
+ 1. Break down the topic into its fundamental components.
106
+ 2. Identify key concepts and their relationships.
107
+ 3. Suggest a structured approach to learning, starting from first principles.
108
+ 4. Highlight potential challenges and how to overcome them.
109
+ 5. Provide a unique point of view that encourages critical thinking.
110
+ Your response should be detailed, insightful, and encourage a deep understanding of the subject.
111
+ """
112
+
113
+ if qa_chain:
114
+ result = qa_chain({"query": f"Provide a Sherlock Holmes style analysis of the topic: {topic}"})
115
+ response = result['result']
116
+ else:
117
+ messages = [
118
+ SystemMessage(content=system_prompt),
119
+ HumanMessage(content=f"Analyze the following topic: {topic}")
120
+ ]
121
+ response = chat.invoke(messages).content
122
+
123
+ return response
124
+
125
+ def chunk_text(text, max_chunk_size=4000):
126
+ chunks = []
127
+ current_chunk = ""
128
+ for sentence in text.split(". "):
129
+ if len(current_chunk) + len(sentence) < max_chunk_size:
130
+ current_chunk += sentence + ". "
131
+ else:
132
+ chunks.append(current_chunk)
133
+ current_chunk = sentence + ". "
134
+ if current_chunk:
135
+ chunks.append(current_chunk)
136
+ return chunks
137
+
138
+ def main():
139
+ st.set_page_config(page_title="S.H.E.R.L.O.C.K. Observation", page_icon="πŸ”", layout="wide")
140
+
141
+ st.title("πŸ•΅οΈ S.H.E.R.L.O.C.K. Observation")
142
+ st.markdown("*Uncover the depths of any subject with the keen insight of Sherlock Holmes*")
143
+
144
+ col1, col2 = st.columns([2, 1])
145
+
146
+ with col2:
147
+ st.subheader("Choose Your Method")
148
+ method = st.radio("Select input method:", ["Enter Topic", "Upload Document", "Choose from List"])
149
+
150
+ if method == "Enter Topic":
151
+ topic = st.text_input("Enter your topic of interest:")
152
+ elif method == "Upload Document":
153
+ uploaded_file = st.file_uploader("Upload a document (PDF or TXT)", type=["pdf", "txt"])
154
+ if uploaded_file:
155
+ topic = uploaded_file.name
156
+ else:
157
+ topic = st.selectbox("Choose a topic:", PREDEFINED_TOPICS)
158
+
159
+ if st.button("Analyze", key="analyze_button"):
160
+ if method == "Upload Document" and uploaded_file:
161
+ qa_chain = process_document(uploaded_file)
162
+ analysis = get_sherlock_analysis(topic, qa_chain)
163
+ elif topic:
164
+ analysis = get_sherlock_analysis(topic)
165
+ else:
166
+ st.warning("Please provide a topic or upload a document.")
167
+ return
168
+
169
+ col1.markdown("## Sherlock's Analysis")
170
+ chunks = chunk_text(analysis)
171
+ for chunk in chunks:
172
+ col1.markdown(chunk)
173
+
174
+ st.sidebar.image("https://upload.wikimedia.org/wikipedia/commons/c/cd/Sherlock_Holmes_Portrait_Paget.jpg", use_column_width=True)
175
+ st.sidebar.title("About S.H.E.R.L.O.C.K. Observation")
176
+ st.sidebar.markdown("""
177
+ S.H.E.R.L.O.C.K. Observation is your personal detective for any subject.
178
+ It provides:
179
+ - In-depth analysis of topics
180
+ - Unique perspectives on learning approaches
181
+ - First principles breakdown of subjects
182
+ - Critical thinking encouragement
183
+
184
+ Let Sherlock guide you through the intricacies of any field of study!
185
+ """)
186
+
187
+ st.sidebar.markdown("---")
188
+ st.sidebar.markdown("Powered by Falcon-180B and Streamlit")
189
+
190
+ if __name__ == "__main__":
191
+ main()
pages/study_roadmap.py ADDED
@@ -0,0 +1,481 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import networkx as nx
3
+ import plotly.graph_objects as go
4
+ from dotenv import load_dotenv
5
+ from langchain.chat_models import ChatOpenAI
6
+ from langchain.prompts import ChatPromptTemplate
7
+ from langchain.output_parsers import PydanticOutputParser
8
+ from pydantic import BaseModel, Field
9
+ from typing import List, Dict, Optional
10
+ import json
11
+ import pandas as pd
12
+ import time
13
+ from datetime import datetime
14
+ import random
15
+ import re
16
+ from PIL import Image
17
+ import logging
18
+
19
+ # Set up logging
20
+ logging.basicConfig(level=logging.INFO)
21
+ logger = logging.getLogger(__name__)
22
+
23
+ # Load environment variables
24
+ load_dotenv()
25
+
26
+ AI71_BASE_URL = "https://api.ai71.ai/v1/"
27
+ AI71_API_KEY = "api71-api-92fc2ef9-9f3c-47e5-a019-18e257b04af2"
28
+
29
+ # Initialize the Falcon model
30
+ chat = ChatOpenAI(
31
+ model="tiiuae/falcon-180B-chat",
32
+ api_key=AI71_API_KEY,
33
+ base_url=AI71_BASE_URL,
34
+ temperature=0.7,
35
+ )
36
+
37
+ class RoadmapStep(BaseModel):
38
+ title: str
39
+ description: str
40
+ resources: List[Dict[str, str]] = Field(default_factory=list)
41
+ estimated_time: str
42
+ how_to_use: Optional[str] = None
43
+
44
+ class Roadmap(BaseModel):
45
+ steps: Dict[str, RoadmapStep] = Field(default_factory=dict)
46
+
47
+ def clean_json(content):
48
+ # Remove any leading or trailing whitespace
49
+ content = content.strip()
50
+
51
+ # Ensure the content starts and ends with curly braces
52
+ if not content.startswith('{'):
53
+ content = '{' + content
54
+ if not content.endswith('}'):
55
+ content = content + '}'
56
+
57
+ # Remove any newline characters and extra spaces
58
+ content = ' '.join(content.split())
59
+
60
+ # Escape any unescaped double quotes within string values
61
+ content = re.sub(r'(?<!\\)"(?=(?:(?:[^"]*"){2})*[^"]*$)', r'\"', content)
62
+
63
+ return content
64
+
65
+ def ensure_valid_json(content):
66
+ # First, apply our existing cleaning function
67
+ content = clean_json(content)
68
+
69
+ # Use regex to find and fix unquoted property names
70
+ pattern = r'(\{|\,)\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:'
71
+ content = re.sub(pattern, r'\1 "\2":', content)
72
+
73
+ # Replace single quotes with double quotes
74
+ content = content.replace("'", '"')
75
+
76
+ # Attempt to parse the JSON to catch any remaining issues
77
+ try:
78
+ json_obj = json.loads(content)
79
+ return json.dumps(json_obj) # Return a properly formatted JSON string
80
+ except json.JSONDecodeError as e:
81
+ # If we still can't parse it, log the error and return None
82
+ logger.error(f"Failed to parse JSON after cleaning: {str(e)}")
83
+ logger.debug(f"Problematic JSON: {content}")
84
+ return None
85
+
86
+ def generate_roadmap(topic):
87
+ levels = [
88
+ "knowledge",
89
+ "comprehension",
90
+ "application",
91
+ "analysis",
92
+ "synthesis",
93
+ "evaluation"
94
+ ]
95
+
96
+ roadmap = Roadmap()
97
+
98
+ for level in levels:
99
+ try:
100
+ logger.info(f"Generating roadmap step for topic: {topic} at {level} level")
101
+ step = generate_simplified_step(topic, level, chat)
102
+ roadmap.steps[level] = step
103
+ logger.info(f"Added step for {level} level")
104
+
105
+ except Exception as e:
106
+ logger.error(f"Error in generate_roadmap for {level}: {str(e)}")
107
+ step = create_fallback_step(topic, level, chat)
108
+ roadmap.steps[level] = step
109
+
110
+ logger.info("Roadmap generation complete")
111
+ return roadmap
112
+
113
+ def generate_diverse_resources(topic, level):
114
+ encoded_topic = topic.replace(' ', '+')
115
+ encoded_level = level.replace(' ', '+')
116
+
117
+ resource_templates = [
118
+ {"title": "Wikipedia", "url": f"https://en.wikipedia.org/wiki/{topic.replace(' ', '_')}"},
119
+ {"title": "YouTube Overview", "url": f"https://www.youtube.com/results?search_query={encoded_topic}+{encoded_level}"},
120
+ {"title": "Coursera Courses", "url": f"https://www.coursera.org/search?query={encoded_topic}"},
121
+ {"title": "edX Courses", "url": f"https://www.edx.org/search?q={encoded_topic}"},
122
+ {"title": "Brilliant", "url": f"https://brilliant.org/search/?q={encoded_topic}"},
123
+ {"title": "Google Scholar", "url": f"https://scholar.google.com/scholar?q={encoded_topic}"},
124
+ {"title": "MIT OpenCourseWare", "url": f"https://ocw.mit.edu/search/?q={encoded_topic}"},
125
+ {"title": "Khan Academy", "url": f"https://www.khanacademy.org/search?query={encoded_topic}"},
126
+ {"title": "TED Talks", "url": f"https://www.ted.com/search?q={encoded_topic}"},
127
+ {"title": "arXiv Papers", "url": f"https://arxiv.org/search/?query={encoded_topic}&searchtype=all"},
128
+ {"title": "ResearchGate", "url": f"https://www.researchgate.net/search/publication?q={encoded_topic}"},
129
+ {"title": "Academic Earth", "url": f"https://academicearth.org/search/?q={encoded_topic}"},
130
+ ]
131
+
132
+ # Randomly select 5-7 resources
133
+ num_resources = random.randint(5, 7)
134
+ selected_resources = random.sample(resource_templates, num_resources)
135
+
136
+ return selected_resources
137
+
138
+ def create_fallback_step(topic, level, chat):
139
+ def generate_component(prompt, default_value):
140
+ try:
141
+ response = chat.invoke([{"role": "system", "content": prompt}])
142
+ return response.content.strip() or default_value
143
+ except Exception as e:
144
+ logger.error(f"Error generating component: {str(e)}")
145
+ return default_value
146
+
147
+ # Generate title
148
+ title_prompt = f"Create a concise title (max 10 words) for a study step about {topic} at the {level} level of Bloom's Taxonomy."
149
+ default_title = f"{level.capitalize()} Step for {topic}"
150
+ title = generate_component(title_prompt, default_title)
151
+
152
+ # Generate description
153
+ description_prompt = f"""Write a detailed description (500-700 words) for a study step about {topic} at the {level} level of Bloom's Taxonomy.
154
+ Explain what this step entails, how the user should approach it, and why it's important for mastering the topic at this level.
155
+ The description should be specific to {topic} and not a generic explanation of the Bloom's Taxonomy level."""
156
+ default_description = f"In this step, you will focus on {topic} at the {level} level. This involves understanding key concepts and theories related to {topic}. Engage with the provided resources to build a strong foundation."
157
+ description = generate_component(description_prompt, default_description)
158
+
159
+ # Generate estimated time
160
+ time_prompt = f"Estimate the time needed to complete a study step about {topic} at the {level} level of Bloom's Taxonomy. Provide the answer in a format like '3-4 days' or '1-2 weeks'."
161
+ default_time = "3-4 days"
162
+ estimated_time = generate_component(time_prompt, default_time)
163
+
164
+ # Generate how to use
165
+ how_to_use_prompt = f"""Write a paragraph (100-150 words) on how to effectively use the {level} level of Bloom's Taxonomy when studying {topic}.
166
+ Include tips and strategies specific to {topic} at this {level} level."""
167
+ default_how_to_use = f"Explore the provided resources and take notes on key concepts related to {topic}. Practice explaining these concepts in your own words to reinforce your understanding at the {level} level."
168
+ how_to_use = generate_component(how_to_use_prompt, default_how_to_use)
169
+
170
+ return RoadmapStep(
171
+ title=title,
172
+ description=description,
173
+ resources=generate_diverse_resources(topic, level),
174
+ estimated_time=estimated_time,
175
+ how_to_use=how_to_use
176
+ )
177
+
178
+ def create_interactive_graph(roadmap):
179
+ G = nx.DiGraph()
180
+ color_map = {
181
+ 'Knowledge': '#FF6B6B',
182
+ 'Comprehension': '#4ECDC4',
183
+ 'Application': '#45B7D1',
184
+ 'Analysis': '#FFA07A',
185
+ 'Synthesis': '#98D8C8',
186
+ 'Evaluation': '#F9D56E'
187
+ }
188
+
189
+ for i, (level, step) in enumerate(roadmap.steps.items()):
190
+ G.add_node(step.title, level=level.capitalize(), pos=(i, -i))
191
+
192
+ pos = nx.get_node_attributes(G, 'pos')
193
+
194
+ edge_trace = go.Scatter(
195
+ x=[], y=[],
196
+ line=dict(width=2, color='#888'),
197
+ hoverinfo='none',
198
+ mode='lines')
199
+
200
+ node_trace = go.Scatter(
201
+ x=[], y=[],
202
+ mode='markers+text',
203
+ hoverinfo='text',
204
+ marker=dict(
205
+ showscale=False,
206
+ color=[],
207
+ size=30,
208
+ line_width=2
209
+ ),
210
+ text=[],
211
+ textposition="top center"
212
+ )
213
+
214
+ for node in G.nodes():
215
+ x, y = pos[node]
216
+ node_trace['x'] += (x,)
217
+ node_trace['y'] += (y,)
218
+ node_info = f"{node}<br>Level: {G.nodes[node]['level']}"
219
+ node_trace['text'] += (node_info,)
220
+ node_trace['marker']['color'] += (color_map.get(G.nodes[node]['level'], '#CCCCCC'),)
221
+
222
+ fig = go.Figure(data=[edge_trace, node_trace],
223
+ layout=go.Layout(
224
+ title='Interactive Study Roadmap',
225
+ titlefont_size=16,
226
+ showlegend=False,
227
+ hovermode='closest',
228
+ margin=dict(b=20,l=5,r=5,t=40),
229
+ annotations=[dict(
230
+ text="",
231
+ showarrow=False,
232
+ xref="paper", yref="paper",
233
+ x=0.005, y=-0.002
234
+ )],
235
+ xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
236
+ yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
237
+ plot_bgcolor='rgba(0,0,0,0)',
238
+ paper_bgcolor='rgba(0,0,0,0)'
239
+ ))
240
+
241
+ # Add a color legend
242
+ for level, color in color_map.items():
243
+ fig.add_trace(go.Scatter(
244
+ x=[None], y=[None],
245
+ mode='markers',
246
+ marker=dict(size=10, color=color),
247
+ showlegend=True,
248
+ name=level
249
+ ))
250
+
251
+ fig.update_layout(legend=dict(
252
+ orientation="h",
253
+ yanchor="bottom",
254
+ y=1.02,
255
+ xanchor="right",
256
+ x=1
257
+ ))
258
+
259
+ return fig
260
+
261
+ def get_user_progress(roadmap):
262
+ if 'user_progress' not in st.session_state:
263
+ st.session_state.user_progress = {}
264
+
265
+ for level, step in roadmap.steps.items():
266
+ if step.title not in st.session_state.user_progress:
267
+ st.session_state.user_progress[step.title] = 0
268
+
269
+ return st.session_state.user_progress
270
+
271
+ def update_user_progress(step_title, progress):
272
+ st.session_state.user_progress[step_title] = progress
273
+
274
+ def calculate_overall_progress(progress_dict):
275
+ if not progress_dict:
276
+ return 0
277
+ total_steps = len(progress_dict)
278
+ completed_steps = sum(1 for progress in progress_dict.values() if progress == 100)
279
+ return (completed_steps / total_steps) * 100
280
+
281
+ def generate_simplified_step(topic, level, chat):
282
+ prompt = f"""Create a detailed study step for the topic: {topic} at the {level} level of Bloom's Taxonomy.
283
+
284
+ Provide:
285
+ 1. A descriptive title (max 10 words)
286
+ 2. A detailed description (500-700 words) explaining what this step entails, how the user should approach it, and why it's important for mastering the topic at this level. The description should be specific to {topic} and not a generic explanation of the Bloom's Taxonomy level.
287
+ 3. Estimated time for completion (e.g., 3-4 days, 1-2 weeks, etc.)
288
+ 4. A paragraph (100-150 words) on how to use this level effectively, including tips and strategies specific to {topic} at this {level} level
289
+
290
+ Format your response as a valid JSON object with the following structure:
291
+ {{
292
+ "title": "Step title",
293
+ "description": "Step description",
294
+ "estimated_time": "Estimated time",
295
+ "how_to_use": "Paragraph on how to use this level effectively"
296
+ }}
297
+ """
298
+
299
+ try:
300
+ response = chat.invoke([{"role": "system", "content": prompt}])
301
+ valid_json = ensure_valid_json(response.content)
302
+ if valid_json is None:
303
+ raise ValueError("Failed to create valid JSON")
304
+
305
+ step_dict = json.loads(valid_json)
306
+
307
+ # Generate diverse resources
308
+ resources = generate_diverse_resources(topic, level)
309
+
310
+ return RoadmapStep(
311
+ title=step_dict["title"],
312
+ description=step_dict["description"],
313
+ resources=resources,
314
+ estimated_time=step_dict["estimated_time"],
315
+ how_to_use=step_dict["how_to_use"]
316
+ )
317
+ except Exception as e:
318
+ logger.error(f"Error in generate_simplified_step for {level}: {str(e)}")
319
+ return create_fallback_step(topic, level, chat)
320
+
321
+
322
+
323
+ def display_step(step, level, user_progress):
324
+ with st.expander(f"{level.capitalize()}: {step.title}"):
325
+ st.write(f"**Description:** {step.description}")
326
+ st.write(f"**Estimated Time:** {step.estimated_time}")
327
+ st.write("**Resources:**")
328
+ for resource in step.resources:
329
+ st.markdown(f"- [{resource['title']}]({resource['url']})")
330
+ if 'contribution' in resource:
331
+ st.write(f" *{resource['contribution']}*")
332
+
333
+ # Check if how_to_use exists before displaying it
334
+ if step.how_to_use:
335
+ st.write("**How to use this level effectively:**")
336
+ st.write(step.how_to_use)
337
+
338
+ progress = st.slider(f"Progress for {step.title}", 0, 100, user_progress.get(step.title, 0), key=f"progress_{level}")
339
+ update_user_progress(step.title, progress)
340
+
341
+ def main():
342
+ st.set_page_config(page_title="S.H.E.R.L.O.C.K. Study Roadmap Generator", layout="wide")
343
+
344
+ # Custom CSS for dark theme
345
+ st.markdown("""
346
+ <style>
347
+ .stApp {
348
+ background-color: #1E1E1E;
349
+ color: #FFFFFF;
350
+ }
351
+ .stButton>button {
352
+ background-color: #4CAF50;
353
+ color: white;
354
+ border-radius: 5px;
355
+ }
356
+ .stProgress > div > div > div > div {
357
+ background-color: #4CAF50;
358
+ }
359
+ .streamlit-expanderHeader {
360
+ background-color: #2E2E2E;
361
+ color: #FFFFFF;
362
+ }
363
+ .streamlit-expanderContent {
364
+ background-color: #2E2E2E;
365
+ color: #FFFFFF;
366
+ }
367
+ </style>
368
+ """, unsafe_allow_html=True)
369
+
370
+ st.title("🧠 S.H.E.R.L.O.C.K. Study Roadmap Generator")
371
+ st.write("Generate a comprehensive study roadmap based on first principles for any topic.")
372
+
373
+ # Sidebar
374
+ with st.sidebar:
375
+ st.image("https://placekitten.com/300/200", caption="S.H.E.R.L.O.C.K.", use_column_width=True)
376
+ st.markdown("""
377
+ ## About S.H.E.R.L.O.C.K.
378
+ **S**tudy **H**elper for **E**fficient **R**oadmaps and **L**earning **O**ptimization using **C**omprehensive **K**nowledge
379
+
380
+ S.H.E.R.L.O.C.K. is your AI-powered study companion, designed to create personalized learning roadmaps for any topic. It breaks down complex subjects into manageable steps, ensuring a comprehensive understanding from fundamentals to advanced concepts.
381
+ """)
382
+
383
+ st.subheader("πŸ“‹ Todo List")
384
+ if 'todos' not in st.session_state:
385
+ st.session_state.todos = []
386
+
387
+ new_todo = st.text_input("Add a new todo:")
388
+ if st.button("Add Todo", key="add_todo"):
389
+ if new_todo:
390
+ st.session_state.todos.append({"task": new_todo, "completed": False})
391
+ st.success("Todo added successfully!")
392
+ else:
393
+ st.warning("Please enter a todo item.")
394
+
395
+ for i, todo in enumerate(st.session_state.todos):
396
+ col1, col2, col3 = st.columns([0.05, 0.8, 0.15])
397
+ with col1:
398
+ todo['completed'] = st.checkbox("", todo['completed'], key=f"todo_{i}")
399
+ with col2:
400
+ st.write(todo['task'], key=f"todo_text_{i}")
401
+ with col3:
402
+ if st.button("πŸ—‘οΈ", key=f"delete_{i}", help="Delete todo"):
403
+ st.session_state.todos.pop(i)
404
+ st.experimental_rerun()
405
+
406
+ st.subheader("⏱️ Pomodoro Timer")
407
+ pomodoro_duration = st.slider("Pomodoro Duration (minutes)", 1, 60, 25)
408
+ if st.button("Start Pomodoro"):
409
+ progress_bar = st.progress(0)
410
+ for i in range(pomodoro_duration * 60):
411
+ time.sleep(1)
412
+ progress_bar.progress((i + 1) / (pomodoro_duration * 60))
413
+ st.success("Pomodoro completed!")
414
+ if 'achievements' not in st.session_state:
415
+ st.session_state.achievements = set()
416
+ st.session_state.achievements.add("Consistent Learner")
417
+
418
+ topic = st.text_input("πŸ“š Enter the topic you want to master:")
419
+
420
+ if st.button("πŸš€ Generate Roadmap"):
421
+ if topic:
422
+ with st.spinner("🧠 Generating your personalized study roadmap..."):
423
+ try:
424
+ logger.info(f"Starting roadmap generation for topic: {topic}")
425
+ roadmap = generate_roadmap(topic)
426
+ if roadmap and roadmap.steps:
427
+ logger.info("Roadmap generated successfully")
428
+ st.session_state.current_roadmap = roadmap
429
+ st.session_state.current_topic = topic
430
+ st.success("Roadmap generated successfully!")
431
+ else:
432
+ logger.warning("Generated roadmap is empty or invalid")
433
+ st.error("Failed to generate a valid roadmap. Please try again with a different topic.")
434
+ except Exception as e:
435
+ logger.error(f"Error during roadmap generation: {str(e)}", exc_info=True)
436
+ st.error(f"An error occurred while generating the roadmap: {str(e)}")
437
+
438
+ if 'current_roadmap' in st.session_state:
439
+ st.subheader(f"πŸ“Š Study Roadmap for: {st.session_state.current_topic}")
440
+
441
+ roadmap = st.session_state.current_roadmap
442
+ fig = create_interactive_graph(roadmap)
443
+ fig.update_layout(
444
+ plot_bgcolor='rgba(0,0,0,0)',
445
+ paper_bgcolor='rgba(0,0,0,0)',
446
+ font_color='#FFFFFF'
447
+ )
448
+ st.plotly_chart(fig, use_container_width=True)
449
+
450
+ user_progress = get_user_progress(roadmap)
451
+
452
+ levels_description = {
453
+ "knowledge": "Understanding and remembering basic facts and concepts",
454
+ "comprehension": "Grasping the meaning and interpreting information",
455
+ "application": "Using knowledge in new situations",
456
+ "analysis": "Breaking information into parts and examining relationships",
457
+ "synthesis": "Combining elements to form a new whole",
458
+ "evaluation": "Making judgments based on criteria and standards"
459
+ }
460
+
461
+ for level, step in roadmap.steps.items():
462
+ st.header(f"{level.capitalize()} Level")
463
+ st.write(f"**Description:** {levels_description[level]}")
464
+ st.write("**How to master this level:**")
465
+ st.write(f"To master the {level} level, focus on {levels_description[level].lower()}. Engage with the resources provided, practice applying the concepts, and gradually build your understanding. Remember that mastery at this level is crucial before moving to the next.")
466
+ display_step(step, level, user_progress)
467
+
468
+ overall_progress = calculate_overall_progress(user_progress)
469
+ st.progress(overall_progress / 100)
470
+ st.write(f"Overall progress: {overall_progress:.2f}%")
471
+
472
+ roadmap_json = json.dumps(roadmap.dict(), indent=2)
473
+ st.download_button(
474
+ label="πŸ“₯ Download Roadmap as JSON",
475
+ data=roadmap_json,
476
+ file_name="study_roadmap.json",
477
+ mime="application/json"
478
+ )
479
+
480
+ if __name__ == "__main__":
481
+ main()