|
import gradio as gr |
|
from huggingface_hub import HfApi, hf_hub_download, Repository |
|
from huggingface_hub.repocard import metadata_load |
|
from gradio_client import Client |
|
from PIL import Image, ImageDraw, ImageFont |
|
|
|
from datetime import datetime, timezone, timedelta |
|
import time |
|
|
|
import os |
|
import sys |
|
from collections import defaultdict |
|
import pandas as pd |
|
import json |
|
import shutil |
|
|
|
api = HfApi() |
|
HF_TOKEN = os.environ.get("HF_TOKEN") |
|
|
|
|
|
DATASET_REPO_URL = f"https://wseo:{HF_TOKEN}@huggingface.co/datasets/pseudolab/huggingface-krew-hackathon2023" |
|
CERTIFIED_USERS_FILENAME = "certified.csv" |
|
|
|
ORGANIZATION = "pseudolab" |
|
|
|
|
|
START_DATE = datetime(2023, 10, 11, tzinfo=timezone(timedelta(hours=9))) |
|
END_DATE = datetime(2023, 11, 10, tzinfo=timezone(timedelta(hours=9))) |
|
|
|
|
|
def has_contributions(repo_type, hf_username, organization, likes=10): |
|
""" |
|
Check if a user has contributions in the specified repository type. |
|
:param repo_type: A repo type supported by the Hub |
|
:param hf_username: HF Hub username |
|
:param organization: HF Hub organization |
|
:param likes: Minimum number of likes for a contribution to be considered |
|
""" |
|
repo_list = { |
|
"model": api.list_models, |
|
"dataset": api.list_datasets, |
|
"space": api.list_spaces, |
|
} |
|
|
|
for repo in repo_list[repo_type](author=organization): |
|
if repo.likes < likes: |
|
continue |
|
commits = api.list_repo_commits(repo.id, repo_type=repo_type) |
|
if any(hf_username in commit.authors for commit in commits): |
|
return True |
|
return False |
|
|
|
|
|
def get_hub_footprint(hf_username, organization): |
|
""" |
|
Check the types of contributions a user has made. |
|
:param hf_username: HF Hub username |
|
:param organization: HF Hub organization |
|
""" |
|
has_models = has_contributions("model", hf_username, organization) |
|
has_datasets = has_contributions("dataset", hf_username, organization) |
|
has_spaces = has_contributions("space", hf_username, organization) |
|
|
|
return (has_models, has_datasets, has_spaces) |
|
|
|
|
|
def check_if_passed(hf_username): |
|
""" |
|
Check if given user contributed to hackathon |
|
:param hf_username: HF Hub username |
|
""" |
|
|
|
passed = False |
|
certificate_type = "" |
|
|
|
|
|
has_models, has_datasets, has_spaces = get_hub_footprint(hf_username, ORGANIZATION) |
|
if all(has_models, has_datasets, has_spaces): |
|
passed = True |
|
certificate_type = "excellence" |
|
elif any(has_models, has_datasets, has_spaces): |
|
passed = True |
|
certificate_type = "completion" |
|
|
|
return passed, certificate_type |
|
|
|
|
|
def generate_certificate(certificate_template, first_name, last_name, hf_username): |
|
""" |
|
Generates certificate from the template |
|
:param certificate_template: type of the certificate to generate |
|
:param first_name: first name entered by user |
|
:param last_name: last name entered by user |
|
:param hf_username: Hugging Face Hub username entered by user |
|
""" |
|
|
|
im = Image.open(certificate_template) |
|
d = ImageDraw.Draw(im) |
|
|
|
name_font = ImageFont.truetype("HeiseiMinchoStdW7.otf", 60) |
|
username_font = ImageFont.truetype("HeiseiMinchoStdW7.otf", 18) |
|
|
|
name = str(first_name) + " " + str(last_name) |
|
print("NAME", name) |
|
|
|
|
|
|
|
|
|
|
|
|
|
d.text((538, 419), name, fill=(87, 87, 87), anchor="mm", font=name_font) |
|
|
|
|
|
|
|
|
|
|
|
d.text((815, 327), f"HKH23-{hf_username}", fill=(117, 117, 117), font=username_font) |
|
|
|
pdf = im.convert("RGB") |
|
pdf.save("certificate.pdf") |
|
|
|
return im, "./certificate.pdf" |
|
|
|
|
|
def create_initial_csv(path): |
|
"""Create an initial CSV file with headers if it doesn't exist.""" |
|
|
|
headers = [ |
|
"hf_username", |
|
"first_name", |
|
"last_name", |
|
"certificate_type", |
|
"datetime", |
|
"pdf_path", |
|
] |
|
|
|
df = pd.DataFrame(columns=headers) |
|
|
|
df.to_csv(path, index=False) |
|
|
|
|
|
def add_certified_user(hf_username, first_name, last_name, certificate_type): |
|
""" |
|
Add the certified user to the dataset and include their certificate PDF. |
|
""" |
|
print("ADD CERTIFIED USER") |
|
repo = Repository( |
|
local_dir="data", |
|
clone_from=DATASET_REPO_URL, |
|
git_user="wseo", |
|
git_email="wonhseo.v@gmail.com", |
|
) |
|
repo.git_pull() |
|
|
|
csv_full_path = os.path.join("data", CERTIFIED_USERS_FILENAME) |
|
|
|
if not os.path.isfile(csv_full_path): |
|
create_initial_csv(csv_full_path) |
|
|
|
history = pd.read_csv(csv_full_path) |
|
|
|
|
|
check = history.loc[history["hf_username"] == hf_username] |
|
if not check.empty: |
|
history = history.drop(labels=check.index[0], axis=0) |
|
|
|
pdfs_repo_path = os.path.join("data", "certificates") |
|
|
|
|
|
pdf_repo_filename = f"{hf_username}.pdf" |
|
pdf_repo_path_full = os.path.join(pdfs_repo_path, pdf_repo_filename) |
|
|
|
|
|
os.makedirs(pdfs_repo_path, exist_ok=True) |
|
|
|
shutil.copy("./certificate.pdf", pdf_repo_path_full) |
|
|
|
new_row = pd.DataFrame( |
|
{ |
|
"hf_username": hf_username, |
|
"first_name": first_name, |
|
"last_name": last_name, |
|
"certificate_type": certificate_type, |
|
"datetime": time.time(), |
|
"pdf_path": pdf_repo_path_full[5:], |
|
}, |
|
index=[0], |
|
) |
|
|
|
history = pd.concat([new_row, history[:]]).reset_index(drop=True) |
|
|
|
|
|
history.to_csv(os.path.join("data", CERTIFIED_USERS_FILENAME), index=False) |
|
|
|
|
|
repo.git_add() |
|
repo.push_to_hub(commit_message="Update certified users list and add PDF") |
|
|
|
|
|
def create_certificate(passed, certificate_type, hf_username, first_name, last_name): |
|
""" |
|
Generates certificate, adds message, saves username of the certified user |
|
:param passed: boolean whether the user passed enough assignments |
|
:param certificate_type: type of the certificate - completion or excellence |
|
:param hf_username: Hugging Face Hub username entered by user |
|
:param first_name: first name entered by user |
|
:param last_name: last name entered by user |
|
""" |
|
|
|
if passed and certificate_type == "excellence": |
|
|
|
certificate, pdf = generate_certificate( |
|
"./certificate-excellence.png", first_name, last_name, hf_username |
|
) |
|
|
|
add_certified_user(hf_username, first_name, last_name, certificate_type) |
|
|
|
message = f""" |
|
Congratulations, you successfully completed the 2023 Hackathon 🎉! |
|
Since you contributed to models, datasets, and spaces- you get a Certificate of Excellence 🎓. |
|
You can download your certificate below ⬇️ |
|
https://huggingface.co/datasets/pseudolab/huggingface-krew-hackathon2023/resolve/main/certificates/{hf_username}.pdf\n |
|
Don't hesitate to share your certificate link above on Twitter and Linkedin (you can tag me @wonhseo, @pseudo-lab and @huggingface) 🤗 |
|
|
|
""" |
|
elif passed and certificate_type == "completion": |
|
|
|
certificate, pdf = generate_certificate( |
|
"./certificate-completion.png", first_name, last_name, hf_username |
|
) |
|
|
|
add_certified_user(hf_username, first_name, last_name, certificate_type) |
|
|
|
message = f""" |
|
Congratulations, you successfully completed the 2023 Hackathon 🎉! |
|
Since you contributed to at least one model, dataset, or space- you get a Certificate of Completion 🎓. |
|
You can download your certificate below ⬇️ |
|
https://huggingface.co/datasets/pseudolab/huggingface-krew-hackathon2023/resolve/main/certificates/{hf_username}.pdf\n |
|
Don't hesitate to share your certificate link above on Twitter and Linkedin (you can tag me @wonhseo and @huggingface) 🤗 |
|
You can try to get a Certificate of Excellence if you contribute to all types of repos, please don't hesitate to do so. |
|
""" |
|
else: |
|
|
|
certificate = Image.new("RGB", (100, 100), (255, 255, 255)) |
|
pdf = "./fail.pdf" |
|
|
|
message = """ |
|
You didn't pass the minimum of one contribution to get a certificate of completion. |
|
For more information about the certification process, refer to the hackathon page. |
|
If the results here differ from your contributions, make sure you moved your space to the pseudolab organization. |
|
""" |
|
return certificate, message, pdf |
|
|
|
|
|
def certification(hf_username, first_name, last_name): |
|
passed, certificate_type = check_if_passed(hf_username) |
|
certificate, message, pdf = create_certificate( |
|
passed, certificate_type, hf_username, first_name, last_name |
|
) |
|
print("MESSAGE", message) |
|
|
|
if passed: |
|
visible = True |
|
else: |
|
visible = False |
|
|
|
return message, pdf, certificate, output_row.update(visible=visible) |
|
|
|
|
|
def make_clickable_repo(name, repo_type): |
|
if repo_type == "space": |
|
link = "https://huggingface.co/" + "spaces/" + name |
|
elif repo_type == "model": |
|
link = "https://huggingface.co/" + name |
|
elif repo_type == "dataset": |
|
link = "https://huggingface.co/" + "datasets/" + name |
|
return f'<a target="_blank" href="{link}">{name.split("/")[-1]}</a>' |
|
|
|
|
|
def make_clickable_user(user_id): |
|
link = "https://huggingface.co/" + user_id |
|
return f'<a target="_blank" href="{link}">{user_id}</a>' |
|
|
|
|
|
def leaderboard(): |
|
""" |
|
Get the leaderboard of the hackathon. |
|
|
|
The leaderboard is a Pandas DataFrame with the following columns: |
|
- Rank: the rank of the user in the leaderboard |
|
- User: the Hugging Face username of the user |
|
- Contributions: the list of contributions of the user (models, datasets, spaces) |
|
- Likes: the total number of likes of the user's contributions |
|
""" |
|
repo_list = { |
|
'model': api.list_models, |
|
'dataset': api.list_datasets, |
|
'space': api.list_spaces |
|
} |
|
|
|
|
|
not_included = [ |
|
|
|
|
|
|
|
|
|
] |
|
|
|
contributions = defaultdict(list) |
|
|
|
for repo_type in repo_list: |
|
for repo in repo_list[repo_type](author=ORGANIZATION): |
|
if repo.id.split('/')[-1] in not_included: |
|
continue |
|
commits = api.list_repo_commits(repo.id, repo_type=repo_type) |
|
for author in set(author for commit in commits if START_DATE < commit.created_at < END_DATE for author in commit.authors): |
|
contributions[author].append((repo_type, repo.id, repo.likes)) |
|
|
|
leaderboard = [] |
|
for user, repo_likes in contributions.items(): |
|
repos = [] |
|
user_likes = 0 |
|
for repo_type, repo, likes in repo_likes: |
|
repos.append(make_clickable_repo(repo, repo_type)) |
|
user_likes += likes |
|
leaderboard.append([make_clickable_user(user), '- ' + '\n- '.join(repos), user_likes]) |
|
|
|
df = pd.DataFrame(data=leaderboard, columns=["User 👤", "Contributions 🛠️", "Likes ❤️"]) |
|
df.sort_values(by=["Likes ❤️"], ascending=False, inplace=True) |
|
df.insert(0, "Rank 🏆", list(range(1, len(df) + 1))) |
|
|
|
return df |
|
|
|
|
|
with gr.Blocks() as demo: |
|
gr.Markdown( |
|
'<img style="display: block; margin-left: auto; margin-right: auto; height: 10em;"' |
|
' src="file/hfkr_logo.png"/>\n\n' |
|
'<h1 style="text-align: center;">Hugging Face KREW Hackathon 2023: Everyday AI</h1>' |
|
) |
|
with gr.Row(): |
|
with gr.Column() as certificate_column: |
|
gr.Markdown( |
|
f""" |
|
## Get your 2023 Hackathon Certificate 🎓 |
|
The certification process is completely free: |
|
- To get a *certificate of completion*: you need to **contribute to at least one model, dataset, or space**. |
|
- To get a *certificate of excellence*: you need to **contribute to models, datasets, and spaces**. *(Yes, all three!)* |
|
|
|
For more information about the certification process [check the hackathon page on certification](https://pseudo-lab.github.io/huggingface-hackathon23/tutorials/project-roadmap.html#certification). |
|
Don't hesitate to share your certificate on Twitter (tag me [@wonhseo](https://twitter.com/wonhseo) and [@huggingface](https://twitter.com/huggingface)) and on LinkedIn. |
|
""" |
|
) |
|
|
|
hf_username = gr.Textbox( |
|
placeholder="wseo", label="Your Hugging Face Username (case sensitive)" |
|
) |
|
first_name = gr.Textbox(placeholder="Wonhyeong", label="Your First Name") |
|
last_name = gr.Textbox(placeholder="Seo", label="Your Last Name") |
|
|
|
check_progress_button = gr.Button(value="Check if I pass and get the certificate") |
|
output_text = gr.components.Textbox(label="Your Result") |
|
|
|
with gr.Row(visible=True) as output_row: |
|
output_pdf = gr.File() |
|
output_img = gr.components.Image(type="pil") |
|
|
|
check_progress_button.click( |
|
fn=certification, |
|
inputs=[hf_username, first_name, last_name], |
|
outputs=[output_text, output_pdf, output_img, output_row], |
|
) |
|
with gr.Column() as leaderboard_column: |
|
gr.Markdown( |
|
f""" |
|
## ❤️ Leaderboard |
|
The leaderboard showcases your contributions for easy sharing on SNS platforms: |
|
|
|
- Event #1: *1 repo 1 share* - **share your contributions to the world!** |
|
- (more on the way!) |
|
|
|
For more information about the offline event [check our event-us page](https://event-us.kr/huggingfacekrew/event/72612). |
|
Don't hesitate to share your contributions on Twitter (tag me [@wonhseo](https://twitter.com/wonhseo) and [@huggingface](https://twitter.com/huggingface)) and on LinkedIn. |
|
|
|
<a class="twitter-share-button" data-size="large" |
|
data-text="I'm participating in the Hugging Face KREW Hackathon 2023: Everyday AI! @wonhseo @huggingface" |
|
data-url="https://huggingface.co/spaces/pseudolab/2023-Hackathon-Certification" |
|
data-hashtags="huggingface,krewhackathon2023" |
|
href="https://twitter.com/intent/tweet"> |
|
Tweet</a> |
|
""" |
|
) |
|
with gr.Row(): |
|
repos_data = gr.components.Dataframe( |
|
type="pandas", datatype=["number", "markdown", "markdown", "number"] |
|
) |
|
with gr.Row(): |
|
data_run = gr.Button("Refresh") |
|
data_run.click( |
|
leaderboard, outputs=repos_data |
|
) |
|
|
|
scripts = """ |
|
async () => { |
|
const twitter = await import("https://platform.twitter.com/widgets.js"); |
|
globalThis.twitter = twitter; |
|
} |
|
""" |
|
|
|
demo.load(leaderboard, outputs=repos_data) |
|
demo.load(None, None, None, _js=scripts) |
|
|
|
demo.launch(debug=True) |
|
|