Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 8,218 Bytes
065a30a 75075b9 8adf41a 91cb2a2 75075b9 c6b4c88 93e0d72 75075b9 93e0d72 8adf41a dabc1e3 93e0d72 9350e9c 75075b9 e28fc42 421b84e b4d0ff6 75075b9 421b84e 75075b9 421b84e 75075b9 421b84e 75075b9 421b84e 452a3a4 75075b9 421b84e 7a0686a e9b5b0a c6b4c88 8adf41a 75075b9 8adf41a 75075b9 dabc1e3 75075b9 8adf41a 75075b9 8adf41a 75075b9 9350e9c 75075b9 9350e9c 75075b9 421b84e 8adf41a 606a083 8adf41a b4d0ff6 75075b9 165c76d 75075b9 b4d0ff6 75075b9 165c76d b4d0ff6 165c76d b0bb8b4 75075b9 9350e9c 75075b9 b4d0ff6 75075b9 8adf41a 75075b9 8adf41a 75075b9 165c76d c6b4c88 45cb0ff 165c76d 45cb0ff 75075b9 b4d0ff6 c6b4c88 75075b9 b4d0ff6 75075b9 45cb0ff 75075b9 165c76d 75075b9 165c76d b4d0ff6 165c76d 75075b9 6317b66 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
import os
import requests
from io import BytesIO
from datetime import date
import tempfile
import gradio as gr
from PIL import Image, ImageDraw, ImageFont
from huggingface_hub import upload_file
from criteria import check_certification as check_certification_criteria
from org import join_finishers_org
CERTIFYING_ORG_LINKEDIN_ID = os.getenv("CERTIFYING_ORG_LINKEDIN_ID", "000000")
COURSE_TITLE = os.getenv("COURSE_TITLE", "AI Agents Fundamentals")
def download_profile_picture(profile_url: str):
"""Download profile picture from URL."""
try:
response = requests.get(profile_url)
response.raise_for_status() # Ensure we got a proper response
return Image.open(BytesIO(response.content))
except Exception as e:
print(f"Error downloading profile picture from {profile_url}: {e}")
# Return a default fallback image (a plain white 100x100 image)
return Image.new("RGB", (100, 100), color="white")
def generate_certificate(certificate_path: str, name: str, profile_url: str):
"""Generate certificate image and PDF."""
im = Image.open(certificate_path)
d = ImageDraw.Draw(im)
name_font = ImageFont.truetype("Quattrocento-Regular.ttf", 100)
date_font = ImageFont.truetype("Quattrocento-Regular.ttf", 48)
# Capitalize first letter of each name
name = name.title()
# Add name
d.text((1000, 740), name, fill="black", anchor="mm", font=name_font)
# Add profile picture just below the name
profile_img = download_profile_picture(profile_url)
profile_img = profile_img.resize((100, 100))
im.paste(im=profile_img, box=(350, 700))
# Add date
d.text((1480, 1170), str(date.today()), fill="black", anchor="mm", font=date_font)
# Save PDF
pdf = im.convert("RGB")
pdf.save("certificate.pdf")
return im, "certificate.pdf"
def create_linkedin_button(username: str, cert_url: str | None) -> str:
"""Create LinkedIn 'Add to Profile' button HTML."""
current_year = date.today().year
current_month = date.today().month
# Use the dataset certificate URL if available, otherwise fallback to default
certificate_url = cert_url or "https://huggingface.co./agents-course-finishers"
linkedin_params = {
"startTask": "CERTIFICATION_NAME",
"name": COURSE_TITLE,
"organizationName": "Hugging Face",
"organizationId": CERTIFYING_ORG_LINKEDIN_ID,
"organizationIdissueYear": str(current_year),
"issueMonth": str(current_month),
"certUrl": certificate_url,
"certId": username, # Using username as cert ID
}
# Build the LinkedIn button URL
base_url = "https://www.linkedin.com/profile/add?"
params = "&".join(
f"{k}={requests.utils.quote(v)}" for k, v in linkedin_params.items()
)
button_url = base_url + params
message = f"""
<a href="{button_url}" target="_blank" style="display: block; margin-top: 20px; text-align: center;">
<img src="https://download.linkedin.com/desktop/add2profile/buttons/en_US.png"
alt="LinkedIn Add to Profile button">
</a>
"""
message += """
<a href="https://huggingface.co./agents-course-finishers" target="_blank"
style="display: inline-block; background-color: #fff7e0; border: 2px solid #ffa500;
border-radius: 10px; padding: 10px 20px; margin: 20px auto; text-align: center;
text-decoration: none; color: #000; white-space: nowrap;">
<img src="https://agents-course-unit1-certification-app.hf.space/gradio_api/file=/usr/local/lib/python3.10/site-packages/gradio/icons/huggingface-logo.svg"
style="display: inline-block; height: 20px; vertical-align: middle; margin-right: 10px;">
<span style="display: inline-block; vertical-align: middle; color: #000;">You are now an Agents Course Finisher</span>
</a>
"""
return message
def upload_certificate_to_hub(username: str, certificate_img) -> str:
"""Upload certificate to the dataset hub and return the URL."""
# Save image to temporary file
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
certificate_img.save(tmp.name)
try:
# Upload file to hub
repo_id = "agents-course/certificates"
path_in_repo = f"certificates/{username}/{date.today()}.png"
upload_file(
path_or_fileobj=tmp.name,
path_in_repo=path_in_repo,
repo_id=repo_id,
repo_type="dataset",
token=os.getenv("HF_TOKEN"),
)
# Construct the URL to the image
cert_url = (
f"https://huggingface.co./datasets/{repo_id}/resolve/main/{path_in_repo}"
)
# Clean up temp file
os.unlink(tmp.name)
return cert_url
except Exception as e:
print(f"Error uploading certificate: {e}")
os.unlink(tmp.name)
return None
def check_certification(
token: gr.OAuthToken | None,
profile: gr.OAuthProfile | None,
custom_name: str | None = None,
):
"""Check certification status for logged-in user."""
if token is None or profile is None:
gr.Warning("Please log in to Hugging Face before checking certification!")
return None, None, gr.Row.update(visible=False)
username = profile.username
# Use custom name if provided, otherwise fall back to profile name
name = custom_name.strip() if custom_name and custom_name.strip() else profile.name
profile_url = profile.picture
if not username:
return (
"Please login with your Hugging Face account to check certification status",
None,
gr.Row.update(visible=False),
)
# Check certification criteria
gr.Info("Collecting data from your course progress...")
result = check_certification_criteria(username)
# Generate certificate if passed
if result.passed and result.certificate_path:
certificate_img, pdf_path = generate_certificate(
certificate_path=result.certificate_path,
name=name,
profile_url=profile_url,
)
# Upload certificate to hub and get URL
cert_url = upload_certificate_to_hub(username, certificate_img)
# Add LinkedIn button for passed certificates
linkedin_button = create_linkedin_button(username, cert_url)
result_message = f"{result.message}\n\n{linkedin_button}"
else:
certificate_img = None
pdf_path = None
result_message = result.message
return (
gr.update(visible=True, value=result_message, label="Grade"),
gr.update(visible=result.passed, value=certificate_img, label="Certificate"),
)
with gr.Blocks() as demo:
gr.Markdown(
"""
# Get your Certificate of Fundamentals of Agents 🎓
The certification process is completely free.
To earn this certificate, you need to complete <a href="https://hf.co/learn/agents-course/unit1/introduction" alt="Agent Course Unit 1"/>Unit 1 of the Agents Course</a> and **pass 80% of the final quiz**.
Once you receive your certificate, don't hesitate to share it on X (and tag @huggingface) as well as on LinkedIn so that we can congratulate you.
"""
)
with gr.Row():
# Add login button
gr.LoginButton()
# Add optional name input
custom_name_input = gr.Textbox(
label="Custom Name (Optional)",
placeholder="Enter your name as you want it to appear on the certificate",
info="Leave empty to use your Hugging Face profile name",
)
check_progress_button = gr.Button(value="Get My Certificate")
output_text = gr.Markdown(visible=False, sanitize_html=False)
output_img = gr.Image(type="pil", visible=False)
check_progress_button.click(
fn=check_certification,
inputs=[custom_name_input],
outputs=[output_text, output_img],
).then(
fn=join_finishers_org,
)
if __name__ == "__main__":
demo.launch(debug=True, ssr_mode=False)
|