import json
import re
import random
from collections import defaultdict
from datetime import datetime
import hashlib
from dotenv import load_dotenv
load_dotenv()
import gradio as gr
from gen_api_answer import (
get_model_response,
parse_model_response,
prometheus_parse_model_response
)
from random_sample_generation import (
get_random_human_ai_pair,
get_random_human_ai_ground_truth_pair,
generate_ai_response
)
from db import add_vote, create_db_connection, get_votes
from utils import Vote
from common import (
POLICY_CONTENT,
ACKNOWLEDGEMENTS,
CSS_STYLES,
MAIN_TITLE,
HOW_IT_WORKS,
)
from prompts import (
DEFAULT_EVAL_PROMPT,
DEFAULT_EVAL_PROMPT_EDITABLE,
FIXED_EVAL_SUFFIX,
DEFAULT_EVAL_CRITERIA,
DEFAULT_SCORE_1,
DEFAULT_SCORE_2,
DEFAULT_SCORE_3,
DEFAULT_SCORE_4,
DEFAULT_SCORE_5,
)
from leaderboard import (
get_leaderboard,
get_leaderboard_stats,
get_model_rankings,
DEFAULT_ELO,
K_FACTOR
)
elo_scores = defaultdict(lambda: DEFAULT_ELO)
vote_counts = defaultdict(int)
db = create_db_connection()
votes_collection = get_votes(db)
current_time = datetime.now()
# Load the model_data from JSONL
def load_model_data():
model_data = {}
try:
with open("data/models.jsonl", "r") as f:
for line in f:
model = json.loads(line)
model_data[model["name"]] = {
"organization": model["organization"],
"license": model["license"],
"api_model": model["api_model"],
}
except FileNotFoundError:
print("Warning: models.jsonl not found")
return {}
return model_data
model_data = load_model_data()
def store_vote_data(prompt, response_a, response_b, model_a, model_b, winner, judge_id):
prompt_value = prompt.value if hasattr(prompt, 'value') else prompt
vote = Vote(
timestamp=datetime.now().isoformat(),
prompt=prompt_value,
response_a=response_a,
response_b=response_b,
model_a=model_a,
model_b=model_b,
winner=winner,
judge_id=judge_id,
)
add_vote(vote, db)
def parse_variables(prompt):
# Extract variables enclosed in double curly braces
variables = re.findall(r"{{(.*?)}}", prompt)
# Remove duplicates while preserving order
seen = set()
variables = [
x.strip() for x in variables if not (x.strip() in seen or seen.add(x.strip()))
]
return variables
def get_final_prompt(eval_prompt, variable_values):
# Replace variables in the eval prompt with their values
for var, val in variable_values.items():
eval_prompt = eval_prompt.replace("{{" + var + "}}", val)
return eval_prompt
def submit_prompt(eval_prompt, *variable_values):
try:
variables = parse_variables(eval_prompt)
variable_values_dict = {var: val for var, val in zip(variables, variable_values)}
final_prompt = get_final_prompt(eval_prompt, variable_values_dict)
models = list(model_data.keys())
model1, model2 = random.sample(models, 2)
model_a, model_b = (model1, model2) if random.random() < 0.5 else (model2, model1)
response_a = get_model_response(model_a, model_data.get(model_a), final_prompt)
response_b = get_model_response(model_b, model_data.get(model_b), final_prompt)
return (
response_a,
response_b,
gr.update(visible=True),
gr.update(visible=True),
model_a,
model_b,
final_prompt,
)
except Exception as e:
print(f"Error in submit_prompt: {str(e)}")
return (
"Error generating response",
"Error generating response",
gr.update(visible=False),
gr.update(visible=False),
None,
None,
None,
)
def get_ip(request: gr.Request) -> str:
"""Get and hash the IP address from the request."""
if "cf-connecting-ip" in request.headers:
ip = request.headers["cf-connecting-ip"]
elif "x-forwarded-for" in request.headers:
ip = request.headers["x-forwarded-for"]
if "," in ip:
ip = ip.split(",")[0]
else:
ip = request.client.host
# Hash the IP address for privacy
return hashlib.sha256(ip.encode()).hexdigest()[:16]
def get_vote_message(choice: str, model_a: str, model_b: str) -> tuple[str, str]:
"""Generate appropriate message based on vote and model rankings.
Returns (title, message) tuple."""
# Get current rankings
voting_data = get_current_votes()
leaderboard = get_leaderboard(model_data, voting_data, show_preliminary=True)
rankings = get_model_rankings(leaderboard)
pos_a = rankings.get(model_a, 0)
pos_b = rankings.get(model_b, 0)
if choice == "Tie":
return "It's a tie!", "Keep voting responsibly 🤗"
# Check if vote aligns with leaderboard
if (choice == "A" and pos_a < pos_b) or (choice == "B" and pos_b < pos_a):
return "The favourite wins!", "Keep voting responsibly 🤗"
else:
return "The underdog wins!", "Keep voting responsibly 🤗"
def vote(
choice,
model_a,
model_b,
final_prompt,
score_a,
critique_a,
score_b,
critique_b,
request: gr.Request,
):
# Get hashed IP as judge_id
judge_id = get_ip(request)
# Update ELO scores based on user choice
elo_a = elo_scores[model_a]
elo_b = elo_scores[model_b]
# Calculate expected scores
Ea = 1 / (1 + 10 ** ((elo_b - elo_a) / 400))
Eb = 1 / (1 + 10 ** ((elo_a - elo_b) / 400))
# Assign actual scores
if choice == "A":
Sa, Sb = 1, 0
elif choice == "B":
Sa, Sb = 0, 1
else:
Sa, Sb = 0.5, 0.5
# Update scores and vote counts
elo_scores[model_a] += K_FACTOR * (Sa - Ea)
elo_scores[model_b] += K_FACTOR * (Sb - Eb)
vote_counts[model_a] += 1
vote_counts[model_b] += 1
# Format the full responses with score and critique
response_a = f"""{score_a}
{critique_a}"""
response_b = f"""{score_b}
{critique_b}"""
# Store the vote data with the final prompt
store_vote_data(
final_prompt, response_a, response_b, model_a, model_b, choice, judge_id
)
# Get model positions for display
voting_data = get_current_votes()
leaderboard = get_leaderboard(model_data, voting_data, show_preliminary=True)
rankings = get_model_rankings(leaderboard)
pos_a = rankings.get(model_a, 0)
pos_b = rankings.get(model_b, 0)
# Format model names with positions and win/loss indicators
if choice == "Tie":
model_a_display = f"*Model: {model_a} (Position #{pos_a})*"
model_b_display = f"*Model: {model_b} (Position #{pos_b})*"
else:
winner = model_a if choice == "A" else model_b
loser = model_b if choice == "A" else model_a
winner_pos = pos_a if choice == "A" else pos_b
loser_pos = pos_b if choice == "A" else pos_a
model_a_display = f"*Model: {model_a} {'✅' if choice == 'A' else '❌'} (Position #{pos_a})*"
model_b_display = f"*Model: {model_b} {'✅' if choice == 'B' else '❌'} (Position #{pos_b})*"
# Generate vote message
title, message = get_vote_message(choice, model_a, model_b)
return [
gr.update(interactive=False, variant="primary" if choice == "A" else "secondary"), # vote_a
gr.update(interactive=False, variant="primary" if choice == "B" else "secondary"), # vote_b
gr.update(interactive=False, variant="primary" if choice == "Tie" else "secondary"), # vote_tie
gr.update(value=model_a_display), # model_name_a
gr.update(value=model_b_display), # model_name_b
gr.update(interactive=True, value="Regenerate judges", variant="secondary"), # send_btn
gr.update(value="🎲 New round", variant="primary"), # random_btn
gr.Info(message, title=title), # success message
]
def get_current_votes():
"""Get current votes from database."""
return get_votes(db)
# Update the refresh_leaderboard function
def refresh_leaderboard(show_preliminary):
"""Refresh the leaderboard data and stats."""
voting_data = get_current_votes()
leaderboard = get_leaderboard(model_data, voting_data, show_preliminary)
data = [
[
entry["Model"],
float(entry["ELO Score"]),
entry["95% CI"],
entry["# Votes"],
entry["Organization"],
entry["License"],
]
for entry in leaderboard
]
stats = get_leaderboard_stats(model_data, voting_data)
return [gr.update(value=data), gr.update(value=stats)]
# Update the leaderboard table definition in the UI
leaderboard_table = gr.Dataframe(
headers=["Model", "ELO", "95% CI", "Matches", "Organization", "License"],
datatype=["str", "number", "str", "number", "str", "str", "str"],
)
def populate_random_example(request: gr.Request, compatible_mode: bool):
"""Generate a random human-AI conversation example and reset judge outputs."""
if compatible_mode:
# Generate all three components when compatible mode is enabled
human_msg, ai_msg, ground_truth_msg = get_random_human_ai_ground_truth_pair()
else:
# Generate only human and AI messages when compatible mode is disabled
human_msg, ai_msg = get_random_human_ai_pair()
ground_truth_msg = ""
return [
gr.update(value=human_msg),
gr.update(value=ai_msg),
gr.update(value="🎲", variant="secondary"), # Reset random button appearance
gr.update(value=""), # Clear score A
gr.update(value=""), # Clear critique A
gr.update(value=""), # Clear score B
gr.update(value=""), # Clear critique B
gr.update(interactive=False, variant="primary"), # Reset vote A
gr.update(interactive=False, variant="primary"), # Reset vote B
gr.update(interactive=False, variant="primary"), # Reset vote tie
gr.update(value="*Model: Hidden*"), # Reset model name A
gr.update(value="*Model: Hidden*"), # Reset model name B
gr.update(value=ground_truth_msg, visible=compatible_mode), # Set ground truth and visibility
]
with gr.Blocks(theme="default", css=CSS_STYLES) as demo:
gr.Markdown(MAIN_TITLE)
gr.Markdown(HOW_IT_WORKS)
# Hidden eval prompt that will always contain DEFAULT_EVAL_PROMPT
eval_prompt = gr.Textbox(
value=DEFAULT_EVAL_PROMPT,
visible=False
)
with gr.Tabs():
with gr.TabItem("Judge Arena"):
with gr.Row():
# Left side - Input section
with gr.Column(scale=1):
with gr.Group():
human_input = gr.TextArea(
label="👩 User Input",
lines=10,
placeholder="Enter the human message here..."
)
with gr.Row():
generate_btn = gr.Button(
"Generate AI Response",
size="sm",
interactive=False
)
ai_response = gr.TextArea(
label="🤖 AI Response",
lines=15,
placeholder="Enter the AI response here..."
)
# Ground truth response (initially hidden)
ground_truth = gr.TextArea(
label="🎯 Ground truth response",
lines=12,
placeholder="Enter the ground truth response here...",
visible=False
)
with gr.Row():
random_btn = gr.Button("🎲", scale=2)
send_btn = gr.Button(
value="Run judges",
variant="primary",
size="lg",
scale=8
)
# Right side - Model outputs
with gr.Column(scale=1):
gr.Markdown("### 👩⚖️ Judge A")
with gr.Group():
model_name_a = gr.Markdown("*Model: Hidden*")
with gr.Row():
with gr.Column(scale=1, min_width=100): # Fixed narrow width for score
score_a = gr.Textbox(label="Score", lines=6, interactive=False)
vote_a = gr.Button("Vote A", variant="primary", interactive=False)
with gr.Column(scale=9, min_width=400): # Wider width for critique
critique_a = gr.TextArea(label="Critique", lines=8, interactive=False)
# Tie button row
with gr.Row() as tie_button_row:
with gr.Column():
vote_tie = gr.Button("Tie", variant="primary", interactive=False)
gr.Markdown("### 🧑⚖️ Judge B")
with gr.Group():
model_name_b = gr.Markdown("*Model: Hidden*")
with gr.Row():
with gr.Column(scale=1, min_width=100): # Fixed narrow width for score
score_b = gr.Textbox(label="Score", lines=6, interactive=False)
vote_b = gr.Button("Vote B", variant="primary", interactive=False)
with gr.Column(scale=9, min_width=400): # Wider width for critique
critique_b = gr.TextArea(label="Critique", lines=8, interactive=False)
# Place Vote B button directly under Judge B
gr.Markdown("
")
# Replace the "Edit Judge Prompt" Accordion section with:
with gr.Accordion("📝 Edit Judge Prompt", open=False) as prompt_accordion:
gr.Markdown("
")
use_reference_toggle = gr.Checkbox(
label="Use a reference response",
value=False
)
# Hide the default prompt editor
with gr.Column(visible=False) as default_prompt_editor:
eval_prompt_editable = gr.TextArea(
value=DEFAULT_EVAL_PROMPT_EDITABLE,
label="Evaluation Criteria",
lines=12
)
with gr.Row(visible=False) as edit_buttons_row:
cancel_prompt_btn = gr.Button("Cancel")
save_prompt_btn = gr.Button("Save", variant="primary")
gr.Markdown("*The sample being evaluated is always appended as:*")
gr.Markdown(f"```{FIXED_EVAL_SUFFIX}")
# Show the compatible mode editor
with gr.Column(visible=True) as compatible_prompt_editor:
with gr.Row():
# Left column - Evaluation Criteria
with gr.Column(scale=1):
eval_criteria_text = gr.TextArea(
label="Evaluation Criteria",
lines=12,
value=DEFAULT_EVAL_CRITERIA,
placeholder="Enter the evaluation criteria..."
)
prometheus_reference = gr.Markdown(
"
*By default, we use the Prometheus absolute grading prompt template - see [here](https://huggingface.co/prometheus-eval/prometheus-7b-v2.0).*",
visible=True
)
# Right column - Score Descriptions
with gr.Column(scale=1):
score1_description = gr.TextArea(
label="Score 1",
value=DEFAULT_SCORE_1,
placeholder="Description for score 1",
lines=2
)
score2_description = gr.TextArea(
label="Score 2",
value=DEFAULT_SCORE_2,
placeholder="Description for score 2",
lines=2
)
score3_description = gr.TextArea(
label="Score 3",
value=DEFAULT_SCORE_3,
placeholder="Description for score 3",
lines=2
)
score4_description = gr.TextArea(
label="Score 4",
value=DEFAULT_SCORE_4,
placeholder="Description for score 4",
lines=2
)
score5_description = gr.TextArea(
label="Score 5",
value=DEFAULT_SCORE_5,
placeholder="Description for score 5",
lines=2
)
# Add save/cancel buttons for compatible mode
with gr.Row(visible=False) as compatible_edit_buttons_row:
compatible_cancel_btn = gr.Button("Cancel")
compatible_save_btn = gr.Button("Save", variant="primary")
with gr.TabItem("Leaderboard"):
with gr.Row():
with gr.Column(scale=1):
show_preliminary = gr.Checkbox(
label="Reveal preliminary results",
value=True, # Checked by default
info="Show all models, including models with less human ratings (< 500 votes)",
interactive=True
)
stats_display = gr.Markdown()
leaderboard_table = gr.Dataframe(
headers=["Model", "ELO", "95% CI", "Matches", "Organization", "License"],
datatype=["str", "number", "str", "number", "str", "str", "str"],
)
gr.Markdown("""
Judge Arena uses Together AI for inference of open-source models. FP8 models are named as -- "Turbo" where the performance of the FP16 reference models is closely matched:
[*"Together Turbo achieves this performance while maintaining full accuracy compared to Meta's reference implementation across all models. Llama-3.1-405B-Instruct-Turbo matches the accuracy of Meta reference models."*](https://www.together.ai/blog/together-inference-engine-2)
""")
# Add change handler for checkbox
show_preliminary.change(
fn=refresh_leaderboard,
inputs=[show_preliminary],
outputs=[leaderboard_table, stats_display]
)
# Update the load event
demo.load(
fn=refresh_leaderboard,
inputs=[show_preliminary],
outputs=[leaderboard_table, stats_display]
)
with gr.TabItem("Policy"):
gr.Markdown(POLICY_CONTENT)
gr.Markdown(ACKNOWLEDGEMENTS)
# Define state variables for model tracking
model_a_state = gr.State()
model_b_state = gr.State()
final_prompt_state = gr.State()
eval_prompt_previous = gr.State(value=DEFAULT_EVAL_PROMPT_EDITABLE) # Initialize with default value
is_editing = gr.State(False) # Track editing state
compatible_mode_state = gr.State(False) # Track compatible mode state
# Update model names after responses are generated
def update_model_names(model_a, model_b):
return gr.update(value=f"*Model: {model_a}*"), gr.update(
value=f"*Model: {model_b}*"
)
# Store the last submitted prompt and variables for comparison
last_submission = gr.State({})
# Update the vote button click handlers
vote_a.click(
fn=vote,
inputs=[
gr.State("A"),
model_a_state,
model_b_state,
final_prompt_state,
score_a,
critique_a,
score_b,
critique_b,
],
outputs=[
vote_a,
vote_b,
vote_tie,
model_name_a,
model_name_b,
send_btn,
random_btn,
gr.State(), # placeholder for success message
],
)
vote_b.click(
fn=vote,
inputs=[
gr.State("B"),
model_a_state,
model_b_state,
final_prompt_state,
score_a,
critique_a,
score_b,
critique_b,
],
outputs=[
vote_a,
vote_b,
vote_tie,
model_name_a,
model_name_b,
send_btn,
random_btn,
gr.State(), # placeholder for success message
],
)
vote_tie.click(
fn=vote,
inputs=[
gr.State("Tie"),
model_a_state,
model_b_state,
final_prompt_state,
score_a,
critique_a,
score_b,
critique_b,
],
outputs=[
vote_a,
vote_b,
vote_tie,
model_name_a,
model_name_b,
send_btn,
random_btn,
gr.State(), # placeholder for success message
],
)
# Add handlers for save/cancel buttons
def save_prompt(new_prompt, previous_prompt):
return [
gr.update(value=new_prompt), # Update the prompt
new_prompt, # Update the previous prompt state
gr.update(visible=False) # Hide the buttons
]
def cancel_prompt(previous_prompt):
return [
gr.update(value=previous_prompt), # Revert to previous prompt
previous_prompt, # Keep the previous prompt state
gr.update(visible=False) # Hide the buttons
]
def show_edit_buttons(current_value, previous_value):
# Show buttons only if the current value differs from the previous value
return gr.update(visible=current_value != previous_value)
# Add handlers for save/cancel buttons and prompt changes
save_prompt_btn.click(
fn=save_prompt,
inputs=[eval_prompt_editable, eval_prompt_previous],
outputs=[eval_prompt_editable, eval_prompt_previous, edit_buttons_row]
)
cancel_prompt_btn.click(
fn=cancel_prompt,
inputs=[eval_prompt_previous],
outputs=[eval_prompt_editable, eval_prompt_previous, edit_buttons_row]
)
eval_prompt_editable.change(
fn=show_edit_buttons,
inputs=[eval_prompt_editable, eval_prompt_previous],
outputs=edit_buttons_row
)
# Function to toggle visibility based on compatible mode
def toggle_use_reference(checked):
if checked:
# Get new random samples with ground truth when enabling reference mode
human_msg, ai_msg, ground_truth_msg = get_random_human_ai_ground_truth_pair()
return {
ground_truth: gr.update(visible=True, value=ground_truth_msg),
human_input: gr.update(value=human_msg),
ai_response: gr.update(value=ai_msg),
# Reset other UI elements
score_a: gr.update(value=""),
critique_a: gr.update(value=""),
score_b: gr.update(value=""),
critique_b: gr.update(value=""),
vote_a: gr.update(interactive=False, variant="primary"),
vote_b: gr.update(interactive=False, variant="primary"),
vote_tie: gr.update(interactive=False, variant="primary"),
model_name_a: gr.update(value="*Model: Hidden*"),
model_name_b: gr.update(value="*Model: Hidden*"),
random_btn: gr.update(value="🎲", variant="secondary"),
}
else:
# Just hide ground truth when disabling reference mode
return {
ground_truth: gr.update(visible=False)
}
# Update the change handler to include all necessary outputs
use_reference_toggle.change(
fn=toggle_use_reference,
inputs=[use_reference_toggle],
outputs=[
ground_truth,
human_input,
ai_response,
score_a,
critique_a,
score_b,
critique_b,
vote_a,
vote_b,
vote_tie,
model_name_a,
model_name_b,
random_btn,
]
)
# Update the submit function to handle different prompts
def submit_and_store(
use_reference,
eval_criteria_text_input,
human_input,
ai_response,
ground_truth_input,
score1_description,
score2_description,
score3_description,
score4_description,
score5_description,
):
# Build prompt data dictionary
prompt_data = {
'human_input': human_input,
'ai_response': ai_response,
'ground_truth_input': ground_truth_input,
'eval_criteria': eval_criteria_text_input,
'score1_desc': score1_description,
'score2_desc': score2_description,
'score3_desc': score3_description,
'score4_desc': score4_description,
'score5_desc': score5_description,
}
models = list(model_data.keys())
model1, model2 = random.sample(models, 2)
model_a, model_b = (model1, model2) if random.random() < 0.5 else (model2, model1)
# Get responses from models
response_a = get_model_response(
model_a,
model_data.get(model_a),
prompt_data,
use_reference=use_reference
)
response_b = get_model_response(
model_b,
model_data.get(model_b),
prompt_data,
use_reference=use_reference
)
# Parse the responses based on model, using Prometheus parsing for Prometheus models and JSON parsing for others
is_prometheus_a = (model_data.get(model_a)['organization'] == 'Prometheus')
is_prometheus_b = (model_data.get(model_b)['organization'] == 'Prometheus')
if is_prometheus_a:
score_a_val, critique_a_val = prometheus_parse_model_response(response_a)
score_a_val = f"{score_a_val} / 5"
else:
score_a_val, critique_a_val = parse_model_response(response_a)
score_a_val = f"{score_a_val} / 5"
if is_prometheus_b:
score_b_val, critique_b_val = prometheus_parse_model_response(response_b)
score_b_val = f"{score_b_val} / 5"
else:
score_b_val, critique_b_val = parse_model_response(response_b)
score_b_val = f"{score_b_val} / 5"
return (
score_a_val,
critique_a_val,
score_b_val,
critique_b_val,
gr.update(interactive=True, variant="primary"), # vote_a
gr.update(interactive=True, variant="primary"), # vote_b
gr.update(interactive=True, variant="primary"), # vote_tie
model_a,
model_b,
eval_prompt,
gr.update(value="*Model: Hidden*"),
gr.update(value="*Model: Hidden*"),
gr.update(value="Regenerate judges", variant="secondary", interactive=True),
gr.update(value="🎲"), # random_btn
)
# Update the click handler to use the editable prompt
send_btn.click(
fn=submit_and_store,
inputs=[
use_reference_toggle,
eval_criteria_text,
human_input,
ai_response,
ground_truth,
score1_description,
score2_description,
score3_description,
score4_description,
score5_description,
],
outputs=[
score_a,
critique_a,
score_b,
critique_b,
vote_a,
vote_b,
vote_tie,
model_a_state,
model_b_state,
final_prompt_state,
model_name_a,
model_name_b,
send_btn,
random_btn,
],
)
# Add random button handler
random_btn.click(
fn=populate_random_example,
inputs=[use_reference_toggle], # Use compatible mode toggle to decide behavior
outputs=[
human_input,
ai_response,
random_btn,
score_a,
critique_a,
score_b,
critique_b,
vote_a,
vote_b,
vote_tie,
model_name_a,
model_name_b,
ground_truth, # Set ground truth
]
)
# Add new input change handlers
def handle_input_change():
"""Reset UI state when inputs are changed"""
return [
gr.update(interactive=False), # vote_a
gr.update(interactive=False), # vote_b
gr.update(interactive=False), # vote_tie
gr.update(value="Run judges", variant="primary"), # send_btn
gr.update(value="🎲", variant="secondary"), # random_btn
]
# Update the change handlers for inputs
human_input.change(
fn=handle_input_change,
inputs=[],
outputs=[vote_a, vote_b, vote_tie, send_btn, random_btn]
)
ai_response.change(
fn=handle_input_change,
inputs=[],
outputs=[vote_a, vote_b, vote_tie, send_btn, random_btn]
)
generate_btn.click(
fn=lambda msg: (
generate_ai_response(msg)[0], # Only take the response text
gr.update(
value="Generate AI Response", # Keep the label
interactive=False # Disable the button
)
),
inputs=[human_input],
outputs=[ai_response, generate_btn]
)
human_input.change(
fn=lambda x: gr.update(interactive=bool(x.strip())),
inputs=[human_input],
outputs=[generate_btn]
)
# Update the demo.load to include the random example population
demo.load(
fn=lambda: populate_random_example(None, False), # Pass False for initial compatible_mode
inputs=[],
outputs=[
human_input,
ai_response,
random_btn,
score_a,
critique_a,
score_b,
critique_b,
vote_a,
vote_b,
vote_tie,
model_name_a,
model_name_b,
ground_truth,
]
)
# Add new state variables for compatible mode
eval_criteria_previous = gr.State(value=DEFAULT_EVAL_CRITERIA)
score1_previous = gr.State(value=DEFAULT_SCORE_1)
score2_previous = gr.State(value=DEFAULT_SCORE_2)
score3_previous = gr.State(value=DEFAULT_SCORE_3)
score4_previous = gr.State(value=DEFAULT_SCORE_4)
score5_previous = gr.State(value=DEFAULT_SCORE_5)
# Add new functions to handle compatible mode saves/cancels
def save_compatible_prompt(criteria, score1, score2, score3, score4, score5):
return [
gr.update(value=criteria), # Update criteria
criteria, # Update previous criteria state
gr.update(value=score1),
score1,
gr.update(value=score2),
score2,
gr.update(value=score3),
score3,
gr.update(value=score4),
score4,
gr.update(value=score5),
score5,
gr.update(visible=False) # Hide buttons
]
def cancel_compatible_prompt(prev_criteria, prev_score1, prev_score2, prev_score3, prev_score4, prev_score5):
return [
gr.update(value=prev_criteria),
prev_criteria,
gr.update(value=prev_score1),
prev_score1,
gr.update(value=prev_score2),
prev_score2,
gr.update(value=prev_score3),
prev_score3,
gr.update(value=prev_score4),
prev_score4,
gr.update(value=prev_score5),
prev_score5,
gr.update(visible=False)
]
def show_compatible_edit_buttons(*current_values):
previous_values = current_values[1::2] # Get previous values
current_values = current_values[::2] # Get current values
return gr.update(visible=any(curr != prev for curr, prev in zip(current_values, previous_values)))
# Add click handlers for compatible mode buttons
compatible_save_btn.click(
fn=save_compatible_prompt,
inputs=[
eval_criteria_text,
score1_description,
score2_description,
score3_description,
score4_description,
score5_description
],
outputs=[
eval_criteria_text,
eval_criteria_previous,
score1_description,
score1_previous,
score2_description,
score2_previous,
score3_description,
score3_previous,
score4_description,
score4_previous,
score5_description,
score5_previous,
compatible_edit_buttons_row
]
)
compatible_cancel_btn.click(
fn=cancel_compatible_prompt,
inputs=[
eval_criteria_previous,
score1_previous,
score2_previous,
score3_previous,
score4_previous,
score5_previous
],
outputs=[
eval_criteria_text,
eval_criteria_previous,
score1_description,
score1_previous,
score2_description,
score2_previous,
score3_description,
score3_previous,
score4_description,
score4_previous,
score5_description,
score5_previous,
compatible_edit_buttons_row
]
)
# Add change handlers for all compatible mode inputs
for component in [eval_criteria_text, score1_description, score2_description,
score3_description, score4_description, score5_description]:
component.change(
fn=show_compatible_edit_buttons,
inputs=[
eval_criteria_text,
eval_criteria_previous,
score1_description,
score1_previous,
score2_description,
score2_previous,
score3_description,
score3_previous,
score4_description,
score4_previous,
score5_description,
score5_previous
],
outputs=compatible_edit_buttons_row
)
if __name__ == "__main__":
demo.launch()