import streamlit as st import json from datetime import datetime import time import requests import boto3 import uuid import os # Load configuration from environment variables (Hugging Face Spaces) API_ENDPOINT = os.getenv("API_ENDPOINT", "https://oau6sljd4l.execute-api.ap-south-1.amazonaws.com/production/process") # DynamoDB configuration for session tracking DYNAMODB_REGION = os.getenv("DYNAMODB_REGION", "ap-south-1") SESSION_TABLE = os.getenv("SESSION_TABLE", "SessionTracking") # AWS Configuration AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID") AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY") AWS_DEFAULT_REGION = os.getenv("AWS_DEFAULT_REGION", "ap-south-1") # Default values DEFAULT_COURSE_ID = int(os.getenv("DEFAULT_COURSE_ID", "47")) DEFAULT_USER_ID = int(os.getenv("DEFAULT_USER_ID", "30")) DEFAULT_PERSONALIZATION_ID = int(os.getenv("DEFAULT_PERSONALIZATION_ID", "100")) API_TIMEOUT = int(os.getenv("API_TIMEOUT", "30")) # Authentication credentials from environment variables VALID_USERNAME = os.getenv("APP_USERNAME") VALID_PASSWORD = os.getenv("APP_PASSWORD") # 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(""" """, unsafe_allow_html=True) # Initialize session state for topics and authentication if 'topics_list' not in st.session_state: st.session_state.topics_list = [{"topic_title": "What is Flask", "chapter_title": "Introduction to Flask"}] if 'session_ids' not in st.session_state: st.session_state.session_ids = [] if 'authenticated' not in st.session_state: st.session_state.authenticated = False # Authentication check if not st.session_state.authenticated: st.markdown('

🔐 Login to Course Personalization

