| import argparse |
| import json |
| import os |
| import random |
| from functools import partial |
|
|
| import gradio as gr |
|
|
| from utils.poi_search_utils import ( |
| clear_all_selections, |
| get_selection_summary, |
| pois_list, |
| search_pois, |
| toggle_poi_selection, |
| ) |
| from utils.recommender_poi_utils import ( |
| add_poi_to_completed, |
| back_to_recommendations, |
| get_recommendations_ui, |
| show_recommendation_list, |
| view_poi_details, |
| ) |
| from utils.survey_utils import ( |
| feedback_message, |
| handle_all_answered_responses, |
| handle_next_navigation, |
| handle_prev_navigation, |
| handle_submit_survey, |
| submit_exp_feedback, |
| submit_rec_feedback, |
| update_advanced_responses, |
| ) |
| from utils.user_profile_utils import ( |
| login_user, |
| mark_profile_complete, |
| update_user_selected_pois, |
| update_user_sensory_aversions |
| ) |
|
|
| RESOURCE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "resources") |
|
|
| with open(os.path.join(RESOURCE_DIR, "aversion_config_questions.json"), "r") as f: |
| AVERSIONS_QUESTIONS = json.load(f) |
| with open(os.path.join(RESOURCE_DIR, "aversions.json"), "r") as f: |
| AVERSIONS = json.load(f) |
| AVERSIONS = {v["Name"]: v for v in AVERSIONS} |
|
|
|
|
| feedback_message_delay = 1500 |
| js_feedback_message_delay = f"""() => {{ |
| return new Promise(resolve => {{ |
| setTimeout(() => {{ |
| resolve(); |
| }}, {feedback_message_delay}); |
| }}); |
| }}""" |
|
|
|
|
| def create_main_app(self): |
| with gr.Blocks( |
| title="Sistema di Raccomandazione di Punti di Interesse con Personalizzazione Sensoriale", |
| theme=gr.themes.Soft(), |
| css=""" |
| footer{display:none !important} |
| .navigation-container { |
| background: #f8f9fa; |
| padding: 15px; |
| border-radius: 10px; |
| margin-bottom: 20px; |
| border-left: 4px solid #007bff; |
| } |
| .page-container { |
| min-height: 500px; |
| padding: 20px; |
| } |
| .poi-card { |
| transition: all 0.3s ease; |
| } |
| .poi-card:hover { |
| transform: scale(1.02); |
| box-shadow: 0 4px 12px rgba(0,0,0,0.15); |
| } |
| .search-container { |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| padding: 30px; |
| border-radius: 15px; |
| color: white; |
| margin-bottom: 30px; |
| } |
| .continue-button { |
| background-color: #28a745 !important; |
| border-color: #28a745 !important; |
| font-size: 16px !important; |
| padding: 12px 24px !important; |
| } |
| .continue-button:hover { |
| background-color: #218838 !important; |
| border-color: #1e7e34 !important; |
| } |
| .clear-button { |
| background-color: #dc3545 !important; |
| border-color: #dc3545 !important; |
| } |
| .clear-button:hover { |
| background-color: #c82333 !important; |
| border-color: #bd2130 !important; |
| } |
| .sensory-config-main-container { |
| max-width: 900px; |
| margin: 0 auto; |
| padding: 20px; |
| } |
| .header-section { |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| color: white; |
| padding: 20px; |
| border-radius: 12px; |
| margin-bottom: 25px; |
| text-align: center; |
| } |
| .radio-aversion-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); |
| gap: 20px; |
| margin-bottom: 25px; |
| } |
| .radio-aversion-card { |
| background: #f8f9fa; |
| border: 1px solid #e9ecef; |
| border-radius: 12px; |
| padding: 15px; |
| } |
| .continue-to-recommendations-button { |
| background-color: #28a745 !important; |
| border-color: #28a745 !important; |
| font-size: 16px !important; |
| padding: 12px 30px !important; |
| width: 100% !important; |
| } |
| .continue-to-recommendations-button:hover { |
| background-color: #218838 !important; |
| border-color: #1e7e34 !important; |
| } |
| .feedback-indicator { |
| margin-top: 5px; |
| } |
| .back-button-custom { |
| background-color: #32568f !important; |
| border-color: #32568f !important; |
| color: white !important; |
| } |
| .back-button-custom:hover { |
| background-color: #132137 !important; |
| border-color: #132137 !important; |
| } |
| .login-button { |
| background-color: #007bff !important; |
| border-color: #007bff !important; |
| } |
| .login-button:hover { |
| background-color: #0056b3 !important; |
| border-color: #004085 !important; |
| } |
| #poi-search-input { |
| color: black; |
| } |
| """, |
| ) as app: |
| |
| app_user_id = gr.State("") |
| current_page = gr.State("login") |
| current_selected_pois = gr.State(set()) |
| recommendations_state = gr.State([]) |
| selected_poi_index = gr.State(-1) |
| completed_survey_pois = gr.State(set()) |
| current_poi_info = gr.State({}) |
| user_status = gr.State("") |
|
|
| |
| with gr.Column(elem_classes="page-container"): |
| |
| with gr.Column(visible=True) as login_page: |
| gr.Markdown("# 👤 Login / Registrazione") |
|
|
| |
| with gr.Row(): |
| user_id_input = gr.Textbox( |
| placeholder="es: mario_rossi, alice_123, user001...", |
| label="🆔 Inserisci il tuo ID Utente", |
| info="Scegli un ID univoco che userai per accedere al sistema", |
| elem_id="user-id-input", |
| scale=2 |
| ) |
| login_button = gr.Button( |
| "🚀 Accedi / Registrati", |
| variant="primary", |
| elem_classes="action-button login-button", |
| ) |
|
|
| login_status_message = gr.Markdown("", visible=False) |
|
|
| with gr.Row(visible=False) as login_actions: |
| start_setup_btn = gr.Button( |
| "📝 Configura Profilo", variant="secondary" |
| ) |
| go_to_recommendations_btn = gr.Button( |
| "🎯 Vai alle Raccomandazioni", variant="primary" |
| ) |
|
|
| with gr.Column(visible=False) as poi_selection_page: |
| with gr.Column(elem_classes="search-container"): |
| gr.Markdown("# 🔍 Cerca e seleziona i **Luoghi di Interesse** che preferisci cliccando sulla card corrispondente") |
| gr.Markdown( |
| "Esplora i luoghi disponibili e seleziona quelli che preferisci maggiormente. La ricerca è dinamica: inizia a digitare per filtrare i risultati." |
| ) |
|
|
| |
| search_input = gr.Textbox( |
| placeholder="Cerca per nome, descrizione o località...", |
| label="", |
| show_label=False, |
| container=False, |
| elem_id="poi-search-input", |
| ) |
|
|
| with gr.Column(): |
| |
| selection_summary = gr.Markdown(get_selection_summary(set())) |
|
|
| |
| with gr.Row(): |
| clear_button = gr.Button( |
| "🗑️ Cancella Selezioni", |
| variant="secondary", |
| elem_classes="clear-button", |
| scale=1, |
| ) |
| continue_to_sensory_btn = gr.Button( |
| "Continua alla Configurazione Sensoriale ➡️", |
| variant="primary", |
| elem_classes="continue_to_sensory_btn", |
| scale=3, |
| ) |
|
|
| |
| poi_display = gr.HTML( |
| value=search_pois("", set()), elem_id="poi-display-area" |
| ) |
|
|
| |
| poi_buttons = {} |
| for poi in pois_list: |
| poi_id = poi["poi_id:token"] |
| poi_name = poi["name:token_seq"] |
| safe_id = ( |
| poi_id.replace(" ", "-").replace("'", "").replace('"', "") |
| ) |
| button = gr.Button( |
| poi_name, visible=False, elem_id=f"poi-btn-{safe_id}" |
| ) |
| poi_buttons[(poi_id, poi_name)] = button |
|
|
| with gr.Column( |
| visible=False, elem_classes="sensory-config-main-container" |
| ) as sensory_config_page: |
| |
| gr.HTML(""" |
| <div class="header-section"> |
| <h2 style="margin: 0 0 10px 0;">⚙️ Configura le tue Preferenze Sensoriali</h2> |
| <p style="margin: 0; opacity: 0.9;">Indica il tuo livello di sensibilità per ogni caratteristica</p> |
| </div> |
| """) |
|
|
| aversion_radios = [] |
| with gr.Column(): |
| for i, aversion_question in enumerate(AVERSIONS_QUESTIONS): |
| question = aversion_question.get("question", "") |
| aversion_name = aversion_question.get("aversion_name", "") |
| aversion = AVERSIONS[aversion_name] |
|
|
| with gr.Group(elem_classes="radio-aversion-card"): |
| with gr.Column(): |
| |
| gr.HTML(f""" |
| <div style="display: flex; align-items: center; margin-bottom: 8px;"> |
| <span style="font-size: 20px; margin-right: 10px;">{aversion['Icon']} {aversion['DisplayName']}</span> |
| <div> |
| <div style="font-size: 14px; color: #D7D7D7; margin-top: 2px;">{question}</div> |
| </div> |
| </div> |
| """) |
|
|
| |
| av_radio = gr.Radio( |
| choices=[("Nessuno", 1), ("Poco", 2), ("Moderato", 3), ("Molto", 4), ("Estremo", 5)], |
| value=3, |
| show_label=False, |
| interactive=True, |
| elem_id=f"radio-{aversion_name.lower().replace(' ', '-')}", |
| ) |
|
|
| aversion_radios.append(av_radio) |
|
|
| |
| with gr.Row(): |
| continue_to_recommendations_button = gr.Button( |
| "Continua alle Raccomandazioni →", |
| variant="primary", |
| elem_classes="continue-to-recommendations-button", |
| size="lg", |
| ) |
|
|
| with gr.Column(visible=False) as recommendations_page: |
| with gr.Column(visible=True) as recommendations_list_page: |
| gr.Markdown( |
| "# Sistema di Raccomandazione di Punti di Interesse" |
| ) |
| gr.Markdown(""" |
| Questo sistema raccomanda punti di interesse personalizzati per le preferenze sensoriali degli utenti. |
| Ogni raccomandazione include informazioni sensoriali dettagliate e spiegazioni personalizzate. |
| """) |
|
|
| recommendation_list = gr.HTML(label="Raccomandazioni") |
|
|
| with gr.Row(visible=False): |
| select_buttons = [ |
| gr.Button(f"Select_{i}", elem_id=f"select-button-{i}") |
| for i in range(args.top_k) |
| ] |
|
|
| with gr.Column(visible=False) as details_page_block: |
| gr.Markdown("# Dettagli POI") |
| poi_details = gr.HTML(label="Dettagli Punto di Interesse") |
|
|
| with gr.Column(visible=False) as recommendation_feedback_block: |
| gr.Markdown("## Ti è piaciuto questo luogo che ti abbiamo suggerito?") |
|
|
| with gr.Row(equal_height=True): |
| with gr.Column(scale=1): |
| rec_like_btn = gr.Button("👍 Sì", size="lg") |
| with gr.Column(scale=1): |
| rec_dislike_btn = gr.Button("👎 No", size="lg") |
|
|
| recommendation_feedback_result = gr.State(False) |
| recommendation_feedback_submitted = gr.State(False) |
| recommendation_feedback_message = gr.HTML(visible=False) |
|
|
| |
| with gr.Column(visible=False) as simple_survey_block: |
| gr.Markdown("## Ti è stata utile questa spiegazione?") |
|
|
| with gr.Row(equal_height=True): |
| with gr.Column(scale=1): |
| exp_like_btn = gr.Button("👍 Sì", size="lg") |
| with gr.Column(scale=1): |
| exp_dislike_btn = gr.Button("👎 No", size="lg") |
|
|
| simple_survey_result = gr.State(False) |
| simple_feedback_submitted = gr.State(False) |
| simple_feedback_message = gr.HTML(visible=False) |
|
|
| |
| with gr.Column(visible=False) as advanced_survey_block: |
| if args.survey_language == "it": |
| gr.Markdown("## Valuta questa spiegazione della raccomandazione") |
| else: |
| gr.Markdown("## Rate this explanation of the recommendation") |
|
|
| |
| advanced_current_group_idx = gr.State(0) |
|
|
| |
| from utils.survey_utils import SURVEY_OPTIONS |
|
|
| SURVEY_STATEMENTS = SURVEY_OPTIONS[args.survey_language].get("statements", {}) |
| LIKERT_OPTIONS = SURVEY_OPTIONS[args.survey_language].get("likert_options", []) |
|
|
| |
| advanced_containers = [] |
| advanced_responses = [[], [], []] |
| statements = SURVEY_STATEMENTS.copy() |
| random.shuffle(statements) |
|
|
| |
| max_statements_per_group = 2 |
| for i in range(3): |
| with gr.Column(visible=(i == 0)) as container: |
| if args.survey_language == "it": |
| gr.Markdown(f"### Parte {i + 1} di 3") |
| else: |
| gr.Markdown(f"### Part {i + 1} of 3") |
|
|
| group_responses = [] |
| |
| for j in range(3 if i == 2 else max_statements_per_group): |
| response = gr.Radio( |
| choices=LIKERT_OPTIONS, |
| label=statements[i * max_statements_per_group + j], |
| type="value", |
| value=None, |
| ) |
| group_responses.append(response) |
|
|
| advanced_responses[i] = group_responses |
| advanced_containers.append(container) |
|
|
| |
| with gr.Row(): |
| advanced_prev_btn = gr.Button("← Indietro", interactive=False) |
| advanced_next_btn = gr.Button("Avanti →") |
| advanced_submit_btn = gr.Button( |
| "Conferma Risposte", visible=False |
| ) |
|
|
| advanced_feedback_submitted = gr.State(False) |
| advanced_feedback_message = gr.HTML(visible=False) |
|
|
| with gr.Column(visible=False) as back_to_recommendations_block: |
| gr.HTML( |
| '<hr style="margin: 80px 0 2px 0; border-top: 1px solid #ddd;">' |
| ) |
| back_to_recommendations_button = gr.Button( |
| "← Torna alla lista di raccomandazioni", |
| variant="secondary", |
| elem_classes="back-button-custom", |
| ) |
|
|
| def handle_login(user_id_value): |
| """Gestisce il processo di login""" |
| success, message, login_status = login_user(user_id_value) |
|
|
| if not success: |
| return ( |
| gr.update(value=message, visible=True), |
| gr.update(visible=False), |
| gr.update(visible=False), |
| gr.update(visible=False), |
| user_id_value, |
| login_status, |
| ) |
|
|
| |
| show_setup = login_status in ["new_user", "existing_incomplete"] |
| show_proceed = login_status == "existing_complete" |
|
|
| return ( |
| gr.update(value=message, visible=True), |
| gr.update(visible=True), |
| gr.update(visible=show_setup), |
| gr.update(visible=show_proceed), |
| user_id_value, |
| login_status, |
| ) |
|
|
| def handle_poi_click(poi_id, poi_name, selected_pois, query): |
| """Handle POI click - toggle selection""" |
| print(f"🔥 POI Button clicked: {poi_name}") |
| return toggle_poi_selection(poi_id, poi_name, selected_pois, query) |
|
|
| def handle_proceed_to_sensory_config(user_id, selected_pois): |
| """Handle proceeding to next step""" |
| if not selected_pois: |
| gr.Warning("⚠️ Seleziona la card di almeno un Punto di Interesse per continuare!") |
| return |
|
|
| update_user_selected_pois(user_id, selected_pois) |
| gr.Info(f"✅ Procedendo con {len(selected_pois)} Punti di Interesse selezionati") |
| return navigate_to_sensory_config() |
|
|
| def navigate_to_poi_selection(): |
| """Naviga alla selezione POI""" |
| return ( |
| gr.update(visible=False), |
| gr.update(visible=True), |
| gr.update(visible=False), |
| gr.update(visible=False), |
| "poi_selection", |
| ) |
|
|
| def navigate_to_sensory_config(): |
| """Naviga alla configurazione sensoriale""" |
| return ( |
| gr.update(visible=False), |
| gr.update(visible=False), |
| gr.update(visible=True), |
| gr.update(visible=False), |
| "sensory_config", |
| ) |
|
|
| def navigate_to_recommendations(): |
| """Naviga alle raccomandazioni""" |
| return ( |
| gr.update(visible=False), |
| gr.update(visible=False), |
| gr.update(visible=False), |
| gr.update(visible=True), |
| "recommendations", |
| ) |
|
|
| def complete_profile_setup(user_id): |
| """Completa la configurazione del profilo""" |
| if user_id: |
| mark_profile_complete(user_id) |
| gr.Info(f"✅ Profilo {user_id} completato con successo!") |
| return navigate_to_recommendations() |
|
|
| login_button.click( |
| fn=handle_login, |
| inputs=[user_id_input], |
| outputs=[ |
| login_status_message, |
| login_actions, |
| start_setup_btn, |
| go_to_recommendations_btn, |
| app_user_id, |
| user_status, |
| ], |
| ) |
| |
| start_setup_btn.click( |
| fn=navigate_to_poi_selection, |
| outputs=[ |
| login_page, |
| poi_selection_page, |
| sensory_config_page, |
| recommendations_page, |
| current_page, |
| ], |
| ) |
| |
| go_to_recommendations_btn.click( |
| fn=complete_profile_setup, |
| inputs=[app_user_id], |
| outputs=[ |
| login_page, |
| poi_selection_page, |
| sensory_config_page, |
| recommendations_page, |
| current_page, |
| ], |
| ).then( |
| fn=partial(get_recommendations_ui, k=args.top_k), |
| inputs=[app_user_id], |
| outputs=[recommendations_state, app_user_id, recommendation_list], |
| ) |
|
|
| |
| search_input.change( |
| fn=search_pois, |
| inputs=[search_input, current_selected_pois], |
| outputs=[poi_display], |
| ) |
|
|
| |
| for (poi_id, poi_name), button in poi_buttons.items(): |
| button.click( |
| fn=partial(handle_poi_click, poi_id, poi_name), |
| inputs=[current_selected_pois, search_input], |
| outputs=[current_selected_pois, poi_display, selection_summary], |
| ) |
|
|
| |
| clear_button.click( |
| fn=clear_all_selections, |
| inputs=[search_input], |
| outputs=[current_selected_pois, poi_display, selection_summary], |
| ) |
|
|
| continue_to_sensory_btn.click( |
| fn=handle_proceed_to_sensory_config, |
| inputs=[app_user_id, current_selected_pois], |
| outputs=[ |
| login_page, |
| poi_selection_page, |
| sensory_config_page, |
| recommendations_page, |
| current_page, |
| ], |
| ) |
|
|
| |
| continue_to_recommendations_button.click( |
| fn=update_user_sensory_aversions, |
| inputs=[app_user_id, *aversion_radios], |
| ).then( |
| fn=complete_profile_setup, |
| inputs=[app_user_id], |
| outputs=[ |
| login_page, |
| poi_selection_page, |
| sensory_config_page, |
| recommendations_page, |
| current_page, |
| ], |
| ).then( |
| fn=partial(get_recommendations_ui, k=args.top_k), |
| inputs=[app_user_id], |
| outputs=[recommendations_state, app_user_id, recommendation_list], |
| ) |
|
|
| for i, btn in enumerate(select_buttons): |
| btn.click( |
| fn=lambda current_idx=i: current_idx, |
| inputs=[], |
| outputs=[selected_poi_index], |
| ).then( |
| fn=view_poi_details, |
| inputs=[recommendations_state, app_user_id, selected_poi_index, completed_survey_pois], |
| outputs=[ |
| recommendations_list_page, |
| details_page_block, |
| poi_details, |
| recommendation_feedback_block, |
| back_to_recommendations_block, |
| current_poi_info, |
| ], |
| ) |
|
|
| surveys_objects = [ |
| recommendation_feedback_result, |
| recommendation_feedback_submitted, |
| recommendation_feedback_message, |
| simple_survey_result, |
| simple_feedback_submitted, |
| simple_feedback_message, |
| advanced_current_group_idx, |
| advanced_feedback_submitted, |
| advanced_feedback_message, |
| ] |
|
|
| back_to_recommendations_button.click( |
| fn=lambda: back_to_recommendations(advanced_responses, advanced_containers), |
| inputs=[], |
| outputs=[ |
| recommendations_list_page, |
| details_page_block, |
| poi_details, |
| recommendation_feedback_block, |
| simple_survey_block, |
| advanced_survey_block, |
| back_to_recommendations_block, |
| *surveys_objects, |
| *[radio for group in advanced_responses for radio in group], |
| *advanced_containers, |
| ], |
| ).then( |
| fn=show_recommendation_list, |
| inputs=[recommendations_state, completed_survey_pois], |
| outputs=[recommendation_list] |
| ) |
|
|
| rec_like_btn.click( |
| fn=feedback_message, |
| inputs=[], |
| outputs=[ |
| recommendation_feedback_message, |
| ], |
| show_progress="hidden", |
| ).then( |
| fn=lambda: submit_rec_feedback(True), |
| inputs=[], |
| outputs=[ |
| recommendation_feedback_result, |
| recommendation_feedback_submitted, |
| recommendation_feedback_message, |
| simple_survey_block, |
| recommendation_feedback_block, |
| ], |
| js=js_feedback_message_delay, |
| show_progress="hidden", |
| ) |
|
|
| rec_dislike_btn.click( |
| fn=feedback_message, |
| inputs=[], |
| outputs=[ |
| recommendation_feedback_message, |
| ], |
| show_progress="hidden", |
| ).then( |
| fn=lambda: submit_rec_feedback(False), |
| inputs=[], |
| outputs=[ |
| recommendation_feedback_result, |
| recommendation_feedback_submitted, |
| recommendation_feedback_message, |
| simple_survey_block, |
| recommendation_feedback_block, |
| ], |
| js=js_feedback_message_delay, |
| show_progress="hidden", |
| ) |
|
|
| |
| exp_like_btn.click( |
| fn=feedback_message, |
| inputs=[], |
| outputs=[ |
| simple_feedback_message, |
| ], |
| show_progress="hidden", |
| ).then( |
| fn=lambda: submit_exp_feedback(True), |
| inputs=[], |
| outputs=[ |
| simple_survey_result, |
| simple_feedback_submitted, |
| simple_feedback_message, |
| advanced_survey_block, |
| simple_survey_block, |
| advanced_prev_btn, |
| advanced_next_btn, |
| advanced_submit_btn, |
| ], |
| js=js_feedback_message_delay, |
| show_progress="hidden", |
| ) |
|
|
| exp_dislike_btn.click( |
| fn=feedback_message, |
| inputs=[], |
| outputs=[ |
| simple_feedback_message, |
| ], |
| show_progress="hidden", |
| ).then( |
| fn=lambda: submit_exp_feedback(False), |
| inputs=[], |
| outputs=[ |
| simple_survey_result, |
| simple_feedback_submitted, |
| simple_feedback_message, |
| advanced_survey_block, |
| simple_survey_block, |
| advanced_prev_btn, |
| advanced_next_btn, |
| advanced_submit_btn, |
| ], |
| js=js_feedback_message_delay, |
| show_progress="hidden", |
| ) |
|
|
| |
| navigation_outputs = [ |
| advanced_current_group_idx, |
| advanced_prev_btn, |
| advanced_next_btn, |
| advanced_submit_btn, |
| ] + advanced_containers |
|
|
| advanced_next_btn.click( |
| fn=partial(handle_next_navigation, advanced_responses, advanced_containers), |
| inputs=[advanced_current_group_idx], |
| outputs=navigation_outputs, |
| ).then( |
| fn=partial(handle_all_answered_responses, advanced_responses), |
| inputs=[advanced_current_group_idx], |
| outputs=[advanced_submit_btn, advanced_next_btn], |
| ) |
|
|
| advanced_prev_btn.click( |
| fn=partial(handle_prev_navigation, advanced_containers), |
| inputs=[ |
| advanced_current_group_idx, |
| ], |
| outputs=navigation_outputs, |
| ) |
|
|
| for group_idx, radio_group in enumerate(advanced_responses): |
| for radio_idx, radio_button in enumerate(radio_group): |
| radio_button.change( |
| fn=partial( |
| update_advanced_responses, |
| group_idx, |
| radio_idx, |
| advanced_responses, |
| ), |
| inputs=[radio_button], |
| outputs=[], |
| ).then( |
| fn=partial(handle_all_answered_responses, advanced_responses), |
| inputs=[advanced_current_group_idx], |
| outputs=[advanced_submit_btn, advanced_next_btn], |
| ) |
|
|
| advanced_submit_btn.click( |
| fn=partial( |
| handle_submit_survey, |
| advanced_responses, |
| ), |
| inputs=[ |
| app_user_id, |
| current_poi_info, |
| recommendation_feedback_result, |
| simple_survey_result, |
| ], |
| outputs=[ |
| advanced_feedback_submitted, |
| advanced_feedback_message, |
| advanced_prev_btn, |
| advanced_next_btn, |
| advanced_submit_btn, |
| *advanced_containers, |
| ], |
| ).then( |
| fn=add_poi_to_completed, |
| inputs=[selected_poi_index, completed_survey_pois], |
| outputs=[completed_survey_pois], |
| ) |
|
|
| return app |
|
|
|
|
| if __name__ == "__main__": |
| parser = argparse.ArgumentParser(description="Run the POI Search UI") |
| parser.add_argument( |
| "user_type", |
| choices=["autistic", "neurotypical"], |
| help="Type of user for the interface", |
| ) |
| parser.add_argument( |
| "--top-k", |
| type=int, |
| default=5, |
| help="Number of top recommendations to show", |
| ) |
| parser.add_argument( |
| "--survey_language", |
| choices=["it", "en"], |
| default="it", |
| help="Language for the survey questions", |
| ) |
| parser.add_argument( |
| "--port", type=int, default=7860, help="Port to run the Gradio app on" |
| ) |
| parser.add_argument("--share", action="store_true", help="Share the app publicly") |
| args = parser.parse_args() |
| app = create_main_app(args.user_type) |
| app.launch() |
|
|