Spaces:
Sleeping
Sleeping
# GRADIO HF SPACE | |
import gradio as gr | |
import requests | |
import pandas as pd | |
from datetime import datetime, timedelta | |
import urllib.parse | |
def get_hf_models_by_category(): | |
""" | |
Fetch top 3 models from each Hugging Face category ranked by likes7d | |
""" | |
# Hugging Face API endpoint | |
api_url = "https://huggingface.co/api/models" | |
# Common model categories on Hugging Face | |
categories = [ | |
"text-generation", | |
"text-classification", | |
"token-classification", | |
"question-answering", | |
"fill-mask", | |
"summarization", | |
"translation", | |
"text2text-generation", | |
"image-classification", | |
"object-detection", | |
"image-segmentation", | |
"text-to-image", | |
"image-to-text", | |
"automatic-speech-recognition", | |
"audio-classification", | |
"text-to-speech", | |
"audio-to-audio", | |
"voice-activity-detection", | |
"depth-estimation", | |
"image-feature-extraction", | |
"other" | |
] | |
results = {} | |
for category in categories: | |
try: | |
# Fetch models for this category, sorted by likes in the last 7 days | |
params = { | |
"pipeline_tag": category, | |
"sort": "likes7d", | |
"direction": -1, | |
"limit": 3, | |
"full": True # Get full model info including downloads | |
} | |
response = requests.get(api_url, params=params, timeout=10) | |
if response.status_code == 200: | |
models = response.json() | |
category_models = [] | |
for model in models: | |
# Try different field names for model ID | |
model_id = model.get("id") or model.get("modelId") or model.get("_id", "Unknown") | |
# Get likes (might be in different fields) | |
likes = (model.get("likes") or | |
model.get("likesRecent") or | |
model.get("likes7d") or 0) | |
# Get downloads (different possible field names) | |
downloads = (model.get("downloads") or | |
model.get("downloadsAllTime") or | |
model.get("downloads_all_time") or | |
model.get("downloads_last_month", 0)) | |
# Get last modified date | |
last_modified = (model.get("lastModified") or | |
model.get("last_modified") or | |
model.get("createdAt") or | |
model.get("updatedAt") or "Unknown") | |
model_info = { | |
"name": model_id, | |
"likes": likes, | |
"downloads": downloads, | |
"updated": last_modified, | |
"url": f"https://huggingface.co/{model_id}" | |
} | |
category_models.append(model_info) | |
if category_models: # Only add if we found models | |
results[category] = category_models | |
except Exception as e: | |
print(f"Error fetching {category}: {str(e)}") | |
continue | |
return results | |
def format_number(num): | |
"""Format large numbers in a readable way""" | |
if num >= 1000000: | |
return f"{num/1000000:.1f}M" | |
elif num >= 1000: | |
return f"{num/1000:.1f}k" | |
else: | |
return str(num) | |
def format_date(date_str): | |
"""Format date string to be more readable""" | |
if date_str == "Unknown" or not date_str: | |
return "Unknown" | |
try: | |
# Parse the ISO date string and format it | |
if "T" in date_str: | |
date_obj = datetime.fromisoformat(date_str.replace("Z", "+00:00")) | |
return date_obj.strftime("%Y-%m-%d") | |
else: | |
return date_str[:10] # Just take the date part | |
except: | |
return "Unknown" | |
def format_model_display(models_data): | |
""" | |
Format the models data into a nice display format | |
""" | |
if not models_data: | |
return "No models found or API unavailable." | |
html_content = """ | |
<div style="font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto;"> | |
<h1 style="text-align: center; color: #ff6b6b; margin-bottom: 30px;"> | |
π€ Top 3 Hugging Face Models by Category (Last 7 Days) | |
</h1> | |
""" | |
for category, models in models_data.items(): | |
if not models: | |
continue | |
# Format category name | |
category_display = category.replace("-", " ").title() | |
html_content += f""" | |
<div style="margin-bottom: 40px; border: 2px solid #f0f0f0; border-radius: 10px; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white;"> | |
<h2 style="margin-top: 0; text-align: center; font-size: 24px; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);"> | |
π {category_display} | |
</h2> | |
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 20px; margin-top: 20px;"> | |
""" | |
for i, model in enumerate(models[:3], 1): | |
medal = "π₯" if i == 1 else "π₯" if i == 2 else "π₯" | |
# Format the numbers and date | |
likes_formatted = format_number(model['likes']) | |
downloads_formatted = format_number(model['downloads']) | |
date_formatted = format_date(model['updated']) | |
author = model['name'].split("/")[0] | |
model_name = model['name'].split("/")[-1] | |
model_normal_name = model_name.replace("-", " ").title() | |
# Create YouTube search URL | |
youtube_search_query = urllib.parse.quote(f"{model_normal_name} {author} AI") | |
youtube_url = f"https://www.youtube.com/results?search_query={youtube_search_query}" | |
html_content += f""" | |
<div style="background: rgba(255,255,255,0.95); color: #333; padding: 20px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); display: flex; flex-direction: column; height: 100%;"> | |
<div style="display: flex; align-items: center; margin-bottom: 15px;"> | |
<span style="font-size: 24px; margin-right: 10px;">{medal}</span> | |
<h3 style="margin: 0; font-size: 16px; color: #2d3748;">#{i}</h3> | |
</div> | |
<h4 style="margin: 0 0 15px 0; font-size: 18px; color: #2b6cb0; word-break: break-word; line-height: 1.3; flex-grow: 1;"> | |
<a href="{model['url']}" target="_blank" style="text-decoration: none; color: #2b6cb0;"> | |
{model['name']} | |
</a> | |
</h4> | |
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-bottom: 15px;"> | |
<div style="text-align: center; padding: 8px; background: #f7fafc; border-radius: 6px;"> | |
<div style="font-size: 16px; margin-bottom: 2px;">β€οΈ</div> | |
<div style="font-size: 12px; color: #4a5568; font-weight: bold;">Likes</div> | |
<div style="background: #e53e3e; color: white; padding: 2px 6px; border-radius: 12px; font-size: 11px; margin-top: 4px; display: inline-block;"> | |
{likes_formatted} | |
</div> | |
</div> | |
<div style="text-align: center; padding: 8px; background: #f7fafc; border-radius: 6px;"> | |
<div style="font-size: 16px; margin-bottom: 2px;">π₯</div> | |
<div style="font-size: 12px; color: #4a5568; font-weight: bold;">Downloads</div> | |
<div style="background: #38a169; color: white; padding: 2px 6px; border-radius: 12px; font-size: 11px; margin-top: 4px; display: inline-block;"> | |
{downloads_formatted} | |
</div> | |
</div> | |
<div style="text-align: center; padding: 8px; background: #f7fafc; border-radius: 6px;"> | |
<div style="font-size: 16px; margin-bottom: 2px;">π</div> | |
<div style="font-size: 12px; color: #4a5568; font-weight: bold;">Updated</div> | |
<div style="background: #3182ce; color: white; padding: 2px 6px; border-radius: 12px; font-size: 11px; margin-top: 4px; display: inline-block;"> | |
{date_formatted} | |
</div> | |
</div> | |
</div> | |
<div style="display: flex; gap: 8px; margin-top: auto;"> | |
<a href="{model['url']}" target="_blank" style="flex: 1; text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 8px 12px; border-radius: 6px; text-decoration: none; font-size: 12px; font-weight: bold; transition: all 0.2s;"> | |
π€ View Model | |
</a> | |
<a href="{youtube_url}" target="_blank" style="flex: 1; text-align: center; background: linear-gradient(135deg, #ff0000 0%, #cc0000 100%); color: white; padding: 8px 12px; border-radius: 6px; text-decoration: none; font-size: 12px; font-weight: bold; transition: all 0.2s;"> | |
πΊ Find on YouTube | |
</a> | |
</div> | |
</div> | |
""" | |
html_content += """ | |
</div> | |
</div> | |
""" | |
html_content += f""" | |
<div style="text-align: center; margin-top: 30px; padding: 20px; background-color: #f8f9fa; border-radius: 10px;"> | |
<p style="color: #6c757d; font-style: italic; margin-bottom: 10px;"> | |
π Data fetched from Hugging Face API β’ Updated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} UTC | |
</p> | |
<p style="color: #6c757d; font-size: 12px; margin: 0;"> | |
Rankings based on likes received in the last 7 days β’ Found {len(models_data)} categories with active models | |
</p> | |
</div> | |
</div> | |
""" | |
return html_content | |
def refresh_models(): | |
""" | |
Refresh and get the latest model data | |
""" | |
models_data = get_hf_models_by_category() | |
formatted_display = format_model_display(models_data) | |
return formatted_display | |
# Create Gradio interface | |
def create_interface(): | |
with gr.Blocks( | |
title="π€ Top HF Models by Category", | |
theme=gr.themes.Soft(), | |
css=""" | |
.gradio-container { | |
max-width: 1400px !important; | |
} | |
.gr-button { | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; | |
border: none !important; | |
color: white !important; | |
} | |
""" | |
) as demo: | |
gr.Markdown(""" | |
# π€ Hugging Face Model Explorer | |
Discover the most popular models across different categories on Hugging Face! | |
This space shows the **top 3 models** in each category ranked by **likes received in the last 7 days**. | |
Click the refresh button to get the latest rankings! | |
""") | |
with gr.Row(): | |
refresh_btn = gr.Button( | |
"π Refresh Rankings", | |
variant="primary", | |
size="lg" | |
) | |
with gr.Row(): | |
gr.Markdown(""" | |
**π― What you'll see:** | |
- β€οΈ **Likes**: Community appreciation in the last 7 days | |
- π₯ **Downloads**: Total download count (all-time) | |
- π **Updated**: Last modification date | |
- π€ **View Model**: Direct link to model page | |
- πΊ **Find on YouTube**: Search for tutorials and demos | |
""") | |
output_html = gr.HTML( | |
value=refresh_models(), # Load initial data | |
label="Top Models by Category" | |
) | |
refresh_btn.click( | |
fn=refresh_models, | |
outputs=output_html | |
) | |
gr.Markdown(""" | |
--- | |
### βΉοΈ About This Space | |
- **Data Source**: Hugging Face Models API (`/api/models`) | |
- **Ranking Metric**: Likes received in the last 7 days (`sort=likes7d`) | |
- **Categories**: All major model types (text, image, audio, multimodal, etc.) | |
- **Update Frequency**: Real-time (when you click refresh) | |
**Note**: Only categories with available models are displayed. Some specialized categories might not appear if no models are currently trending. | |
π **Pro tip**: Use the YouTube button to find tutorials, demos, and implementation guides for each model! | |
""") | |
return demo | |
# Launch the application | |
if __name__ == "__main__": | |
demo = create_interface() | |
demo.launch( | |
server_name="0.0.0.0", # For Hugging Face Spaces | |
server_port=7860, # Standard port for HF Spaces | |
share=False, | |
debug=False | |
) |