QA_Descriptions / app.py
vsingh1991's picture
Update app.py
a68b86d verified
Raw
History Blame Contribute Delete
13.9 kB
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()