"""Main Gradio interface builder""" import gradio as gr from ..config.settings import CSS_PATHS class InterfaceBuilder: """Handles creation of the main Gradio interface""" def __init__(self, app, page_handlers): self.app = app self.page_handlers = page_handlers def create_interface(self): with gr.Blocks(title="Help the LLM be Creative!", css_paths=CSS_PATHS) as demo: # Navigation state management current_page = gr.State("welcome") has_results = gr.State(False) # Session and data state management current_prompt = gr.State(None) session_id = gr.State(None) session_data = gr.State({}) # Navigation bar nav_container = gr.Column(elem_classes=["nav-container"]) with nav_container: with gr.Row(): nav_welcome = gr.Button("🏠 Welcome", elem_classes=["nav-button", "active"]) nav_tutorial = gr.Button("🎯 Tutorial", elem_classes=["nav-button"]) nav_creative = gr.Button("✨ Be Creative", elem_classes=["nav-button"]) nav_gallery = gr.Button("🏆 Gallery", elem_classes=["nav-button"]) nav_results = gr.Button("🎉 Results", elem_classes=["nav-button"], visible=False) nav_session = gr.Button("📊 Progress", elem_classes=["nav-button"], visible=False) # Landing page landing_page = gr.Column(visible=True) with landing_page: with gr.Column(elem_classes=["landing-page"]): gr.Markdown("# 🤖 I'm a poor, boring language model...😢", elem_classes=["landing-title"]) gr.Markdown("# Please help me be creative!", elem_classes=["landing-subtitle"]) with gr.Row(): with gr.Column(scale=1): tutorial_btn = gr.Button("🎯 Take a Quick Tour", elem_classes=["primary-button"]) with gr.Column(scale=1): skip_to_game_btn = gr.Button("🚀 Let's Be Creative Together!", elem_classes=["secondary-button"]) with gr.Row(): with gr.Column(scale=1): gallery_btn = gr.Button("🏆 View Creative Gallery", elem_classes=["secondary-button"]) # Tutorial page tutorial_page = gr.Column(visible=False) with tutorial_page: # Tutorial header with gr.Column(elem_classes=["tutorial-container"]): with gr.Column(elem_classes=["tutorial-header"]): gr.Markdown("# 🎯 Quick Tour", elem_classes=["tutorial-title"]) gr.Markdown("## Here's how you can help me be more creative", elem_classes=["tutorial-subtitle"]) # Current step explanation tutorial_step_explanation = gr.Markdown("", elem_classes=["tutorial-step-explanation"]) # Tutorial interface components (identical to game interface) tutorial_prompt_display = gr.Textbox( label="🎯 Here's what I was asked to write about:", lines=3, interactive=False, elem_classes=["prompt-box"], visible=False ) tutorial_partial_response_display = gr.Textbox( label="🤖 Here's the boring start of my response... (help me continue creatively!)", lines=5, interactive=False, elem_classes=["assistant-box"], visible=False ) tutorial_input_section = gr.Column(visible=False) with tutorial_input_section: with gr.Row(): with gr.Column(scale=4): tutorial_user_input = gr.Textbox( label="✨ Continue where my response above leaves off, and then I'll finish the response after you (max 5 tokens)", placeholder="Type a few words to inspire me...", lines=2, elem_classes=["user-box"], interactive=False ) with gr.Column(scale=1, min_width=150): tutorial_token_counter = gr.Markdown( "**Tokens:** 0/5", elem_classes=["token-counter"] ) tutorial_submit_btn = gr.Button("✨ Help Me Be Creative!", variant="primary", interactive=False) # Tutorial results section tutorial_results_section = gr.Column(visible=False) with tutorial_results_section: tutorial_score_display = gr.HTML() gr.Markdown("## 🔄 See The Difference!") with gr.Row(equal_height=True): with gr.Column(scale=1): gr.Markdown("### 🤖 My Original Boring Version") tutorial_original_response = gr.Textbox( label="What I wrote originally (so boring! 😴)", lines=6, interactive=False, elem_classes=["original-response"] ) with gr.Column(scale=1): gr.Markdown("### ✨ Your Creative Version") tutorial_creative_response = gr.Textbox( label="What I wrote after your creative input! 🎨", lines=6, interactive=False, elem_classes=["results-box"] ) # Tutorial navigation with gr.Column(elem_classes=["tutorial-navigation"]): with gr.Row(): tutorial_prev_btn = gr.Button("⬅️ Previous", elem_classes=["tutorial-button", "secondary"], visible=False) tutorial_next_btn = gr.Button("Next ➡️", elem_classes=["tutorial-button"]) tutorial_play_btn = gr.Button("🚀 Let's Play!", elem_classes=["tutorial-button"], visible=False) tutorial_back_btn = gr.Button("⬅️ Back to Start", elem_classes=["tutorial-button", "secondary"]) # Gallery page gallery_page = gr.Column(visible=False) with gallery_page: with gr.Column(elem_classes=["gallery-container"]): gr.Markdown("# 🏆 Creative Response Gallery", elem_classes=["tutorial-title"]) gr.Markdown("### Showcasing the most creative responses from our community!", elem_classes=["tutorial-subtitle"]) gallery_filter = gr.Dropdown( choices=[("All Creative (≥0.15)", 0.15), ("Great (≥0.3)", 0.3), ("Exceptional (≥0.5)", 0.5), ("Legendary (≥0.7)", 0.7)], value=0.3, label="🎯 Filter by creativity level:", elem_classes=["prompt-box"] ) gallery_display = gr.HTML() with gr.Row(): gallery_refresh_btn = gr.Button("🔄 Refresh Gallery", elem_classes=["tutorial-button"]) gallery_back_btn = gr.Button("⬅️ Back to Start", elem_classes=["tutorial-button", "secondary"]) # Creative page components (initially hidden) creative_page = gr.Column(visible=False) with creative_page: prompt_display = gr.Textbox( label="🎯 Here's what I was asked to do:", lines=3, interactive=False, elem_classes=["prompt-box"] ) partial_response_display = gr.Textbox( label="🤖 Here's the boring start of my response... (help me continue creatively!)", lines=5, interactive=False, elem_classes=["assistant-box"] ) user_input = gr.Textbox( label="✨ Continue where my response above leaves off, and then I'll finish the response after you (max 5 tokens)", placeholder="Type a few words to continue my response...", lines=1, # changed to single line so that "enter" submits the request elem_classes=["user-box"] ) token_counter = gr.Markdown( "**Tokens:** 0/5", elem_classes=["token-counter"] ) token_visualization = gr.Markdown( "Once you start typing, I'll show you what you've written, but in tokens!", elem_classes=["token-visualization"] ) submit_btn = gr.Button("✨ Help Me Be Creative!", variant="primary", size="lg") # Loading and error messages (positioned right after submit button) loading_message = gr.Textbox(visible=False, interactive=False, label="🤖 I'm thinking...", value="Working on your creative response... This is exciting!") error_message = gr.Textbox(visible=False, interactive=False, label="🙋 Oops!", elem_classes=["error-box"]) # Clear section divider gr.HTML("
") # Help and inspiration section gr.Markdown("### 📚 Need Help or Inspiration?", elem_classes=["section-header"]) # Inspire Me section - collapsible gr.Markdown("✨ **Need some inspiration?** See how others have creatively continued this same prompt!", elem_classes=["token-explanation"]) with gr.Accordion("💡 Inspire Me! Show creative examples from others", open=False): inspire_me_btn = gr.Button("🎲 Show Different Examples", elem_classes=["inspire-me-button"]) inspire_me_display = gr.HTML() gr.Markdown( "💡 **About tokens:** Your input is measured in \"tokens\" (how I process text). About 5 tokens ≈ 3-5 words. You'll see your exact count above as you type!", elem_classes=["token-explanation"] ) # Session progress page session_page = gr.Column(visible=False) with session_page: gr.HTML("""

