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