Skip to content

Commit a549649

Browse files
committed
leaderboard configuration
1 parent faecac3 commit a549649

File tree

3 files changed

+251
-27
lines changed

3 files changed

+251
-27
lines changed

.DS_Store

6 KB
Binary file not shown.

app/app.py

Lines changed: 189 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
from huggingface_hub import InferenceClient
2323
from pandas import DataFrame
2424
from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
25+
import threading
26+
from collections import defaultdict
2527

2628

2729
BASE_MODEL = os.getenv("MODEL", "google/gemma-3-12b-pt")
@@ -525,9 +527,63 @@ def wrangle_retry_data(
525527
)
526528
return history, update_dataframe(dataframe, history)
527529

530+
# Global variables for tracking language data points
531+
LANGUAGE_DATA_POINTS = defaultdict(int)
532+
language_data_lock = threading.Lock()
533+
534+
def get_leaderboard_data():
535+
"""Get sorted leaderboard data for all languages"""
536+
with language_data_lock:
537+
leaderboard_data = {lang: LANGUAGE_DATA_POINTS.get(lang, 0) for lang in LANGUAGES.keys()}
538+
sorted_data = sorted(leaderboard_data.items(), key=lambda x: x[1], reverse=True)
539+
return sorted_data
540+
541+
def increment_language_data_point(language):
542+
"""Increment the data point count for a specific language"""
543+
with language_data_lock:
544+
LANGUAGE_DATA_POINTS[language] += 1
545+
return get_leaderboard_data()
546+
547+
def set_language_data_points(language, count):
548+
"""Manually set the data point count for a specific language"""
549+
with language_data_lock:
550+
LANGUAGE_DATA_POINTS[language] = count
551+
return get_leaderboard_data()
552+
553+
def load_initial_language_data():
554+
"""Load initial language data points from persistent storage or default values"""
555+
data_points_path, use_persistent = get_persistent_storage_path("language_data_points.json")
556+
557+
if data_points_path.exists():
558+
try:
559+
with open(data_points_path, "r", encoding="utf-8") as f:
560+
data = json.load(f)
561+
with language_data_lock:
562+
LANGUAGE_DATA_POINTS.clear()
563+
LANGUAGE_DATA_POINTS.update(data)
564+
except Exception as e:
565+
print(f"Error loading language data points: {e}")
566+
567+
for lang in LANGUAGES.keys():
568+
if lang not in LANGUAGE_DATA_POINTS:
569+
LANGUAGE_DATA_POINTS[lang] = 0
570+
571+
return get_leaderboard_data()
572+
573+
def save_language_data_points():
574+
"""Save language data points to persistent storage"""
575+
data_points_path, use_persistent = get_persistent_storage_path("language_data_points.json")
576+
577+
try:
578+
with language_data_lock:
579+
with open(data_points_path, "w", encoding="utf-8") as f:
580+
json.dump(dict(LANGUAGE_DATA_POINTS), f, ensure_ascii=False, indent=2)
581+
except Exception as e:
582+
print(f"Error saving language data points: {e}")
583+
528584

529585
def submit_conversation(dataframe, conversation_id, session_id, language):
530-
""" "Submit the conversation to dataset repo"""
586+
""" "Submit the conversation to dataset repo & update leaderboard"""
531587
if dataframe.empty or len(dataframe) < 2:
532588
gr.Info("No feedback to submit.")
533589
return (gr.Dataframe(value=None, interactive=False), [])
@@ -543,7 +599,10 @@ def submit_conversation(dataframe, conversation_id, session_id, language):
543599
"language": language,
544600
}
545601
save_feedback(input_object=conversation_data)
546-
return (gr.Dataframe(value=None, interactive=False), [])
602+
leaderboard_data = increment_language_data_point(language)
603+
save_language_data_points()
604+
605+
return (gr.Dataframe(value=None, interactive=False), [], leaderboard_data)
547606

548607

