Arena / app.py
FredOru's picture
bug: requirement and name is team
4730bc7
raw
history blame
18.3 kB
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(
'<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
##################
"""
# 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", {"team": 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["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,
],
)
# Exemple d'utilisation
if __name__ == "__main__":
demo.launch() # ajouter share=True pour partager l'interface