import streamlit as st import json import os from dotenv import load_dotenv from typing import Dict, Any # Import the LLM Handler directly from llms_handler import LLMHandler # Load environment variables for OpenAI API key load_dotenv() # Page configuration st.set_page_config( page_title="WizLab Lesson Plan Generator", page_icon="📚", layout="wide" ) # Custom CSS with improved styling st.markdown(""" """, unsafe_allow_html=True) # Initialize the LLM Handler (using Streamlit caching) @st.cache_resource def get_llm_handler(): """Create and cache the LLM Handler.""" return LLMHandler() llm_handler = get_llm_handler() # Header st.title("WizLab Lesson Plan Generator") st.markdown("We help you generate lesson plans tailored to your needs.") # Input section st.header("Input Your Requirements") # Create two columns for input fields col1, col2 = st.columns(2) with col1: topic = st.text_input("Topic", placeholder="e.g., Lesson Plan to teach Spanish numbers as third language to English Speaking students ") age_group_options = ["Elementary (6-11)", "Middle School (12-14)", "High School (15-18)", "Adult Learners", "Other"] age_group_selection = st.selectbox("Target Age Group", age_group_options) if age_group_selection == "Other": age_group = st.text_input("Specify Age Group") else: age_group = age_group_selection language_options = [ "English", "中文 (Mandarin Chinese)" ] language_selection = st.selectbox("Select Output Language", language_options) LANGUAGE_MAPPING = { "中文 (Mandarin Chinese)": "Mandarin Chinese" } # Then in your language selection code: # if language_selection == "Other": # language = st.text_input("Specify Language") #else: # Use mapping if available, otherwise use the base language name language = LANGUAGE_MAPPING.get(language_selection, language_selection) skills_section = ["Reading", "Writing", "Listening", "Speaking", "Other"] skill_focus = st.multiselect("Skills to focus", skills_section) if "Other" in skill_focus: other_skills = st.text_input("Specify Skills to focus") skill_focus.remove("Other") # Remove 'Other' placeholder from the list if other_skills: skill_focus.append(other_skills) # Add user-specified skills with col2: duration = st.text_input("Duration [in minutes]", placeholder="e.g., 25 minutes") proficiency_options = ["Beginner [A1]", "Elementary [A2]", "Intermediate[B1]", "Upper-Intermediate [B2]", "Advanced[C1]", "Proficient [C2]", "Other"] proficiency_selection = st.selectbox("Proficiency Level [CEFR]", proficiency_options) if proficiency_selection == "Other": proficiency = st.text_input("Specify Proficiency Level") else: proficiency = proficiency_selection tech_options = ["Interactive Whiteboard", "Computers/Laptops", "Mobile Devices", "Internet Access", "None", "Other"] tech_selection = st.multiselect("Accessible Tech Resources", tech_options) num_students = st.text_input("Number of students", placeholder="e.g., 30 students") if "Other" in tech_selection: other_tech = st.text_input("Specify Other Technology Requirements") tech_usage = [tech for tech in tech_selection if tech != "Other"] + [other_tech] else: tech_usage = tech_selection def format_content(data): html_content = '
' def format_key(key): """Format key string to be more readable""" # Handle camelCase key = ''.join(' ' + char if char.isupper() else char for char in key).strip() # Replace underscores and normalize spaces key = key.replace('_', ' ').title() return key def process_value(value, level=0): if isinstance(value, dict): return process_dict(value, level) elif isinstance(value, list): return process_list(value, level) else: return f'
{value}
' def process_dict(d, level): content = "" for key, value in d.items(): formatted_key = format_key(key) section_class = "section-level-" + str(level) content += f'
' if level == 0: content += f'
{formatted_key}
' else: content += f'
{formatted_key}
' if isinstance(value, dict) and any(isinstance(v, (dict, list)) for v in value.values()): content += process_value(value, level + 1) elif isinstance(value, list) and any(isinstance(item, dict) for item in value): content += process_value(value, level + 1) else: content += process_value(value, level + 1) content += '
' return content def process_list(lst, level): content = '
' for item in lst: if isinstance(item, dict): content += process_dict(item, level + 1) else: content += f'
{item}
' content += '
' return content html_content += process_dict(data, 0) html_content += '
' return html_content # Generate button if st.button("Generate Lesson Plan", type="primary"): if not topic: st.error("Please enter a topic for the lesson plan.") else: with st.spinner("Generating your lesson plan... This may take a minute or two."): # Set default values if not provided if not duration: duration = "30 minutes" if not proficiency: proficiency = "Intermediate [B1, B2]" if not age_group: age_group = "Elementary (6-11)" if not tech_usage: tech_usage = ["White Board", "Internet Access"] if not language: language = "English" detailed_prompt = f""" Create a lesson plan for teaching '{topic}' to {age_group} students, for a Duration: {duration}, Number of students in the class: {num_students}, Skills to focus in generating lesson plan: {', '.join(skill_focus) if skill_focus else 'All language skills'}, Proficiency Level [CEFR]: {proficiency}, Technology Requirements: {', '.join(tech_usage) if tech_usage else 'None'}, Generate response in {language} Language. """ # Add debug output to see what's happening progress_placeholder = st.empty() try: # Direct integration with LLM Handler # Step 1: Extract and validate input parameters progress_placeholder.text("Step 1/4: Extracting and validating inputs...") input_data = llm_handler.input_extraction_validation(detailed_prompt) progress_placeholder.text("Step 1/4: Input extraction completed") # Step 2: Determine lesson plan structure progress_placeholder.text("Step 2/4: Determining lesson structure...") structure_info = llm_handler.lesson_plan_structure(input_data) progress_placeholder.text("Step 2/4: Structure determination completed") # Step 3: Select activity templates progress_placeholder.text("Step 3/4: Selecting activity templates...") activity_info = llm_handler.activity_template_selection(input_data, structure_info) progress_placeholder.text("Step 3/4: Activity template selection completed") # Step 4: Generate lesson plan progress_placeholder.text("Step 4/4: Generating final lesson plan...") lesson_plan = llm_handler.lesson_plan_generation(input_data, structure_info, activity_info) progress_placeholder.text("Step 4/4: Lesson plan generation completed") # Clear the progress placeholder progress_placeholder.empty() # Notify success st.success("Lesson plan generated successfully!") # Create tabs for different views tab1, tab2 = st.tabs(["Formatted View", "Raw JSON"]) with tab1: st.markdown(format_content(lesson_plan), unsafe_allow_html=True) with tab2: st.json(lesson_plan) # Download button st.download_button( label="Download Lesson Plan", data=json.dumps(lesson_plan, indent=2, ensure_ascii=False), # ensure_ascii=False for proper Unicode handling file_name=f"lesson_plan_{language}.json", mime="application/json" ) except Exception as e: st.error(f"An error occurred: {str(e)}") st.error("Please check if your OpenAI API key is valid and has sufficient credits.") # Footer st.markdown("---") st.markdown("© WizLab Lesson Plan Generator | powered by AI")