📊 Your Creative Journey

Track your progress, achievements, and creative evolution!

""") # Main session stats display session_main_stats = gr.HTML() # Detailed session history gr.Markdown("## 📈 Your Creative History", elem_classes=["results-section-header"]) session_history_display = gr.HTML() # Session achievements gr.Markdown("## 🏆 Your Achievements", elem_classes=["results-section-header"]) session_achievements_display = gr.HTML() # Back to creative action with gr.Column(elem_classes=["action-section"]): gr.Markdown("### Ready to add to your journey?") back_to_creative_btn = gr.Button("✨ Continue Being Creative!", elem_classes=["primary-button"]) # Results page components results_page = gr.Column(visible=False) with results_page: cosine_distance_display = gr.HTML(visible=False) results_prompt_display = gr.Textbox( label="🎯 Here's what I was asked to write about:", lines=2, interactive=False, elem_classes=["prompt-box"] ) results_partial_display = gr.Textbox( label="🤖 My Boring Start", lines=3, interactive=False, elem_classes=["assistant-box"] ) results_user_input_display = gr.Textbox( label="✨ Your Creative Input", lines=2, interactive=False, elem_classes=["user-box"] ) # Side-by-side comparison gr.Markdown("## 🔄 See The Difference!") with gr.Row(equal_height=True): with gr.Column(scale=1): gr.Markdown("### 🤖 My Original Boring Version") original_response_display = gr.Textbox( label="What I wrote originally (so boring! 😴)", lines=8, interactive=False, elem_classes=["original-response"] ) with gr.Column(scale=1): gr.Markdown("### ✨ Your Creative Version") results_continuation_display = gr.Textbox( label="What I wrote after your creative input! 🎨", lines=8, interactive=False, elem_classes=["results-box"] ) # Visualization gr.Markdown("## 📊 How does your help compare with others?") violin_plot_display = gr.Plot( label="Score Distribution by Token Count", visible=False ) # Collapsible explanation of cosine similarity with gr.Accordion("🤔 How does the scoring work? (Click to learn!)", open=False): gr.Markdown(""" ## The Magic Behind Your Creativity Score! ✨ I use something called **"Cosine Distance"** to see how different your version is from my boring original! **Think of it like this:** 🎯 - I convert both responses into "meaning fingerprints" - Then I measure how far apart these fingerprints are - **Farther apart = More creative = Higher score!** 🏆 **Score Guide:** - **0.7+** = 🌟 WOW! You completely changed my direction! - **0.5+** = 🔥 Amazing! Very different from my original - **0.3+** = ✨ Great job! Nice creative twist - **0.15+** = 💡 Good start! I can see the difference - **Below 0.15** = 🤔 Pretty similar to what I would have written anyway **Pro tip:** The most unexpected words often lead to the highest scores! 🎪 """) with gr.Row(): try_again_same_btn = gr.Button("🔄 Let Me Try Again!", elem_classes=["try-again-button"]) try_again_new_btn = gr.Button("🎯 Give Me A New Challenge!", elem_classes=["try-again-button"]) # Tutorial state tutorial_current_step = gr.State(1) # Wire up all the event handlers self._wire_event_handlers( # Navigation components nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, # Landing page components tutorial_btn, skip_to_game_btn, gallery_btn, # Tutorial components tutorial_next_btn, tutorial_prev_btn, tutorial_play_btn, tutorial_back_btn, # Gallery components gallery_filter, gallery_refresh_btn, gallery_back_btn, # Creative page components user_input, submit_btn, inspire_me_btn, # Results page components try_again_same_btn, try_again_new_btn, # Session page components back_to_creative_btn, # State components current_page, has_results, tutorial_current_step, # Display components landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, prompt_display, partial_response_display, token_counter, token_visualization, loading_message, error_message, inspire_me_display, gallery_display, cosine_distance_display, results_prompt_display, results_partial_display, results_user_input_display, original_response_display, results_continuation_display, violin_plot_display, session_main_stats, session_history_display, session_achievements_display, # Tutorial display components tutorial_step_explanation, tutorial_prompt_display, tutorial_partial_response_display, tutorial_input_section, tutorial_results_section, tutorial_user_input, tutorial_token_counter, tutorial_score_display, tutorial_original_response, tutorial_creative_response, tutorial_prev_btn, tutorial_next_btn, tutorial_play_btn, # State variables current_prompt, session_id, session_data ) # Demo starts with landing page visible return demo def _wire_event_handlers(self, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, tutorial_btn, skip_to_game_btn, gallery_btn, tutorial_next_btn, tutorial_prev_btn, tutorial_play_btn, tutorial_back_btn, gallery_filter, gallery_refresh_btn, gallery_back_btn, user_input, submit_btn, inspire_me_btn, try_again_same_btn, try_again_new_btn, back_to_creative_btn, current_page, has_results, tutorial_current_step, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, prompt_display, partial_response_display, token_counter, token_visualization, loading_message, error_message, inspire_me_display, gallery_display, cosine_distance_display, results_prompt_display, results_partial_display, results_user_input_display, original_response_display, results_continuation_display, violin_plot_display, session_main_stats, session_history_display, session_achievements_display, tutorial_step_explanation, tutorial_prompt_display, tutorial_partial_response_display, tutorial_input_section, tutorial_results_section, tutorial_user_input, tutorial_token_counter, tutorial_score_display, tutorial_original_response, tutorial_creative_response, tutorial_prev_btn_ref, tutorial_next_btn_ref, tutorial_play_btn_ref, current_prompt, session_id, session_data): """Wire up all the event handlers for the interface""" # Wire up landing page buttons tutorial_btn.click( self.page_handlers.show_tutorial, outputs=[ current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, tutorial_step_explanation, tutorial_prompt_display, tutorial_partial_response_display, tutorial_input_section, tutorial_results_section, tutorial_prev_btn_ref, tutorial_next_btn_ref, tutorial_play_btn_ref, tutorial_current_step ] ) skip_to_game_btn.click( self.page_handlers.start_game, inputs=[current_prompt, session_id], outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, prompt_display, partial_response_display, inspire_me_display, current_prompt, session_id] ) # Wire up gallery button (handled at end of function) # Wire up gallery page buttons gallery_back_btn.click( self.page_handlers.back_to_landing, outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, gallery_display] ) gallery_refresh_btn.click( self.page_handlers.show_gallery, inputs=[gallery_filter], outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, gallery_display] ) gallery_filter.change( self.page_handlers.show_gallery, inputs=[gallery_filter], outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, gallery_display] ) # Wire up tutorial page buttons tutorial_back_btn.click( lambda: self.page_handlers.switch_to_page("welcome"), outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) tutorial_play_btn.click( self.page_handlers.load_creative_with_prompt, inputs=[current_prompt, session_id], outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, prompt_display, partial_response_display, inspire_me_display, current_prompt, session_id], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) # Wire up tutorial navigation tutorial_next_btn.click( self.page_handlers.tutorial_next_step, inputs=[tutorial_current_step], outputs=[ tutorial_step_explanation, tutorial_prompt_display, tutorial_partial_response_display, tutorial_input_section, tutorial_user_input, tutorial_token_counter, tutorial_results_section, tutorial_original_response, tutorial_creative_response, tutorial_score_display, tutorial_prev_btn_ref, tutorial_next_btn_ref, tutorial_play_btn_ref, tutorial_current_step ] ) tutorial_prev_btn.click( self.page_handlers.tutorial_prev_step, inputs=[tutorial_current_step], outputs=[ tutorial_step_explanation, tutorial_prompt_display, tutorial_partial_response_display, tutorial_input_section, tutorial_results_section, tutorial_prev_btn_ref, tutorial_next_btn_ref, tutorial_play_btn_ref, tutorial_current_step ] ) submit_btn.click( self.page_handlers.on_submit_start, inputs=[user_input], outputs=[submit_btn, loading_message, error_message, landing_page, gallery_page, creative_page, results_page, cosine_distance_display] ).then( self.page_handlers.on_submit_process, inputs=[user_input, current_prompt, session_id], outputs=[submit_btn, loading_message, error_message, landing_page, gallery_page, creative_page, results_page, cosine_distance_display, results_prompt_display, results_partial_display, results_user_input_display, original_response_display, results_continuation_display, violin_plot_display, current_page, has_results, nav_results, nav_session, nav_welcome, nav_tutorial, nav_creative, nav_gallery] ) user_input.submit( self.page_handlers.on_submit_start, inputs=[user_input], outputs=[submit_btn, loading_message, error_message, landing_page, gallery_page, creative_page, results_page, cosine_distance_display] ).then( self.page_handlers.on_submit_process, inputs=[user_input, current_prompt, session_id], outputs=[submit_btn, loading_message, error_message, landing_page, gallery_page, creative_page, results_page, cosine_distance_display, results_prompt_display, results_partial_display, results_user_input_display, original_response_display, results_continuation_display, violin_plot_display, current_page, has_results, nav_results, nav_session, nav_welcome, nav_tutorial, nav_creative, nav_gallery] ) # Try again button - stay on same prompt, switch to creative page try_again_same_btn.click( self.page_handlers.try_same_prompt, outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, submit_btn, user_input, loading_message, error_message, token_counter, token_visualization], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) # Try new prompt button - new prompt and switch to creative page try_again_new_btn.click( self.page_handlers.try_new_prompt, outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, prompt_display, partial_response_display, submit_btn, user_input, loading_message, error_message, inspire_me_display, current_prompt], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) # Wire up inspire me button inspire_me_btn.click( self.page_handlers.show_inspire_me_examples, inputs=[current_prompt], outputs=[inspire_me_display] ) # Wire up real-time token counter user_input.change( self.page_handlers.update_token_count, inputs=[user_input], outputs=[token_counter, token_visualization] ) # Navigation button handlers nav_welcome.click( lambda: self.page_handlers.switch_to_page("welcome"), outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) nav_tutorial.click( self.page_handlers.load_tutorial_with_content, outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, tutorial_step_explanation, tutorial_prompt_display, tutorial_partial_response_display, tutorial_input_section, tutorial_results_section, tutorial_prev_btn_ref, tutorial_next_btn_ref, tutorial_play_btn_ref, tutorial_current_step], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) nav_creative.click( self.page_handlers.load_creative_with_prompt, inputs=[current_prompt, session_id], outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, prompt_display, partial_response_display, inspire_me_display, current_prompt, session_id], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) nav_gallery.click( self.page_handlers.load_gallery_with_content, outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, gallery_display], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) nav_results.click( lambda: self.page_handlers.switch_to_page("results"), outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) # Update session page when navigating to it nav_session.click( self.page_handlers.navigate_to_session, inputs=[session_id], outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, session_main_stats, session_history_display, session_achievements_display], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) # Update back to creative button in session page back_to_creative_btn.click( lambda: self.page_handlers.switch_to_page("creative"), outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" ) # Wire up gallery button from landing page gallery_btn.click( self.page_handlers.load_gallery_with_content, outputs=[current_page, landing_page, tutorial_page, creative_page, gallery_page, results_page, session_page, nav_welcome, nav_tutorial, nav_creative, nav_gallery, nav_results, nav_session, gallery_display], js="() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }" )