banao-tech's picture
Update app.py
febc5c7 verified
raw
history blame
19.3 kB
import streamlit as st
import json
from datetime import datetime
import time
import requests
import boto3
import uuid
# API endpoint - Replace with your actual endpoint
API_ENDPOINT = "https://oau6sljd4l.execute-api.ap-south-1.amazonaws.com/production/process"
# DynamoDB configuration for session tracking
DYNAMODB_REGION = "ap-south-1"
SESSION_TABLE = "SessionTracking"
# Set page configuration
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
}
)
# Custom CSS for dark theme styling
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;
text-align: center;
}
.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,
.stNumberInput > div > div > input,
.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);
}
/* API Response Container */
.api-response {
background-color: #1A1A1A;
border-radius: 8px;
padding: 1rem;
border-left: 4px solid var(--accent-color);
}
.session-info {
background-color: var(--card-background);
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
border: 1px solid var(--border-color);
}
</style>
""", unsafe_allow_html=True)
# Initialize session state
if 'session_ids' not in st.session_state:
st.session_state.session_ids = []
# App Header
st.markdown('<h1 class="main-header">πŸ“š Base Course Personalization</h1>', unsafe_allow_html=True)
st.markdown("""
<div style="text-align: center; margin-bottom: 2rem;">
Complete this form to tailor your learning experience to your preferences.<br>
Your personalized course will be generated based on the information you provide below.
</div>
""", unsafe_allow_html=True)
# Main Form
with st.form("personalization_form", clear_on_submit=False):
# Course Information Section
st.markdown('<div class="section-header">πŸ“š Course Information</div>', unsafe_allow_html=True)
col1, col2 = st.columns(2)
with col1:
course_id = st.number_input("Course ID", min_value=1, value=47, help="Enter the course ID")
user_id = st.number_input("User ID", min_value=1, value=30, help="Enter your user ID")
with col2:
personalization_id = st.number_input("Personalization ID", min_value=1, value=100, help="Enter personalization ID")
# Topics Section
st.markdown('<div class="section-header">πŸ“‹ Topics Configuration</div>', unsafe_allow_html=True)
# Option to choose single or multiple topics
topic_mode = st.radio(
"Topic Mode",
["Single Topic", "Multiple Topics"],
horizontal=True,
help="Choose whether to process one topic or multiple topics"
)
if topic_mode == "Single Topic":
st.subheader("Single Topic Details")
col1, col2 = st.columns(2)
with col1:
single_topic_id = st.number_input("Topic ID", min_value=1, value=10834)
single_topic_title = st.text_input("Topic Title", value="Setting Up Flask Environment")
with col2:
single_chapter_id = st.number_input("Chapter ID", min_value=1, value=647)
single_chapter_title = st.text_input("Chapter Title", value="Introduction to Flask")
single_video_url = st.text_input(
"Video URL",
value="https://techlearn-dev.s3.ap-south-1.amazonaws.com/course_videos/47/647/1729064365.mp4"
)
col1, col2 = st.columns(2)
with col1:
single_video_duration = st.number_input("Video Duration (seconds)", min_value=1, value=462)
with col2:
single_sequence_number = st.number_input("Sequence Number", min_value=1, value=1)
else:
st.subheader("Multiple Topics")
num_topics = st.number_input("Number of Topics", min_value=1, max_value=10, value=3)
topics_data = []
for i in range(num_topics):
with st.expander(f"Topic {i+1}"):
col1, col2 = st.columns(2)
with col1:
topic_id = st.number_input(f"Topic ID {i+1}", min_value=1, value=10833+i, key=f"topic_id_{i}")
topic_title = st.text_input(f"Topic Title {i+1}",
value=["What is Flask", "Setting Up Flask Environment", "Understanding Flask Project Structure"][i] if i < 3 else f"Topic {i+1}",
key=f"topic_title_{i}")
with col2:
chapter_id = st.number_input(f"Chapter ID {i+1}", min_value=1, value=647, key=f"chapter_id_{i}")
chapter_title = st.text_input(f"Chapter Title {i+1}", value="Introduction to Flask", key=f"chapter_title_{i}")
video_url = st.text_input(f"Video URL {i+1}",
value=f"https://techlearn-dev.s3.ap-south-1.amazonaws.com/course_videos/47/647/172906{4322+i*50}.mp4",
key=f"video_url_{i}")
col1, col2 = st.columns(2)
with col1:
video_duration = st.number_input(f"Video Duration {i+1} (seconds)", min_value=1, value=410+i*20, key=f"video_duration_{i}")
with col2:
sequence_number = st.number_input(f"Sequence Number {i+1}", min_value=1, value=i+1, key=f"sequence_number_{i}")
topics_data.append({
"topic_id": topic_id,
"topic_title": topic_title,
"chapter_id": chapter_id,
"chapter_title": chapter_title,
"video_url": video_url,
"video_duration": video_duration,
"sequence_number": sequence_number,
"course_id": course_id
})
# Personal Information Section
st.markdown('<div class="section-header">πŸ‘€ User Profile</div>', unsafe_allow_html=True)
col1, col2 = st.columns(2)
with col1:
user_name = st.text_input("Full Name", placeholder="Enter your full name", value="John Doe")
user_age = st.number_input("Age", min_value=10, max_value=100, value=22)
user_gender = st.selectbox(
"Gender",
["male", "female", "other"],
index=0,
format_func=lambda x: x.capitalize()
)
with col2:
tech_knowledge = st.select_slider(
"Technical Knowledge",
options=["beginner", "intermediate", "advanced"],
value="beginner"
)
learning_style = st.radio(
"Learning Style",
["visual", "auditory", "kinesthetic"],
index=0,
horizontal=True,
format_func=lambda x: x.capitalize()
)
# Preferences Section
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",
value="movies, painting, shopping",
help="Enter activities separated by commas"
)
food = st.text_area(
"Food Preferences",
placeholder="e.g., vegetarian, paneer, pizza",
value="vegetarian, paneer, pizza",
help="Enter food items separated by commas"
)
with col2:
physical_activities = st.text_area(
"Physical Activities",
placeholder="e.g., badminton, cricket, yoga",
value="badminton, cricket, yoga",
help="Enter activities separated by commas"
)
# Language & Voice Settings Section
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", "onyx"],
index=4, # Default to "onyx" as used in backend
format_func=lambda x: x.capitalize()
)
col1, col2 = st.columns(2)
with col1:
toggle_hinglish = st.toggle("Enable Hinglish", value=True, help="Mix of Hindi and English")
with col2:
run_visualization = st.toggle("Run Visualization", value=False, help="Enable visualization features")
# Technical Settings Section
st.markdown('<div class="section-header">πŸ’» Technical Settings</div>', unsafe_allow_html=True)
col1, col2, col3 = st.columns(3)
with col1:
programming_language = st.selectbox(
"Programming Language",
["python", "java", "javascript", "c++", "go"],
index=0,
format_func=lambda x: x.capitalize()
)
with col2:
slide_colour = st.selectbox(
"Slide Color",
["blue", "red", "green", "purple", "orange"],
index=0,
format_func=lambda x: x.capitalize()
)
with col3:
video_type = st.selectbox(
"Video Type",
["personalised_video", "standard_video"],
index=0,
format_func=lambda x: x.replace('_', ' ').title()
)
subtitle = st.text_input("Subtitle", placeholder="Optional subtitle for the video", value="")
# Submit button
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)
# Handle submission
if submitted:
# Validate inputs
if not user_name:
st.error("Please enter your name")
elif topic_mode == "Single Topic" and not single_topic_title:
st.error("Please enter a topic title")
else:
# Show loading state
with st.spinner("Generating your personalized course..."):
time.sleep(1.5) # Simulating API call delay
# Create user profile
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": run_visualization,
"subtitle": subtitle,
"age_group": "18-25" if user_age <= 25 else "26-35" if user_age <= 35 else "35+"
}
# Create settings
settings = {
"target_language": target_language,
"tts_gender": tts_gender,
"tts_voice": tts_voice,
"toggle_hinglish": toggle_hinglish,
"run_visualization": run_visualization,
"subtitle": subtitle,
"programming_language": programming_language,
"slide_colour": slide_colour,
"video_type": video_type
}
# Create payload based on topic mode
if topic_mode == "Single Topic":
payload = {
"personalization_id": personalization_id,
"user_profile": user_profile,
"settings": settings,
"topic_data": {
"topic_id": single_topic_id,
"topic_title": single_topic_title,
"chapter_id": single_chapter_id,
"chapter_title": single_chapter_title,
"course_id": course_id,
"video_url": single_video_url,
"video_duration": single_video_duration,
"sequence_number": single_sequence_number
}
}
else:
payload = {
"personalization_id": personalization_id,
"user_id": user_id,
"course_id": course_id,
"total_videos": len(topics_data),
"created_at": datetime.utcnow().isoformat(),
"user_profile": user_profile,
"topics": topics_data,
"settings": settings
}
# Make API call
try:
headers = {
'Content-Type': 'application/json'
}
response = requests.post(API_ENDPOINT, json=payload, headers=headers, timeout=30)
if response.status_code == 200:
response_data = response.json()
session_ids = response_data.get("session_ids", [])
st.success(f"Course personalization started successfully for {user_name}!")
# Store session IDs in session state
st.session_state.session_ids.extend(session_ids)
# Display results in a clean format
st.markdown("### πŸŽ‰ Your personalized course generation has started!")
st.markdown(f"""
**User**: {user_name}
**Course ID**: {course_id}
**Programming Language**: {programming_language.capitalize()}
**Learning Style**: {learning_style.capitalize()}
**Voice**: {tts_voice.capitalize()} ({tts_gender.capitalize()})
**Topics**: {len(topics_data) if topic_mode == "Multiple Topics" else 1}
""")
# Display session IDs
if session_ids:
st.markdown("### πŸ” Session IDs for Tracking")
for i, session_id in enumerate(session_ids, 1):
st.markdown(f'<div class="session-info"><strong>Session {i}:</strong> <code>{session_id}</code></div>', unsafe_allow_html=True)
# Display API response
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_data)
st.markdown('</div>', unsafe_allow_html=True)
# Information about tracking
st.info(f"""
πŸ’‘ **Tracking Information**
You can track the progress of your video generation using the session IDs above.
The processing status will be updated in DynamoDB table: `{SESSION_TABLE}`
Region: `{DYNAMODB_REGION}`
""")
else:
st.error(f"API Error: {response.status_code}")
if response.text:
st.error(f"Error Details: {response.text}")
except requests.exceptions.Timeout:
st.error("Request timed out. Please try again later.")
except requests.exceptions.ConnectionError:
st.error("Connection error. Please check your internet connection.")
except Exception as e:
st.error(f"API call failed: {str(e)}")
# Show payload for debugging
st.warning("Request payload for debugging:")
st.json(payload)
# Display previous session IDs if any
if st.session_state.session_ids:
st.markdown("---")
st.markdown("### πŸ“‹ Previous Session IDs")
for i, session_id in enumerate(st.session_state.session_ids, 1):
st.markdown(f'<div class="session-info"><strong>Session {i}:</strong> <code>{session_id}</code></div>', unsafe_allow_html=True)
# Button to clear session history
if st.button("Clear Session History"):
st.session_state.session_ids = []
st.rerun()
# Footer
st.markdown("---")
st.markdown(f"""
<div style="text-align: center; color: #888888;">
Β© 2025 Base Course Personalization | All Rights Reserved<br>
<small>API Endpoint: {API_ENDPOINT}</small><br>
<small>Session Tracking: {SESSION_TABLE} ({DYNAMODB_REGION})</small>
</div>
""", unsafe_allow_html=True)