', unsafe_allow_html=True) col1, col2, col3 = st.columns([1, 2, 1]) with col2: with st.container(): st.markdown('
', unsafe_allow_html=True) with st.form("login_form"): st.markdown('
🔑 Authentication Required
', unsafe_allow_html=True) username = st.text_input("Username", placeholder="Enter username", key="login_username") password = st.text_input("Password", placeholder="Enter password", type="password", key="login_password") login_submitted = st.form_submit_button("🚀 Login", use_container_width=True) if login_submitted: if username == VALID_USERNAME and password == VALID_PASSWORD: st.session_state.authenticated = True st.success("Login successful! Redirecting...") time.sleep(1) st.rerun() else: st.error("❌ Invalid username or password") st.markdown('
', unsafe_allow_html=True) st.markdown("---") st.markdown(f"""
Demo Credentials: {VALID_USERNAME} / {VALID_PASSWORD if len(VALID_PASSWORD) <= 10 else VALID_PASSWORD[:3] + '...'}
""", unsafe_allow_html=True) st.stop() # Main app header st.markdown('

📚 Base Course Personalization

', unsafe_allow_html=True) # Logout button in top right col1, col2, col3 = st.columns([2, 1, 1]) with col3: if st.button("🔓 Logout", key="logout_btn"): st.session_state.authenticated = False st.session_state.topics_list = [{"topic_title": "What is Flask", "chapter_title": "Introduction to Flask"}] st.session_state.session_ids = [] st.rerun() # Main Form with st.form("personalization_form", clear_on_submit=False): # Topics Section st.markdown('
📋 Topics Configuration
', unsafe_allow_html=True) # Option to choose single or multiple topics topic_mode = st.radio( "Select Topic Mode", ["Single Topic", "Multiple Topics"], horizontal=True, help="Choose whether to process one topic or multiple topics" ) if topic_mode == "Single Topic": st.markdown('
', unsafe_allow_html=True) st.markdown('
📝 Single Topic Configuration
', unsafe_allow_html=True) col1, col2 = st.columns(2) with col1: single_topic_title = st.text_input("Topic Title", value="What is Flask", help="Enter the topic title", key="single_topic") with col2: single_chapter_title = st.text_input("Chapter Title", value="Introduction to Flask", help="Enter the chapter title", key="single_chapter") st.markdown('
', unsafe_allow_html=True) else: st.markdown("### 📚 Multiple Topics Configuration") # Display existing topics with better styling for i, topic in enumerate(st.session_state.topics_list): st.markdown(f'
', unsafe_allow_html=True) st.markdown(f'
📖 Topic {i+1}
', unsafe_allow_html=True) col1, col2, col3 = st.columns([3, 3, 1]) with col1: topic_title = st.text_input( "Topic Title", value=topic["topic_title"], key=f"topic_title_{i}", help="Enter the topic title" ) st.session_state.topics_list[i]["topic_title"] = topic_title with col2: chapter_title = st.text_input( "Chapter Title", value=topic["chapter_title"], key=f"chapter_title_{i}", help="Enter the chapter title" ) st.session_state.topics_list[i]["chapter_title"] = chapter_title with col3: if len(st.session_state.topics_list) > 1: st.markdown("
", unsafe_allow_html=True) # Add spacing if st.button("🗑️", key=f"remove_{i}", help="Remove this topic"): st.session_state.topics_list.pop(i) st.rerun() st.markdown('
', unsafe_allow_html=True) # Language & Voice Settings Section st.markdown('
🗣️ Language & Voice Settings
', unsafe_allow_html=True) col1, col2, col3 = st.columns(3) with col1: target_language = st.selectbox( "Target Language", ["english", "hindi", "marathi", "kannada", "punjabi","gujarati"], index=0, format_func=lambda x: x.capitalize(), help="Select the target language for content generation" ) with col2: tts_gender = st.selectbox( "Voice Gender", ["male", "female"], index=0, format_func=lambda x: x.capitalize(), help="Select the voice gender for text-to-speech" ) with col3: tts_voice = st.selectbox( "Voice Style", ["onyx", "echo", "soprano", "alto", "robotic"], index=0, format_func=lambda x: x.capitalize(), help="Select the voice style for text-to-speech" ) # Technical Settings Section st.markdown('
💻 Technical Settings
', unsafe_allow_html=True) col1, col2 = st.columns(2) with col1: programming_language = st.selectbox( "Programming Language", ["python", "java", "javascript", "c++", "go"], index=0, format_func=lambda x: x.capitalize(), help="Select the primary programming language for examples" ) with col2: st.markdown("
", unsafe_allow_html=True) # Add spacing toggle_hinglish = st.toggle("Enable Hinglish", value=True, help="Enable mixing of Hindi and English") # Submit button st.markdown("
", unsafe_allow_html=True) col1, col2, col3 = st.columns([1, 2, 1]) with col2: submitted = st.form_submit_button("🚀 Generate Base Course", use_container_width=True) # Add/Remove topic buttons outside the form (for multiple topics) if topic_mode == "Multiple Topics": st.markdown('
', unsafe_allow_html=True) col1, col2, col3, col4 = st.columns([2, 2, 2, 4]) with col1: if st.button(" Add Topic", key="add_topic", help="Add a new topic"): st.session_state.topics_list.append({ "topic_title": f"Topic {len(st.session_state.topics_list) + 1}", "chapter_title": f"Chapter {len(st.session_state.topics_list) + 1}" }) st.rerun() with col2: if st.button(" Reset All", key="reset_topics", help="Reset to default topics"): st.session_state.topics_list = [{"topic_title": "What is Flask", "chapter_title": "Introduction to Flask"}] st.rerun() st.markdown('
', unsafe_allow_html=True) # Handle submission if submitted: # Determine which topics to use based on mode if topic_mode == "Single Topic": topics_to_process = [{"topic_title": single_topic_title, "chapter_title": single_chapter_title}] else: topics_to_process = st.session_state.topics_list # Validate inputs valid_topics = [] for topic in topics_to_process: if topic["topic_title"].strip() and topic["chapter_title"].strip(): valid_topics.append(topic) if not valid_topics: st.error("❌ Please enter at least one topic with both topic title and chapter title") else: # Show loading state with better animation with st.spinner("🎬 Generating your personalized course... This may take a few moments."): progress_bar = st.progress(0) for i in range(100): time.sleep(0.02) # Simulating progress progress_bar.progress(i + 1) # Hardcoded values course_id = DEFAULT_COURSE_ID user_id = DEFAULT_USER_ID personalization_id = DEFAULT_PERSONALIZATION_ID # Create user profile (hardcoded) user_profile = { "personalized": True, "user_name": "System User", "user_age": 25, "user_gender": "male", "user_tech_knowledge": "beginner", "user_preferred_activity": "coding, learning, technology", "user_food": "healthy food, vegetarian", "user_physical_activities": "walking, yoga", "learning_style": "visual", "target_language": target_language, "tts_gender": tts_gender, "tts_voice": tts_voice, "toggle_hinglish": toggle_hinglish, "run_visualization": False, "subtitle": "", "age_group": "18-25" } # Create settings 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, "slide_colour": "blue", "video_type": "base_video" } # Generate topics data with user input for titles and hardcoded values for others topics_data = [] for i, topic in enumerate(valid_topics): topics_data.append({ "topic_id": 10834 + i, # Hardcoded with increment "topic_title": topic["topic_title"].strip(), "chapter_id": 647, # Hardcoded "chapter_title": topic["chapter_title"].strip(), # User input "course_id": course_id, "video_url": f"https://techlearn-dev.s3.ap-south-1.amazonaws.com/course_videos/47/647/172906{4365+i*50}.mp4", # Hardcoded with variation "video_duration": 462 + i*20, # Hardcoded with variation "sequence_number": i + 1, }) # Create payload (always multiple topics structure) 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=API_TIMEOUT) if response.status_code == 200: response_data = response.json() session_ids = response_data.get("session_ids", []) st.success(" Base Course started successfully!") # Store session IDs in session state st.session_state.session_ids.extend(session_ids) # Display results in a clean format st.markdown("### Generation Summary") col1, col2 = st.columns(2) with col1: st.markdown(f""" **Course ID**: `{course_id}` **Programming Language**: {programming_language.capitalize()} **Target Language**: {target_language.capitalize()} """) with col2: st.markdown(f""" **Voice**: {tts_voice.capitalize()} ({tts_gender.capitalize()}) **Topics Count**: {len(valid_topics)} **Hinglish**: {"Enabled" if toggle_hinglish else "Disabled"} """) 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 with st.expander("🐛 Debug Information", expanded=False): st.warning("Request payload for debugging:") st.json(payload)