Microguru / app.py
cryogenic22's picture
Update app.py
d7706d6 verified
import streamlit as st
import os
from learning_platform import EnhancedCourseBuilder
import asyncio
import nest_asyncio
from datetime import datetime
from sqlalchemy.orm import sessionmaker
from models import create_engine
nest_asyncio.apply()
# Database setup
db_url = os.getenv('DATABASE_URL', 'sqlite:///learning_platform.db')
engine = create_engine(db_url)
Session = sessionmaker(bind=engine)
db_session = Session()
# Page config
st.set_page_config(page_title="MicroGuru", page_icon="πŸŽ“", layout="wide")
# Custom CSS
st.markdown("""
<style>
.agent-log {
padding: 8px;
margin: 4px 0;
border-radius: 4px;
background: #f0f7ff;
border-left: 3px solid #1e88e5;
}
.module-card {
padding: 20px;
background: white;
border-radius: 8px;
border-left: 4px solid #4caf50;
margin: 10px 0;
cursor: pointer;
transition: background 0.3s ease;
}
.module-card:hover {
background: #f5f5f5;
}
.loading-icon {
font-size: 1.5em;
color: #1e88e5;
margin-right: 10px;
}
.completed-icon {
font-size: 1.5em;
color: #4caf50;
margin-right: 10px;
}
.progress-bar {
height: 20px;
background: #e0e0e0;
border-radius: 10px;
overflow: hidden;
}
.progress-value {
height: 100%;
background: #4caf50;
transition: width 0.5s ease-in-out;
}
.alert {
position: relative;
padding: 20px;
margin-bottom: 20px;
border-radius: 8px;
border: 1px solid #4caf50;
background-color: #dff0d8;
}
.alert .close {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
font-size: 1.5em;
}
</style>
""", unsafe_allow_html=True)
# Initialize session state
if 'learning_path' not in st.session_state:
st.session_state.learning_path = None
if 'current_module' not in st.session_state:
st.session_state.current_module = 0
if 'agent_logs' not in st.session_state:
st.session_state.agent_logs = []
if 'completed_courses' not in st.session_state:
st.session_state.completed_courses = []
# Initialize platform
api_key = os.environ.get('OPENAI_API_KEY')
if not api_key:
st.error("⚠️ OpenAI API key not found.")
st.stop()
platform = EnhancedCourseBuilder(api_key, db_session)
def display_agent_logs():
"""Display agent activity logs in sidebar"""
with st.sidebar:
st.markdown("### πŸ€– Agent Activity")
for log in st.session_state.agent_logs[-5:]: # Show last 5 logs
st.markdown(f'<div class="agent-log">{log}</div>', unsafe_allow_html=True)
def display_progress_bar():
"""Display course progress bar"""
if st.session_state.learning_path:
path = st.session_state.learning_path
total_modules = len(path.modules)
if total_modules == 0:
st.warning("No modules available in the course.")
return
current = st.session_state.current_module + 1
progress = (current / total_modules) * 100
st.markdown(f"""
<div class="progress-bar">
<div class="progress-value" style="width: {progress}%"></div>
</div>
<p style="text-align: center">Module {current}/{total_modules}</p>
""", unsafe_allow_html=True)
def display_learning_roadmap():
"""Display the learning roadmap with module cards"""
st.markdown("### πŸ›£οΈ Learning Roadmap")
path = st.session_state.learning_path
for i, module in enumerate(path.modules):
status_icon = "" if module.is_complete else "<i class='loading-icon'>&#8987;</i>"
is_clickable = "true" if module.is_complete else "false"
st.markdown(f"""
<div class="module-card" onclick="if({is_clickable}) {{ location.href='#module-{i}'; }}">
{status_icon}<h4 id="module-{i}">{module.title}</h4>
<p>{module.description}</p>
</div>
""", unsafe_allow_html=True)
def display_module_content(module):
"""Display module content and quiz"""
st.markdown(f"""
<div class="module-card">
<h3>{module.title}</h3>
""", unsafe_allow_html=True)
# Display objectives
st.markdown("#### 🎯 Learning Objectives")
for obj in module.objectives:
st.markdown(f"- {obj}")
# Display prerequisites if any
if module.prerequisites:
st.markdown("#### πŸ“š Prerequisites")
for prereq in module.prerequisites:
st.markdown(f"- {prereq}")
if not module.is_complete:
st.info("πŸ”„ Content is being generated... Please wait.")
return
# Display sections
for section in module.sections:
with st.expander(f"πŸ“– {section.title}", expanded=True):
st.markdown(section.content)
st.markdown("#### Key Points")
for point in section.key_points:
st.markdown(f"- {point}")
if section.examples:
st.markdown("#### Examples")
for example in section.examples:
st.code(example)
# Quiz section
st.markdown("""
<div class="quiz-card">
<h4>πŸ“ Knowledge Check</h4>
</div>
""", unsafe_allow_html=True)
for i, question in enumerate(section.quiz_questions):
st.markdown(f"**Q{i+1}: {question['question']}**")
answer = st.radio(
"Choose your answer:",
question['options'],
key=f"quiz_{section.title}_{i}"
)
if st.button("Check Answer", key=f"check_{section.title}_{i}"):
if answer == question['correct_answer']:
st.success(f"βœ… Correct! {question['explanation']}")
else:
st.error(f"❌ Incorrect. {question['explanation']}")
def create_new_course():
"""Handle new course creation"""
st.markdown("### πŸš€ Start Your Learning Journey")
with st.form("course_generator"):
topic = st.text_input("What would you like to learn?")
difficulty = st.select_slider(
"Choose difficulty level:",
options=["beginner", "intermediate", "advanced"],
value="intermediate"
)
if st.form_submit_button("Create Course 🎯"):
with st.spinner('Our AI agents are crafting your personalized course...'):
try:
async def create_course():
return await platform.create_course(topic, difficulty, user_id=1)
path = asyncio.run(create_course())
st.session_state.learning_path = path
st.markdown("""
<div class="alert">
πŸŽ‰ Your course is ready! Modules are being generated.
<span class="close" onclick="this.parentElement.style.display='none';">&times;</span>
</div>
""", unsafe_allow_html=True)
except Exception as e:
st.error(f"Error: {str(e)}")
def main():
st.title("πŸŽ“ MicroGuru")
display_agent_logs()
# Navigation
pages = {
"🏠 Home": create_new_course,
"πŸ“š Current Course": lambda: display_current_course(),
"πŸ† Completed Courses": lambda: display_completed_courses()
}
page = st.sidebar.radio("Navigation", list(pages.keys()))
if page == "πŸ“š Current Course" and not st.session_state.learning_path:
st.info("πŸ‘‹ Welcome! Start by creating a new course from the Home page.")
page = "🏠 Home"
pages[page]()
def display_current_course():
"""Display current course content"""
path = st.session_state.learning_path
if not path or len(path.modules) == 0:
st.warning("No modules are available yet. Please wait for the course generation to complete.")
return
display_learning_roadmap()
display_progress_bar()
col1, col2 = st.columns([7, 3])
with col1:
current_module = path.modules[st.session_state.current_module]
display_module_content(current_module)
with col2:
st.markdown("### πŸ“ Navigation")
# Previous module button
if st.session_state.current_module > 0:
if st.button("⬅️ Previous Module"):
st.session_state.current_module -= 1
st.rerun()
# Next module button
next_idx = st.session_state.current_module + 1
if next_idx < len(path.modules):
if path.modules[next_idx].is_complete:
if st.button("Next Module ➑️"):
st.session_state.current_module = next_idx
st.rerun()
else:
with st.spinner("Generating next module..."):
asyncio.run(
platform.generate_module_content(module_id=path.modules[next_idx].id)
)
st.rerun()
def display_completed_courses():
"""Display completed courses"""
st.markdown("### πŸ† Completed Courses")
if not st.session_state.completed_courses:
st.info("Complete your first course to see it here!")
return
for course in st.session_state.completed_courses:
st.markdown(f"""
<div class="module-card">
<h4>{course.topic}</h4>
<p>{course.description}</p>
<p><small>Completed on: {course.completion_date}</small></p>
</div>
""", unsafe_allow_html=True)
if __name__ == "__main__":
main()