|
|
import streamlit as st |
|
|
import json |
|
|
from datetime import datetime |
|
|
import time |
|
|
import requests |
|
|
|
|
|
|
|
|
API_ENDPOINT = "https://api.example.com/personalize-course" |
|
|
|
|
|
|
|
|
st.set_page_config( |
|
|
page_title="Base Course Personalization", |
|
|
layout="wide", |
|
|
initial_sidebar_state="collapsed", |
|
|
page_icon="π", |
|
|
menu_items={ |
|
|
'Get Help': None, |
|
|
'Report a bug': None, |
|
|
'About': None |
|
|
} |
|
|
) |
|
|
|
|
|
|
|
|
st.markdown(""" |
|
|
<style> |
|
|
/* Dark theme colors */ |
|
|
:root { |
|
|
--background-color: #1E1E1E; |
|
|
--card-background: #2D2D2D; |
|
|
--text-color: #E0E0E0; |
|
|
--accent-color: #4F97FF; |
|
|
--border-color: #444444; |
|
|
--header-color: #4F97FF; |
|
|
--subheader-color: #FFFFFF; |
|
|
} |
|
|
|
|
|
/* Main container styling */ |
|
|
.stApp { |
|
|
background-color: var(--background-color); |
|
|
color: var(--text-color); |
|
|
} |
|
|
|
|
|
/* Headers */ |
|
|
.main-header { |
|
|
font-size: 2.5rem; |
|
|
font-weight: 600; |
|
|
color: var(--header-color); |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.section-header { |
|
|
font-size: 1.5rem; |
|
|
font-weight: 500; |
|
|
color: var(--subheader-color); |
|
|
margin-top: 2rem; |
|
|
margin-bottom: 1rem; |
|
|
padding-bottom: 0.5rem; |
|
|
border-bottom: 1px solid var(--border-color); |
|
|
} |
|
|
|
|
|
/* Form container */ |
|
|
div[data-testid="stForm"] { |
|
|
background-color: var(--card-background); |
|
|
padding: 1.5rem; |
|
|
border-radius: 8px; |
|
|
box-shadow: 0 4px 6px rgba(0,0,0,0.3); |
|
|
} |
|
|
|
|
|
/* Button styling */ |
|
|
.stButton>button { |
|
|
background-color: var(--accent-color); |
|
|
color: white; |
|
|
border-radius: 4px; |
|
|
padding: 0.5rem 2rem; |
|
|
font-weight: 500; |
|
|
border: none; |
|
|
} |
|
|
|
|
|
/* Input fields */ |
|
|
div[data-baseweb="select"] > div { |
|
|
background-color: var(--background-color); |
|
|
border-color: var(--border-color); |
|
|
} |
|
|
|
|
|
.stTextInput > div > div > input { |
|
|
background-color: var(--background-color); |
|
|
color: var(--text-color); |
|
|
border-color: var(--border-color); |
|
|
} |
|
|
|
|
|
.stNumberInput > div > div > input { |
|
|
background-color: var(--background-color); |
|
|
color: var(--text-color); |
|
|
} |
|
|
|
|
|
.stTextArea > div > div > textarea { |
|
|
background-color: var(--background-color); |
|
|
color: var(--text-color); |
|
|
border-color: var(--border-color); |
|
|
} |
|
|
|
|
|
/* Radio buttons */ |
|
|
.stRadio > div { |
|
|
background-color: transparent; |
|
|
} |
|
|
|
|
|
/* Spacing */ |
|
|
div.block-container { |
|
|
padding-top: 2rem; |
|
|
} |
|
|
|
|
|
hr { |
|
|
margin-top: 1rem; |
|
|
margin-bottom: 1rem; |
|
|
border-color: var(--border-color); |
|
|
} |
|
|
|
|
|
/* Footer */ |
|
|
footer { |
|
|
color: #888888; |
|
|
} |
|
|
|
|
|
/* API Response Container */ |
|
|
.api-response { |
|
|
background-color: #1A1A1A; |
|
|
border-radius: 8px; |
|
|
padding: 1rem; |
|
|
border-left: 4px solid var(--accent-color); |
|
|
} |
|
|
|
|
|
/* Custom label colors for Full Name and Gender */ |
|
|
[data-testid="stForm"] label:contains("Full Name"), |
|
|
[data-testid="stForm"] label:contains("Gender") { |
|
|
color: white !important; |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
/* Alternative approach if the above doesn't work */ |
|
|
.st-emotion-cache-1gulkj5 label, /* For Full Name */ |
|
|
.st-emotion-cache-1aumxhf label { /* For Gender */ |
|
|
color: white !important; |
|
|
} |
|
|
</style> |
|
|
""", unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
col1, col2, col3 = st.columns([1, 3, 1]) |
|
|
with col2: |
|
|
st.markdown('<h1 class="main-header">π Base Course Personalization</h1>', unsafe_allow_html=True) |
|
|
st.markdown(""" |
|
|
Complete this form to tailor your learning experience to your preferences. |
|
|
Your personalized course will be generated based on the information you provide below. |
|
|
""") |
|
|
|
|
|
|
|
|
with st.form("personalization_form", clear_on_submit=False): |
|
|
|
|
|
st.markdown('<div class="section-header">π€ Personal Details</div>', unsafe_allow_html=True) |
|
|
|
|
|
col1, col2 = st.columns(2) |
|
|
with col1: |
|
|
user_name = st.text_input("Full Name", placeholder="Enter your full name") |
|
|
user_age = st.number_input("Age", min_value=10, max_value=100, value=22) |
|
|
|
|
|
with col2: |
|
|
user_gender = st.selectbox( |
|
|
"Gender", |
|
|
["male", "female", "other"], |
|
|
index=0, |
|
|
format_func=lambda x: x.capitalize() |
|
|
) |
|
|
tech_knowledge = st.select_slider( |
|
|
"Technical Knowledge", |
|
|
options=["beginner", "intermediate", "advanced"], |
|
|
value="beginner" |
|
|
) |
|
|
|
|
|
st.markdown('<div class="section-header">π― Preferences</div>', unsafe_allow_html=True) |
|
|
col1, col2 = st.columns(2) |
|
|
|
|
|
with col1: |
|
|
preferred_activity = st.text_area( |
|
|
"Preferred Activities", |
|
|
placeholder="e.g., movies, painting, shopping", |
|
|
help="Enter activities separated by commas" |
|
|
) |
|
|
physical_activities = st.text_area( |
|
|
"Physical Activities", |
|
|
placeholder="e.g., badminton, cricket, yoga", |
|
|
help="Enter activities separated by commas" |
|
|
) |
|
|
|
|
|
with col2: |
|
|
food = st.text_area( |
|
|
"Food Preferences", |
|
|
placeholder="e.g., vegetarian, paneer, pizza", |
|
|
help="Enter food items separated by commas" |
|
|
) |
|
|
|
|
|
|
|
|
st.markdown('<div class="section-header">π Learning Preferences</div>', unsafe_allow_html=True) |
|
|
|
|
|
learning_style = st.radio( |
|
|
"Learning Style", |
|
|
["visual", "auditory", "kinesthetic"], |
|
|
index=0, |
|
|
help="Visual: learn by seeing, Auditory: learn by hearing, Kinesthetic: learn by doing", |
|
|
horizontal=True, |
|
|
format_func=lambda x: x.capitalize() |
|
|
) |
|
|
|
|
|
with st.expander("Learn more about learning styles"): |
|
|
st.info(""" |
|
|
- **Visual learners** prefer images, diagrams, and spatial understanding |
|
|
- **Auditory learners** learn best through listening and verbal instructions |
|
|
- **Kinesthetic learners** prefer hands-on activities and learning by doing |
|
|
""") |
|
|
|
|
|
|
|
|
st.markdown('<div class="section-header">π£οΈ Language & Voice Settings</div>', unsafe_allow_html=True) |
|
|
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
with col1: |
|
|
target_language = st.selectbox( |
|
|
"Target Language", |
|
|
["english", "hindi", "telugu", "tamil", "other"], |
|
|
index=0, |
|
|
format_func=lambda x: x.capitalize() |
|
|
) |
|
|
|
|
|
with col2: |
|
|
tts_gender = st.selectbox( |
|
|
"Voice Gender", |
|
|
["male", "female"], |
|
|
index=0, |
|
|
format_func=lambda x: x.capitalize() |
|
|
) |
|
|
|
|
|
with col3: |
|
|
tts_voice = st.selectbox( |
|
|
"Voice Style", |
|
|
["echo", "soprano", "alto", "robotic"], |
|
|
index=0, |
|
|
format_func=lambda x: x.capitalize() |
|
|
) |
|
|
|
|
|
toggle_hinglish = st.toggle("Enable Hinglish", value=True, help="Mix of Hindi and English") |
|
|
|
|
|
|
|
|
st.markdown('<div class="section-header">π» Technical Preferences</div>', unsafe_allow_html=True) |
|
|
|
|
|
programming_language = st.selectbox( |
|
|
"Programming Language", |
|
|
["python", "java", "javascript", "c++", "go"], |
|
|
index=0, |
|
|
format_func=lambda x: x.capitalize() |
|
|
) |
|
|
|
|
|
|
|
|
with st.expander("π Sample Course Structure"): |
|
|
st.markdown(""" |
|
|
### Introduction to Flask |
|
|
1. What is Flask |
|
|
2. Setting Up Flask Environment |
|
|
3. Understanding Flask Project Structure |
|
|
""") |
|
|
|
|
|
|
|
|
st.markdown("<br>", unsafe_allow_html=True) |
|
|
col1, col2, col3 = st.columns([1, 2, 1]) |
|
|
with col2: |
|
|
submitted = st.form_submit_button("Generate Personalized Course", use_container_width=True) |
|
|
|
|
|
|
|
|
if submitted: |
|
|
|
|
|
if not user_name: |
|
|
st.error("Please enter your name") |
|
|
elif not preferred_activity: |
|
|
st.warning("Adding preferred activities will help us personalize your content better") |
|
|
else: |
|
|
|
|
|
with st.spinner("Generating your personalized course..."): |
|
|
time.sleep(1.5) |
|
|
|
|
|
|
|
|
payload = { |
|
|
"personalization_id": 100, |
|
|
"user_id": 30, |
|
|
"course_id": 47, |
|
|
"total_videos": 3, |
|
|
"created_at": datetime.utcnow().isoformat(), |
|
|
"user_profile": { |
|
|
"personalized": True, |
|
|
"user_name": user_name, |
|
|
"user_age": user_age, |
|
|
"user_gender": user_gender, |
|
|
"user_tech_knowledge": tech_knowledge, |
|
|
"user_preferred_activity": preferred_activity, |
|
|
"user_food": food, |
|
|
"user_physical_activities": physical_activities, |
|
|
"learning_style": learning_style, |
|
|
"target_language": target_language, |
|
|
"tts_gender": tts_gender, |
|
|
"tts_voice": tts_voice, |
|
|
"toggle_hinglish": toggle_hinglish, |
|
|
"run_visualization": False, |
|
|
"subtitle": "", |
|
|
"age_group": "18-25", |
|
|
}, |
|
|
"topics": [ |
|
|
{ |
|
|
"topic_id": 10834, |
|
|
"topic_title": "Setting Up Flask Environment", |
|
|
"chapter_id": 647, |
|
|
"chapter_title": "Introduction to Flask", |
|
|
"course_id": 47, |
|
|
"video_url": "https://techlearn-dev.s3.ap-south-1.amazonaws.com/course_videos/47/647/1729064365.mp4", |
|
|
"video_duration": 462, |
|
|
"sequence_number": 2 |
|
|
}, |
|
|
{ |
|
|
"topic_id": 10835, |
|
|
"topic_title": "Understanding Flask Project Structure", |
|
|
"chapter_id": 647, |
|
|
"chapter_title": "Introduction to Flask", |
|
|
"course_id": 47, |
|
|
"video_url": "https://techlearn-dev.s3.ap-south-1.amazonaws.com/course_videos/47/647/1729064412.mp4", |
|
|
"video_duration": 429, |
|
|
"sequence_number": 3 |
|
|
}, |
|
|
{ |
|
|
"topic_id": 10833, |
|
|
"topic_title": "What is Flask", |
|
|
"chapter_id": 647, |
|
|
"chapter_title": "Introduction to Flask", |
|
|
"course_id": 47, |
|
|
"video_url": "https://techlearn-dev.s3.ap-south-1.amazonaws.com/course_videos/47/647/1729064322.mp4", |
|
|
"video_duration": 410, |
|
|
"sequence_number": 1 |
|
|
} |
|
|
], |
|
|
"settings": { |
|
|
"target_language": target_language, |
|
|
"tts_gender": tts_gender, |
|
|
"tts_voice": tts_voice, |
|
|
"toggle_hinglish": toggle_hinglish, |
|
|
"run_visualization": False, |
|
|
"subtitle": "", |
|
|
"programming_language": programming_language, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
try: |
|
|
response = requests.post(API_ENDPOINT, json=payload) |
|
|
|
|
|
if response.status_code == 200: |
|
|
st.success(f"Course personalized successfully for {user_name}!") |
|
|
|
|
|
|
|
|
st.markdown("### π Your personalized course is ready!") |
|
|
st.markdown(f""" |
|
|
**Course**: Introduction to Flask |
|
|
**Programming Language**: {programming_language.capitalize()} |
|
|
**Learning Style**: {learning_style.capitalize()} |
|
|
**Voice**: {tts_voice.capitalize()} ({tts_gender.capitalize()}) |
|
|
""") |
|
|
|
|
|
|
|
|
st.markdown('<div class="section-header">π API Response</div>', unsafe_allow_html=True) |
|
|
st.markdown('<div class="api-response">', unsafe_allow_html=True) |
|
|
st.json(response.json()) |
|
|
st.markdown('</div>', unsafe_allow_html=True) |
|
|
else: |
|
|
st.error(f"API Error: {response.status_code} - {response.text}") |
|
|
except Exception as e: |
|
|
st.error(f"API call failed: {e}") |
|
|
|
|
|
|
|
|
st.warning("Using local data as fallback:") |
|
|
st.json(payload) |
|
|
|
|
|
|
|
|
st.markdown("---") |
|
|
st.caption("Β© 2025 Base Course Personalization | All Rights Reserved") |