|
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, |
|
|
|
) as demo: |
|
match_state = gr.State() |
|
user_state = gr.State() |
|
timer = gr.Timer(1) |
|
|
|
gr.Markdown( |
|
'<h1 style="text-align:center;"> Concours du meilleur Prompt Engineer </h1>' |
|
) |
|
|
|
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 |
|
################## |
|
""" |
|
|
|
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("") |
|
|
|
|
|
|
|
@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=""), |
|
} |
|
|
|
@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", {"team": f"{user_state['team']}", "text": prompt_text}) |
|
|
|
all_prompts = db.load("prompts") |
|
prompt_id = all_prompts[all_prompts["team"] == 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, |
|
], |
|
) |
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
demo.launch() |
|
|