|
|
|
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 |
|
""" |
|
|
|
api_url = "https://huggingface.co/api/models" |
|
|
|
|
|
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: |
|
|
|
params = { |
|
"pipeline_tag": category, |
|
"sort": "likes7d", |
|
"direction": -1, |
|
"limit": 3, |
|
"full": True |
|
} |
|
|
|
response = requests.get(api_url, params=params, timeout=10) |
|
|
|
if response.status_code == 200: |
|
models = response.json() |
|
category_models = [] |
|
|
|
for model in models: |
|
|
|
model_id = model.get("id") or model.get("modelId") or model.get("_id", "Unknown") |
|
|
|
|
|
likes = (model.get("likes") or |
|
model.get("likesRecent") or |
|
model.get("likes7d") or 0) |
|
|
|
|
|
downloads = (model.get("downloads") or |
|
model.get("downloadsAllTime") or |
|
model.get("downloads_all_time") or |
|
model.get("downloads_last_month", 0)) |
|
|
|
|
|
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: |
|
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: |
|
|
|
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] |
|
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 |
|
|
|
|
|
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 "π₯" |
|
|
|
|
|
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() |
|
|
|
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 |
|
|
|
|
|
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(), |
|
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 |
|
|
|
|
|
if __name__ == "__main__": |
|
demo = create_interface() |
|
demo.launch( |
|
server_name="0.0.0.0", |
|
server_port=7860, |
|
share=False, |
|
debug=False |
|
) |