549608
def open_add_language_modal():
@@ -813,42 +872,80 @@ def send_notification_email(contributor_data):
813872
padding: 10px 0;
814873
margin-top: 5px;
815874
}
875+
876+
/* Leaderboard styles */
877+
.leaderboard-container {
878+
border-left: 1px solid #eaeaea;
879+
padding-left: 1rem;
880+
height: 100%;
881+
}
882+
.leaderboard-title {
883+
font-weight: bold;
884+
text-align: center;
885+
margin-bottom: 1rem;
886+
}
887+
.leaderboard-item {
888+
display: flex;
889+
justify-content: space-between;
890+
padding: 0.5rem 0;
891+
border-bottom: 1px solid #f0f0f0;
892+
}
893+
.leaderboard-rank {
894+
font-weight: bold;
895+
margin-right: 0.5rem;
896+
}
897+
.leaderboard-language {
898+
flex-grow: 1;
899+
}
900+
.leaderboard-count {
901+
font-weight: bold;
902+
}
903+
.leaderboard-admin-panel {
904+
margin-top: 1rem;
905+
padding-top: 1rem;
906+
border-top: 1px solid #eaeaea;
907+
}
816908
"""
817909

818910
def get_config(request: gr.Request):
819911
"""Get configuration from cookies"""
820-
config = {
821-
"feel_consent": "false",
822-
}
823-
824-
if request and request.cookies:
825-
for key in config.keys():
826-
if key in request.cookies:
827-
config[key] = request.cookies[key]
828-
829-
return config["feel_consent"] == "true"
830-
831-
def initialize_consent_status(request: gr.Request):
832-
"""Initialize consent status and language preference from cookies"""
833-
has_consent = get_config(request)
834-
return has_consent
912+
config = {"feel_consent": False}
913+
if request and 'feel_consent' in request.cookies:
914+
config["feel_consent"] = request.cookies['feel_consent'] == 'true'
915+
return config["feel_consent"]
835916

836917
js = '''function js(){
837918
window.set_cookie = function(key, value){
838-
document.cookie = key+'='+value+'; Path=/; SameSite=Strict';
839-
return [value];
919+
console.log('Setting cookie:', key, value);
920+
document.cookie = key+'='+value+'; Path=/; SameSite=Strict; max-age=31536000'; // 1 year expiry
921+
console.log('Current cookies:', document.cookie);
922+
return [value]
923+
}
924+
925+
window.check_cookie = function(key){
926+
console.log('Checking cookie:', key);
927+
console.log('All cookies:', document.cookie);
928+
const value = document.cookie.split('; ').find(row => row.startsWith(key + '='))?.split('=')[1];
929+
console.log('Found value:', value);
930+
return [value === 'true']
840931
}
841932
}'''
842933

843934

844935

936+
845937
with gr.Blocks(css=css, js=js) as demo:
846938
# State variable to track if user has consented
847-
user_consented = gr.State(value=False)
848-
849-
# Initialize language dropdown first
850-
language = gr.State(value="English") # Default language state
851-
939+
user_consented = gr.State(value=False)
940+
leaderboard_data = gr.State([])
941+
942+
# Landing page with user agreement
943+
with gr.Group(visible=True) as landing_page:
944+
gr.Markdown("# Welcome to FeeL")
945+
with gr.Group(elem_classes=["user-agreement-container"]):
946+
gr.Markdown(USER_AGREEMENT)
947+
consent_btn = gr.Button("I agree")
948+
852949
# Main application interface (initially hidden)
853950
with gr.Group() as main_app:
854951
with gr.Row():
@@ -924,6 +1021,38 @@ def initialize_consent_status(request: gr.Request):
9241021
elem_classes=["add-language-btn"]
9251022
)
9261023

1024+
# Right column with leaderboard
1025+
with gr.Column(scale=3, elem_classes=["leaderboard-container"]):
1026+
gr.Markdown("# Language Leaderboard", elem_classes=["leaderboard-title"])
1027+
leaderboard_html = gr.HTML("Loading leaderboard...")
1028+
1029+
with gr.Accordion("Admin Controls", open=False, visible=False) as admin_panel:
1030+
with gr.Row():
1031+
admin_language = gr.Dropdown(choices=list(LANGUAGES.keys()), label="Language")
1032+
admin_count = gr.Number(value=0, label="Data Points")
1033+
set_count_btn = gr.Button("Set Count")
1034+
1035+
# toggle button for admin panel?
1036+
admin_toggle = gr.Button("Admin Controls", visible=True)
1037+
1038+
# update leaderboard HTML
1039+
def update_leaderboard_html(data):
1040+
if not data:
1041+
return "Loading leaderboard..."
1042+
1043+
html = "<div class='leaderboard-content'>"
1044+
for idx, (lang, count) in enumerate(data):
1045+
html += f"""
1046+
<div class='leaderboard-item'>
1047+
<span class='leaderboard-rank'>#{idx+1}</span>
1048+
<span class='leaderboard-language'>{lang}</span>
1049+
<span class='leaderboard-count'>{count}</span>
1050+
</div>
1051+
"""
1052+
html += "</div>"
1053+
return html
1054+
1055+
9271056
# Create a hidden group instead of a modal
9281057
with gr.Group(visible=False) as add_language_modal:
9291058
gr.Markdown("### Add New Language")
@@ -1086,6 +1215,11 @@ def update_visibility(has_consent):
10861215
).then(update_dataframe, inputs=[dataframe, chatbot], outputs=[dataframe]).then(
10871216
submit_conversation,
10881217
inputs=[dataframe, conversation_id, session_id, language],
1218+
outputs=[dataframe, chatbot, leaderboard_data]
1219+
).then(
1220+
update_leaderboard_html,
1221+
inputs=[leaderboard_data],
1222+
outputs=[leaderboard_html]
10891223
)
10901224

10911225
chatbot.like(
@@ -1128,11 +1262,27 @@ def on_app_load():
11281262
default_language = language_choices[0] if language_choices else "English"
11291263

11301264
return str(uuid.uuid4()), gr.Dropdown(choices=language_choices, value=default_language), default_language
1131-
1265+
1266+
def toggle_admin_panel(visible):
1267+
return gr.Accordion(visible=not visible)
1268+
1269+
def handle_set_count(language, count):
1270+
updated_data = set_language_data_points(language, int(count))
1271+
save_language_data_points()
1272+
return update_leaderboard_html(updated_data), updated_data
1273+
11321274
demo.load(
1133-
fn=on_app_load,
1275+
fn=lambda: (on_app_load(), load_initial_language_data()),
11341276
inputs=None,
1135-
outputs=[session_id, language_dropdown, language]
1277+
outputs=[
1278+
session_id,
1279+
language,
1280+
leaderboard_data
1281+
]
1282+
).then(
1283+
fn=update_leaderboard_html,
1284+
inputs=[leaderboard_data],
1285+
outputs=[leaderboard_html]
11361286
)
11371287

11381288
add_language_btn.click(
@@ -1225,4 +1375,16 @@ def save_languages_file(json_content):
12251375
outputs=[result_message]
12261376
)
12271377

1378+
admin_toggle.click(
1379+
fn=toggle_admin_panel,
1380+
inputs=[admin_panel],
1381+
outputs=[admin_panel]
1382+
)
1383+
1384+
set_count_btn.click(
1385+
fn=handle_set_count,
1386+
inputs=[admin_language, admin_count],
1387+
outputs=[leaderboard_html, leaderboard_data]
1388+
)
1389+
12281390
demo.launch()

app/leadboard_config.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import json
2+
from pathlib import Path
3+
import argparse
4+
5+
def set_initial_counts():
6+
"""command-line tool to set initial language data point counts"""
7+
parser = argparse.ArgumentParser(description='setup initial language data point counts for FeeL leaderboard')
8+
parser.add_argument('--language', type=str, help='Language to set count for')
9+
parser.add_argument('--count', type=int, help='Count to set for the language')
10+
parser.add_argument('--list', action='store_true', help='List current counts')
11+
12+
args = parser.parse_args()
13+
data_file = Path("language_data_points.json")
14+
15+
# Load existing data if available
16+
if data_file.exists():
17+
with open(data_file, "r", encoding="utf-8") as f:
18+
try:
19+
data = json.load(f)
20+
except json.JSONDecodeError:
21+
print("Error reading data file. Creating new data.")
22+
data = {}
23+
else:
24+
data = {}
25+
26+
# Load available languages
27+
languages_file = Path("languages.json")
28+
if languages_file.exists():
29+
with open(languages_file, "r", encoding="utf-8") as f:
30+
languages = json.load(f)
31+
else:
32+
print("Warning: languages.json not found. Cannot verify language names.")
33+
languages = {}
34+
35+
# current counts
36+
if args.list:
37+
print("Current language data point counts:")
38+
for lang in sorted(set(list(languages.keys()) + list(data.keys()))):
39+
count = data.get(lang, 0)
40+
print(f"{lang}: {count}")
41+
return
42+
43+
if args.language and args.count is not None:
44+
if args.language not in languages and languages:
45+
print(f"Warning: '{args.language}' is not in languages.json")
46+
confirm = input("Continue anyway? (y/n): ")
47+
if confirm.lower() != 'y':
48+
return
49+
50+
data[args.language] = args.count
51+
52+
# saving
53+
with open(data_file, "w", encoding="utf-8") as f:
54+
json.dump(data, f, ensure_ascii=False, indent=2)
55+
56+
print(f"Set count for {args.language} to {args.count}")
57+
elif not args.list:
58+
print("Please provide both --language and --count arguments")
59+
parser.print_help()
60+
61+
if __name__ == "__main__":
62+
set_initial_counts()

0 commit comments

Comments
 (0)