import gradio as gr from arena import Arena import db from plot import plot_estimates_distribution LABEL_A = "Proposition A" LABEL_B = "Proposition B" ARENA = Arena() css_code = """ /* Cible le premier bloc Markdown par son ID et lui donne un fond vert */ #green_background input { background-color: #41f707; /* Vert très clair */ } /* Cible le second bloc Markdown par son ID et lui donne un fond rouge */ #red_background input { background-color: #FFCCCC } """ """ ############### Gradio UI setup ############### """ with gr.Blocks( title="Prompt Arena", css=css_code, # theme=gr.themes.Default.load("theme_schema_miku.json"), ) as demo: match_state = gr.State() user_state = gr.State() timer = gr.Timer(1) gr.Markdown( '

Concours du meilleur Prompt Engineer

' ) progress_info = gr.Textbox( label="Progression du concours", value=ARENA.get_progress(), interactive=False, lines=2, visible=False, ) with gr.Tabs() as tabs: """ ################## Identification Tab ################## """ # Onglet Identification with gr.TabItem("Identification", id=0) as identification_tab: with gr.Row(): user_code_box = gr.Textbox( label="Code d'identification", placeholder="Saisissez votre code d'identification à 4 lettres", interactive=True, scale=0, min_width=250, max_lines=1, ) validate_btn = gr.Button( "Valider", variant="primary", scale=0, min_width=250 ) message = gr.Markdown("") """ ###################### Identification Actions ###################### """ @validate_btn.click(inputs=[user_code_box], outputs=[message, user_state]) def on_validate(code): if not code or not code.strip(): return { message: gr.update( value="Veuillez entrer votre code d'identification.", visible=True, ) } user = db.get_user(code) if not user: return { message: gr.update( value="Code invalide. Veuillez vérifier votre code d'identification.", visible=True, ) } return { message: gr.update( value=f"Code reconnu ! Bienvenue joueur {user['username']}", visible=True, ), user_state: user, } """ ################## Candidate Tab ################## """ with gr.TabItem("Candidat", id=1, visible=False) as candidat_tab: with gr.Row(): with gr.Column(): label_input = gr.Markdown(value="Sujet du concours") competition_input = gr.Markdown( value=db.load("inputs") .query("name == 'Competition'")["text"] .values[0], container=True, max_height=100, ) with gr.Row(): with gr.Column(): label_candidat = gr.Markdown( value="Votre candidat au concours", ) candidat_prompt = gr.Textbox( show_label=False, placeholder="Saisissez votre texte candidat", interactive=True, scale=0, min_width=600, lines=10, max_lines=10, ) submit_prompt_btn = gr.Button( "Valider", variant="primary", scale=0, min_width=250 ) message_prompt = gr.Markdown("", visible=False) with gr.Column(): label_preview = gr.Markdown( value="Aperçu du rendu (pour les contenus markdown ou html)", visible=False, ) candidat_preview = gr.Markdown( value="", max_height=300, visible=False, container=True ) candidat_prompt.change( lambda text: ( gr.update(value=text if text else "", visible=True if text else False), gr.update(visible=True if text else False), ), inputs=candidat_prompt, outputs=[candidat_preview, label_preview], ) """ ################## Compétition Tab ################## """ with gr.TabItem("Compétition", id=2, visible=False) as competition_tab: with gr.Row(): new_match_btn = gr.Button("Lancer un nouveau match", variant="primary") with gr.Row(): with gr.Column(): label_prop_a = gr.Markdown(LABEL_A, visible=False) proposition_a = gr.Markdown(container=True, visible=False) vote_a_btn = gr.Button("Choisir " + LABEL_A, visible=False) with gr.Column(): label_prop_b = gr.Markdown(LABEL_B, visible=False) proposition_b = gr.Markdown(container=True, visible=False) vote_b_btn = gr.Button("Choisir " + LABEL_B, visible=False) result = gr.Markdown("") # with gr.TabItem("Classement"): @new_match_btn.click( inputs=[user_state], outputs=[ label_prop_a, label_prop_b, proposition_a, proposition_b, match_state, vote_a_btn, vote_b_btn, new_match_btn, result, ], ) def select_and_display_match(user_state): selected_match = ARENA.select_match(user_state) if not selected_match: return { label_prop_a: gr.update(visible=False), label_prop_b: gr.update(visible=False), proposition_a: gr.update(value="", visible=False), proposition_b: gr.update(value="", visible=False), match_state: {}, vote_a_btn: gr.update(visible=False), vote_b_btn: gr.update(visible=False), new_match_btn: gr.update(visible=False), result: gr.update( value="Vous avez déjà voté pour tous les matchs disponibles. Veuillez attendre la fin de la compétition" ), } else: prompt_a, prompt_b = selected_match return { label_prop_a: gr.update(visible=True), label_prop_b: gr.update(visible=True), proposition_a: gr.update(value=prompt_a["text"], visible=True), proposition_b: gr.update(value=prompt_b["text"], visible=True), match_state: { "prompt_a_id": prompt_a["id"], "prompt_b_id": prompt_b["id"], }, vote_a_btn: gr.update(visible=True), vote_b_btn: gr.update(visible=True), new_match_btn: gr.update(visible=False), result: gr.update(value=""), # Reset result } @vote_a_btn.click( inputs=[match_state, user_state], outputs=[ result, vote_a_btn, vote_b_btn, new_match_btn, ], ) def record_winner_a(match_state, user_state): prompt_a_id = match_state["prompt_a_id"] prompt_b_id = match_state["prompt_b_id"] ARENA.record_result(prompt_a_id, prompt_b_id, user_state["id"]) return { result: f"Vous avez choisi : {LABEL_A}", vote_a_btn: gr.update(visible=False), vote_b_btn: gr.update(visible=False), new_match_btn: gr.update(visible=True), } @vote_b_btn.click( inputs=[match_state, user_state], outputs=[ result, vote_a_btn, vote_b_btn, new_match_btn, ], ) def record_winner_b(match_state, user_state): prompt_a_id = match_state["prompt_a_id"] prompt_b_id = match_state["prompt_b_id"] ARENA.record_result(prompt_b_id, prompt_a_id, user_state["id"]) return { result: f"Vous avez choisi : {LABEL_B}", vote_a_btn: gr.update(visible=False), vote_b_btn: gr.update(visible=False), new_match_btn: gr.update(visible=True), } """ ################## Result Tab ################## """ with gr.TabItem("Classement") as result_tab: rankings_table = gr.DataFrame( label="Classement des équipes", value=ARENA.get_rankings(), interactive=True, ) """ ################## Follow up Tab ################## """ with gr.TabItem("Followup") as admin_followup_tab: with gr.Accordion("Matrice de compétition", open=False): competition_matrix = gr.DataFrame( value=ARENA.get_competition_matrix(), interactive=True, ) with gr.Accordion("Distribution des estimations", open=False): plot_estimates = gr.Plot( plot_estimates_distribution, label="Distribution des estimations", ) """ ################## Database Tab ################## """ with gr.TabItem("Database") as admin_db_tab: with gr.Accordion("Switches", open=False): switches_table = gr.DataFrame( value=db.load("switches"), interactive=True, ) with gr.Accordion("Inputs", open=False): inputs_table = gr.DataFrame( value=db.load("inputs"), interactive=True, ) with gr.Accordion("Prompts", open=False): prompts_table = gr.DataFrame( value=db.load("prompts"), interactive=True, ) with gr.Accordion("Estimates", open=False): estimates_table = gr.DataFrame( label="Estimations", value=db.load("estimates"), interactive=True, ) with gr.Accordion("Votes", open=False): votes_table = gr.DataFrame( label="Votes", value=db.load("votes"), interactive=True, ) with gr.Accordion("Teams", open=False): teams_table = gr.DataFrame( label="Teams", value=db.load("teams"), interactive=True, ) with gr.Accordion("Users", open=False): users_table = gr.DataFrame( label="Users", value=db.load("users"), interactive=True, ) switches_table.change( db.replace, inputs=[gr.Markdown("switches", visible=False), switches_table], outputs=None, ) inputs_table.change( db.replace, inputs=[gr.Markdown("inputs", visible=False), inputs_table], outputs=None, ) prompts_table.change( db.replace, inputs=[gr.Markdown("prompts", visible=False), prompts_table], outputs=None, ) estimates_table.change( db.replace, inputs=[gr.Markdown("estimates", visible=False), estimates_table], outputs=None, ) votes_table.change( db.replace, inputs=[gr.Markdown("votes", visible=False), votes_table], outputs=None, ) teams_table.change( db.replace, inputs=[gr.Markdown("teams", visible=False), teams_table], outputs=None, ) users_table.change( db.replace, inputs=[gr.Markdown("users", visible=False), users_table], outputs=None, ) """ ###################### Candidat Actions ###################### """ @submit_prompt_btn.click( inputs=[candidat_prompt, user_state], outputs=[ submit_prompt_btn, candidat_prompt, message_prompt, competition_tab, tabs, ], ) def submit_prompt(prompt_text, user_state): if not prompt_text or not prompt_text.strip(): return { message_prompt: gr.update( value="Veuillez saisir un prompt", visible=True, ), } db_team_prompt = db.get_prompt(user_state["team"]) if db_team_prompt: return { submit_prompt_btn: gr.update(interactive=False), candidat_prompt: gr.update(value=db_team_prompt, interactive=False), message_prompt: gr.update( value="Votre équipe a déjà enregistré un candidat.", visible=True, ), } db.insert("prompts", {"name": f"{user_state['team']}", "text": prompt_text}) # Initialize estimates for the newly submitted prompt all_prompts = db.load("prompts") prompt_id = all_prompts[all_prompts["name"] == user_state["team"]].iloc[0]["id"] ARENA.init_estimates(prompt_id) return { submit_prompt_btn: gr.update(interactive=False), candidat_prompt: gr.update(interactive=False), message_prompt: gr.update( value="Prompt soumis avec succès !", visible=True ), competition_tab: gr.update(visible=True), tabs: gr.Tabs(selected=2), } """ ###################### Periodic refresh ###################### """ def refresh(user_state): if user_state is None: return { candidat_tab: gr.update(visible=False), competition_tab: gr.update(visible=False), result_tab: gr.update(visible=False), admin_db_tab: gr.update(visible=False), admin_followup_tab: gr.update(visible=False), } team = user_state.get("team", "") update_prompt = {} prompt_team = db.get_prompt(team) if prompt_team: update_prompt = { candidat_prompt: gr.update(value=prompt_team, interactive=False), submit_prompt_btn: gr.update(interactive=False, visible=False), message_prompt: gr.update( value="Votre équipe a déjà enregistré un candidat.", visible=True ), } update_tabs = {} if user_state["team"] == "Admin": update_tabs = { candidat_tab: gr.update(visible=True), competition_tab: gr.update(visible=True), result_tab: gr.update(visible=True), admin_db_tab: gr.update(visible=True), admin_followup_tab: gr.update(visible=True), } else: update_tabs = { candidat_tab: gr.update(visible=db.get_status("Candidate")), competition_tab: gr.update(visible=db.get_status("Competition")), result_tab: gr.update(visible=db.get_status("Result")), admin_db_tab: gr.update(visible=False), admin_followup_tab: gr.update(visible=False), } update_tables = { prompts_table: gr.update(value=db.load("prompts")), estimates_table: gr.update(value=db.load("estimates")), votes_table: gr.update(value=db.load("votes")), teams_table: gr.update(value=db.load("teams")), users_table: gr.update(value=db.load("users")), competition_input: gr.update( value=db.load("inputs").query("name == 'Competition'")["text"].values[0] ), plot_estimates: gr.update(value=plot_estimates_distribution()), rankings_table: gr.update(value=ARENA.get_rankings()), competition_matrix: gr.update(value=ARENA.get_competition_matrix()), } return {**update_prompt, **update_tabs, **update_tables} timer.tick( refresh, [user_state], [ prompts_table, estimates_table, votes_table, teams_table, users_table, candidat_prompt, submit_prompt_btn, message_prompt, candidat_tab, competition_tab, result_tab, admin_db_tab, admin_followup_tab, plot_estimates, rankings_table, competition_matrix, competition_input, ], ) # Exemple d'utilisation if __name__ == "__main__": demo.launch() # ajouter share=True pour partager l'interface