Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import gradio as gr | |
| import os | |
| from datetime import datetime | |
| from pathlib import Path | |
| BASE_PATH = "." | |
| class FeedbackState: | |
| def __init__(self, username): | |
| self.current_idx = 0 | |
| self.feedback_data = [] | |
| self.username = username | |
| self.responses = [] | |
| # Read TSV file with tab separator | |
| df = pd.read_csv(os.path.join(BASE_PATH, 'parameters.tsv'), sep='\t') | |
| with gr.Blocks(title="Évaluation des descriptions auto-générées") as demo: | |
| # Login page with welcome message | |
| with gr.Row(visible=True) as login_row: | |
| with gr.Column(): | |
| gr.Markdown("""### Bienvenue à l'évaluation des descriptions auto-générées! | |
| Ton retour est essentiel pour améliorer notre feature de descriptions automatiques d'annonces. En évaluant ces descriptions, tu nous aides à garantir qu'elles capturent précisément les caractéristiques des produits et adoptent le ton et style approprié pour chaque catégorie. | |
| ⏱️ Temps estimé: environ 2 minutes par annonce""") | |
| username_input = gr.Textbox(label="Ton nom") | |
| login_button = gr.Button("Commencer l'évaluation") | |
| with gr.Column(visible=False) as thank_you_container: | |
| completion_msg = gr.Markdown("", visible=False) | |
| download_link = gr.File(label="Télécharge le fichier CSV des retours") | |
| with gr.Column(visible=False) as main_interface: | |
| state = gr.State(lambda: None) | |
| # Instructions at the top of evaluation interface | |
| gr.Markdown("""### Instructions: | |
| 1. Tu trouveras pour chaque annonce: | |
| - L'image et caractéristiques du produit (à droite) | |
| - Deux versions à évaluer: description générée par l'IA avec titre (gauche) et description générée par l'IA sans titre (droite) | |
| 2. Pour chaque version: | |
| - Choisis "Accepter" ou "Refuser" | |
| - Si "Refuser": sélectionne la raison principale | |
| - Si "Autre": précise brièvement pourquoi | |
| 3. Navigation et fin: | |
| - Utilise "Précédent"/"Suivant" pour parcourir les annonces | |
| - Le compteur en bas à gauche indique ta progression | |
| - À la fin: télécharge le fichier CSV et partage-le dans #cognition-users sur Slack""") | |
| with gr.Row(): | |
| image_display = gr.Image(label="Image du Produit", height=400) | |
| param_view = gr.JSON(label="Paramètres de l'Annonce") | |
| with gr.Row(): | |
| # Left column - With Title | |
| with gr.Column(): | |
| gr.Markdown("### Description générée par l'IA en tenant compte du titre") | |
| title_display = gr.Textbox(label="Titre", interactive=False) | |
| desc_with_title = gr.Textbox(label="Description", interactive=False) | |
| feedback_with_title = gr.Radio( | |
| ["Accepter", "Refuser"], | |
| label="Évalue cette version" | |
| ) | |
| with gr.Column(visible=False) as improvement_with_title_container: | |
| improvement_with_title = gr.Radio( | |
| ["Attributs manquants/imprécis", | |
| "Style trop robotique/impersonnel", | |
| "Style trop familier", | |
| "Description trop longue/verbeuse", | |
| "Description trop courte", | |
| "Autre"], | |
| label="Si tu as choisi 'Refuser', indique la raison principale :" | |
| ) | |
| other_comment_with_title = gr.Textbox( | |
| label="Si 'Autre', précise en quelques mots :", | |
| max_lines=1, | |
| visible=False | |
| ) | |
| # Right column - Without Title | |
| with gr.Column(): | |
| gr.Markdown("### Description générée par l'IA sans tenir compte du titre") | |
| desc_without_title = gr.Textbox(label="Description", interactive=False) | |
| feedback_without_title = gr.Radio( | |
| ["Accepter", "Refuser"], | |
| label="Évalue cette version" | |
| ) | |
| with gr.Column(visible=False) as improvement_without_title_container: | |
| improvement_without_title = gr.Radio( | |
| ["Attributs manquants/imprécis", | |
| "Style trop robotique/impersonnel", | |
| "Style trop familier", | |
| "Description trop longue/verbeuse", | |
| "Description trop courte", | |
| "Autre"], | |
| label="Si tu as choisi 'Refuser', indique la raison principale :" | |
| ) | |
| other_comment_without_title = gr.Textbox( | |
| label="Si 'Autre', précise en quelques mots :", | |
| max_lines=1, | |
| visible=False | |
| ) | |
| with gr.Row(): | |
| prev_btn = gr.Button("Précédent", visible=False) | |
| next_btn = gr.Button("Suivant") | |
| export_btn = gr.Button("Terminer et Exporter en CSV", visible=False) | |
| status = gr.Markdown() | |
| def show_improvement_options(feedback_choice, is_with_title=True): | |
| return { | |
| improvement_with_title_container if is_with_title else improvement_without_title_container: | |
| gr.update(visible=feedback_choice == "Refuser") | |
| } | |
| def show_other_comment(improvement_choice, is_with_title=True): | |
| return { | |
| other_comment_with_title if is_with_title else other_comment_without_title: | |
| gr.update(visible=improvement_choice == "Autre") | |
| } | |
| def login(username): | |
| if not username.strip(): | |
| return { | |
| login_row: gr.update(visible=True), | |
| main_interface: gr.update(visible=False), | |
| username_input: gr.update(value="", error="Entre un nom s'il te plaît") | |
| } | |
| return { | |
| login_row: gr.update(visible=False), | |
| main_interface: gr.update(visible=True), | |
| state: FeedbackState(username) | |
| } | |
| def load_listing(idx, state): | |
| if state is None: | |
| return None | |
| record = df.iloc[idx] | |
| is_last = idx == len(df) - 1 | |
| is_first = idx == 0 | |
| return { | |
| image_display: os.path.join(BASE_PATH, str(record['image_filename']).strip()), | |
| param_view: eval(str(record['listing_params']).strip()), | |
| title_display: str(record['listing_title']).strip(), | |
| desc_with_title: str(record['generated_description_with_title']).strip(), | |
| desc_without_title: str(record['generated_description_without_title']).strip(), | |
| status: f"Annonce {idx+1} sur {len(df)}", | |
| prev_btn: gr.update(visible=not is_first), | |
| next_btn: gr.update(visible=not is_last), | |
| export_btn: gr.update(visible=is_last), | |
| feedback_with_title: None, | |
| feedback_without_title: None, | |
| improvement_with_title: None, | |
| improvement_without_title: None, | |
| other_comment_with_title: "", | |
| other_comment_without_title: "", | |
| improvement_with_title_container: gr.update(visible=False), | |
| improvement_without_title_container: gr.update(visible=False) | |
| } | |
| def navigate(direction, state, | |
| feedback_with_title, improvement_with_title, other_comment_with_title, | |
| feedback_without_title, improvement_without_title, other_comment_without_title): | |
| if state is None: | |
| return None | |
| if feedback_with_title or feedback_without_title: | |
| current_feedback = { | |
| 'username': state.username, | |
| 'listing_id': df.iloc[state.current_idx]['listing_id'], | |
| 'feedback_with_title': feedback_with_title, | |
| 'improvement_with_title': improvement_with_title if feedback_with_title == "Refuser" else "", | |
| 'other_comment_with_title': other_comment_with_title if improvement_with_title == "Autre" else "", | |
| 'feedback_without_title': feedback_without_title, | |
| 'improvement_without_title': improvement_without_title if feedback_without_title == "Refuser" else "", | |
| 'other_comment_without_title': other_comment_without_title if improvement_without_title == "Autre" else "", | |
| 'timestamp': datetime.now().isoformat() | |
| } | |
| state.responses.append(current_feedback) | |
| new_idx = max(0, min(len(df)-1, state.current_idx + direction)) | |
| state.current_idx = new_idx | |
| return load_listing(new_idx, state) | |
| def save_and_export(state, | |
| feedback_with_title, improvement_with_title, other_comment_with_title, | |
| feedback_without_title, improvement_without_title, other_comment_without_title): | |
| if not (feedback_with_title and feedback_without_title): | |
| return ( | |
| gr.update(value="Merci de sélectionner Accepter ou Refuser pour les deux versions.", visible=True), | |
| gr.update(visible=True), | |
| gr.update(visible=False), | |
| None | |
| ) | |
| final_feedback = { | |
| 'username': state.username, | |
| 'listing_id': df.iloc[state.current_idx]['listing_id'], | |
| 'feedback_with_title': feedback_with_title, | |
| 'improvement_with_title': improvement_with_title if feedback_with_title == "Refuser" else "", | |
| 'other_comment_with_title': other_comment_with_title if improvement_with_title == "Autre" else "", | |
| 'feedback_without_title': feedback_without_title, | |
| 'improvement_without_title': improvement_without_title if feedback_without_title == "Refuser" else "", | |
| 'other_comment_without_title': other_comment_without_title if improvement_without_title == "Autre" else "", | |
| 'timestamp': datetime.now().isoformat() | |
| } | |
| state.responses.append(final_feedback) | |
| feedback_df = pd.DataFrame(state.responses) | |
| timestamp = datetime.now().strftime('%Y%m%d') | |
| username_safe = state.username.replace(' ', '_') | |
| csv_filename = f'resultats_feedback_{timestamp}_{username_safe}.csv' | |
| feedback_df.to_csv(csv_filename, index=False) | |
| thank_you_message = "## Merci d'avoir complété l'évaluation ! 🎉\n\nClique ci-dessous pour télécharger ton fichier CSV de retours." | |
| return ( | |
| gr.update(value=thank_you_message, visible=True), | |
| gr.update(visible=False), | |
| gr.update(visible=True), | |
| csv_filename | |
| ) | |
| # Event handlers | |
| login_button.click( | |
| fn=login, | |
| inputs=[username_input], | |
| outputs=[login_row, main_interface, state] | |
| ).then( | |
| fn=lambda s: load_listing(0, s), | |
| inputs=[state], | |
| outputs=[image_display, param_view, title_display, desc_with_title, desc_without_title, | |
| status, prev_btn, next_btn, export_btn, feedback_with_title, feedback_without_title, | |
| improvement_with_title, improvement_without_title, other_comment_with_title, | |
| other_comment_without_title, improvement_with_title_container, | |
| improvement_without_title_container] | |
| ) | |
| feedback_with_title.change( | |
| fn=show_improvement_options, | |
| inputs=[feedback_with_title], | |
| outputs=[improvement_with_title_container] | |
| ) | |
| feedback_without_title.change( | |
| fn=lambda x: show_improvement_options(x, False), | |
| inputs=[feedback_without_title], | |
| outputs=[improvement_without_title_container] | |
| ) | |
| improvement_with_title.change( | |
| fn=show_other_comment, | |
| inputs=[improvement_with_title], | |
| outputs=[other_comment_with_title] | |
| ) | |
| improvement_without_title.change( | |
| fn=lambda x: show_other_comment(x, False), | |
| inputs=[improvement_without_title], | |
| outputs=[other_comment_without_title] | |
| ) | |
| prev_btn.click( | |
| fn=navigate, | |
| inputs=[gr.State(-1), state, | |
| feedback_with_title, improvement_with_title, other_comment_with_title, | |
| feedback_without_title, improvement_without_title, other_comment_without_title], | |
| outputs=[image_display, param_view, title_display, desc_with_title, desc_without_title, | |
| status, prev_btn, next_btn, export_btn, feedback_with_title, feedback_without_title, | |
| improvement_with_title, improvement_without_title, other_comment_with_title, | |
| other_comment_without_title, improvement_with_title_container, | |
| improvement_without_title_container] | |
| ) | |
| next_btn.click( | |
| fn=navigate, | |
| inputs=[gr.State(1), state, | |
| feedback_with_title, improvement_with_title, other_comment_with_title, | |
| feedback_without_title, improvement_without_title, other_comment_without_title], | |
| outputs=[image_display, param_view, title_display, desc_with_title, desc_without_title, | |
| status, prev_btn, next_btn, export_btn, feedback_with_title, feedback_without_title, | |
| improvement_with_title, improvement_without_title, other_comment_with_title, | |
| other_comment_without_title, improvement_with_title_container, | |
| improvement_without_title_container] | |
| ) | |
| export_btn.click( | |
| fn=save_and_export, | |
| inputs=[state, | |
| feedback_with_title, improvement_with_title, other_comment_with_title, | |
| feedback_without_title, improvement_without_title, other_comment_without_title], | |
| outputs=[completion_msg, main_interface, thank_you_container, download_link] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |