openfree's picture
Update app.py
47b7abe verified
raw
history blame
21.5 kB
import gradio as gr
import requests
import pandas as pd
import plotly.graph_objects as go
from datetime import datetime
import os
HF_TOKEN = os.getenv("HF_TOKEN")
target_models = {
"openfree/flux-lora-korea-palace": "https://huggingface.co/openfree/flux-lora-korea-palace",
"seawolf2357/hanbok": "https://huggingface.co/seawolf2357/hanbok",
"LGAI-EXAONE/EXAONE-3.5-32B-Instruct": "https://huggingface.co/LGAI-EXAONE/EXAONE-3.5-32B-Instruct",
"LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct": "https://huggingface.co/LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct",
"LGAI-EXAONE/EXAONE-3.5-7.8B-Instruct": "https://huggingface.co/LGAI-EXAONE/EXAONE-3.5-7.8B-Instruct",
"ginipick/flux-lora-eric-cat": "https://huggingface.co/ginipick/flux-lora-eric-cat",
"seawolf2357/flux-lora-car-rolls-royce": "https://huggingface.co/seawolf2357/flux-lora-car-rolls-royce"
}
def get_models_data(progress=gr.Progress()):
"""๋ชจ๋ธ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ"""
url = "https://huggingface.co/api/models"
params = {
'full': 'true',
'limit': 300 # ์ŠคํŽ˜์ด์Šค์™€ ๋™์ผํ•˜๊ฒŒ 300๊ฐœ๋กœ ์„ค์ •
}
try:
progress(0, desc="Fetching models data...")
response = requests.get(url, params=params)
if response.status_code != 200:
print(f"API ์š”์ฒญ ์‹คํŒจ: {response.status_code}")
print(f"Response: {response.text}")
print(f"URL: {url}")
return create_error_plot(), "<div>๋ชจ๋ธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.</div>", pd.DataFrame()
all_models = response.json()
# target_models์— ์žˆ๋Š” ๋ชจ๋ธ๋งŒ ํ•„ํ„ฐ๋ง
filtered_models = []
for model in all_models:
if model.get('id', '') in target_models:
model['rank'] = len(filtered_models) + 1
filtered_models.append(model)
if not filtered_models:
return create_error_plot(), "<div>์„ ํƒ๋œ ๋ชจ๋ธ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.</div>", pd.DataFrame()
progress(0.3, desc="Creating visualization...")
# ์‹œ๊ฐํ™” ์ƒ์„ฑ
fig = go.Figure()
# ๋ฐ์ดํ„ฐ ์ค€๋น„
ids = [model['id'] for model in filtered_models]
ranks = [model['rank'] for model in filtered_models]
likes = [model.get('likes', 0) for model in filtered_models]
# Y์ถ• ๊ฐ’์„ ๋ฐ˜์ „ (300 - rank + 1)
y_values = [301 - r for r in ranks]
# ๋ง‰๋Œ€ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ
fig.add_trace(go.Bar(
x=ids,
y=y_values,
text=[f"Rank: {r}<br>Likes: {l}" for r, l in zip(ranks, likes)],
textposition='auto',
marker_color='rgb(158,202,225)',
opacity=0.8
))
fig.update_layout(
title={
'text': 'Hugging Face Models Rankings (Top 300)',
'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'
},
xaxis_title='Model ID',
yaxis_title='Rank',
yaxis=dict(
ticktext=[str(i) for i in range(1, 301, 20)],
tickvals=[301 - i for i in range(1, 301, 20)],
range=[0, 300]
),
height=800,
showlegend=False,
template='plotly_white',
xaxis_tickangle=-45
)
progress(0.6, desc="Creating model cards...")
# HTML ์นด๋“œ ์ƒ์„ฑ
html_content = """
<div style='padding: 20px; background: #f5f5f5;'>
<h2 style='color: #2c3e50;'>Models Rankings</h2>
<div style='display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;'>
"""
for model in filtered_models:
model_id = model.get('id', '')
rank = model.get('rank', 'N/A')
likes = model.get('likes', 0)
downloads = model.get('downloads', 0)
html_content += f"""
<div style='
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.2s;
'>
<h3 style='color: #34495e;'>Rank #{rank} - {model_id}</h3>
<p style='color: #7f8c8d;'>๐Ÿ‘ Likes: {likes}</p>
<p style='color: #7f8c8d;'>โฌ‡๏ธ Downloads: {downloads}</p>
<a href='{target_models[model_id]}'
target='_blank'
style='
display: inline-block;
padding: 8px 16px;
background: #3498db;
color: white;
text-decoration: none;
border-radius: 5px;
transition: background 0.3s;
'>
Visit Model ๐Ÿ”—
</a>
</div>
"""
html_content += "</div></div>"
# ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ์ƒ์„ฑ
df = pd.DataFrame([{
'Rank': model.get('rank', 'N/A'),
'Model ID': model.get('id', ''),
'Likes': model.get('likes', 'N/A'),
'Downloads': model.get('downloads', 'N/A'),
'URL': target_models[model.get('id', '')]
} for model in filtered_models])
progress(1.0, desc="Complete!")
return fig, html_content, df
except Exception as e:
print(f"Error in get_models_data: {str(e)}")
return create_error_plot(), f"<div>์—๋Ÿฌ ๋ฐœ์ƒ: {str(e)}</div>", pd.DataFrame()
# ๊ด€์‹ฌ ์ŠคํŽ˜์ด์Šค URL ๋ฆฌ์ŠคํŠธ์™€ ์ •๋ณด
target_spaces = {
"ginipick/FLUXllama": "https://huggingface.co/spaces/ginipick/FLUXllama",
"ginipick/SORA-3D": "https://huggingface.co/spaces/ginipick/SORA-3D",
"fantaxy/Sound-AI-SFX": "https://huggingface.co/spaces/fantaxy/Sound-AI-SFX",
"fantos/flx8lora": "https://huggingface.co/spaces/fantos/flx8lora",
"ginigen/Canvas": "https://huggingface.co/spaces/ginigen/Canvas",
"fantaxy/erotica": "https://huggingface.co/spaces/fantaxy/erotica",
"ginipick/time-machine": "https://huggingface.co/spaces/ginipick/time-machine",
"aiqcamp/FLUX-VisionReply": "https://huggingface.co/spaces/aiqcamp/FLUX-VisionReply",
"openfree/Tetris-Game": "https://huggingface.co/spaces/openfree/Tetris-Game",
"openfree/everychat": "https://huggingface.co/spaces/openfree/everychat",
"VIDraft/mouse1": "https://huggingface.co/spaces/VIDraft/mouse1",
"kolaslab/alpha-go": "https://huggingface.co/spaces/kolaslab/alpha-go",
"ginipick/text3d": "https://huggingface.co/spaces/ginipick/text3d",
"openfree/trending-board": "https://huggingface.co/spaces/openfree/trending-board",
"cutechicken/tankwar": "https://huggingface.co/spaces/cutechicken/tankwar",
"openfree/game-jewel": "https://huggingface.co/spaces/openfree/game-jewel",
"VIDraft/mouse-chat": "https://huggingface.co/spaces/VIDraft/mouse-chat",
"ginipick/AccDiffusion": "https://huggingface.co/spaces/ginipick/AccDiffusion",
"aiqtech/Particle-Accelerator-Simulation": "https://huggingface.co/spaces/aiqtech/Particle-Accelerator-Simulation",
"openfree/GiniGEN": "https://huggingface.co/spaces/openfree/GiniGEN",
"kolaslab/3DAudio-Spectrum-Analyzer": "https://huggingface.co/spaces/kolaslab/3DAudio-Spectrum-Analyzer",
"openfree/trending-news-24": "https://huggingface.co/spaces/openfree/trending-news-24",
"ginipick/Realtime-FLUX": "https://huggingface.co/spaces/ginipick/Realtime-FLUX",
"VIDraft/prime-number": "https://huggingface.co/spaces/VIDraft/prime-number",
"kolaslab/zombie-game": "https://huggingface.co/spaces/kolaslab/zombie-game",
"fantos/miro-game": "https://huggingface.co/spaces/fantos/miro-game",
"kolaslab/shooting": "https://huggingface.co/spaces/kolaslab/shooting",
"VIDraft/Mouse-Hackathon": "https://huggingface.co/spaces/VIDraft/Mouse-Hackathon",
"upstage/open-ko-llm-leaderboard": "https://huggingface.co/spaces/upstage/open-ko-llm-leaderboard",
"LGAI-EXAONE/EXAONE-3.5-Instruct-Demo": "https://huggingface.co/spaces/LGAI-EXAONE/EXAONE-3.5-Instruct-Demo",
"NCSOFT/VARCO_Arena": "https://huggingface.co/spaces/NCSOFT/VARCO_Arena"
}
def get_spaces_data(sort_type="trending", progress=gr.Progress()):
"""์ŠคํŽ˜์ด์Šค ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ (trending ๋˜๋Š” modes)"""
url = f"https://huggingface.co/api/spaces"
params = {
'full': 'true',
'limit': 300
}
if sort_type == "modes":
params['sort'] = 'likes' # modes๋Š” ์ข‹์•„์š” ์ˆœ์œผ๋กœ ์ •๋ ฌ
try:
progress(0, desc=f"Fetching {sort_type} spaces data...")
response = requests.get(url, params=params)
response.raise_for_status()
all_spaces = response.json()
# ์ˆœ์œ„ ์ •๋ณด ์ €์žฅ
space_ranks = {space['id']: idx + 1 for idx, space in enumerate(all_spaces)}
# target_spaces ํ•„ํ„ฐ๋ง ๋ฐ ์ˆœ์œ„ ์ •๋ณด ํฌํ•จ
spaces = []
for space in all_spaces:
if space.get('id', '') in target_spaces:
space['rank'] = space_ranks.get(space['id'], 'N/A')
spaces.append(space)
# ์ˆœ์œ„๋ณ„๋กœ ์ •๋ ฌ
spaces.sort(key=lambda x: x['rank'])
progress(0.3, desc="Creating visualization...")
# ์‹œ๊ฐํ™” ์ƒ์„ฑ
fig = go.Figure()
# ๋ฐ์ดํ„ฐ ์ค€๋น„
ids = [space['id'] for space in spaces]
ranks = [space['rank'] for space in spaces]
likes = [space.get('likes', 0) for space in spaces]
# Y์ถ• ๊ฐ’์„ ๋ฐ˜์ „ (300 - rank + 1)
y_values = [301 - r for r in ranks] # ์ˆœ์œ„๋ฅผ ๋ฐ˜์ „๋œ ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜
# ๋ง‰๋Œ€ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ
fig.add_trace(go.Bar(
x=ids,
y=y_values,
text=[f"Rank: {r}<br>Likes: {l}" for r, l in zip(ranks, likes)],
textposition='auto',
marker_color='rgb(158,202,225)',
opacity=0.8
))
fig.update_layout(
title={
'text': f'Hugging Face Spaces {sort_type.title()} Rankings (Top 300)',
'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'
},
xaxis_title='Space ID',
yaxis_title='Rank',
yaxis=dict(
ticktext=[str(i) for i in range(1, 301, 20)], # 1๋ถ€ํ„ฐ 300๊นŒ์ง€ 20 ๊ฐ„๊ฒฉ
tickvals=[301 - i for i in range(1, 301, 20)], # ๋ฐ˜์ „๋œ ๊ฐ’
range=[0, 300] # y์ถ• ๋ฒ”์œ„ ์„ค์ •
),
height=800,
showlegend=False,
template='plotly_white',
xaxis_tickangle=-45
)
progress(0.6, desc="Creating space cards...")
# HTML ์นด๋“œ ์ƒ์„ฑ
html_content = f"""
<div style='padding: 20px; background: #f5f5f5;'>
<h2 style='color: #2c3e50;'>{sort_type.title()} Rankings</h2>
<div style='display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;'>
"""
for space in spaces:
space_id = space.get('id', '')
rank = space.get('rank', 'N/A')
likes = space.get('likes', 0)
title = space.get('title', 'No Title')
description = space.get('description', 'No Description')[:100]
html_content += f"""
<div style='
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.2s;
'>
<h3 style='color: #34495e;'>Rank #{rank} - {space_id}</h3>
<p style='color: #7f8c8d;'>๐Ÿ‘ Likes: {likes}</p>
<p style='color: #2c3e50;'>{title}</p>
<p style='color: #7f8c8d; font-size: 0.9em;'>{description}...</p>
<a href='{target_spaces[space_id]}'
target='_blank'
style='
display: inline-block;
padding: 8px 16px;
background: #3498db;
color: white;
text-decoration: none;
border-radius: 5px;
transition: background 0.3s;
'>
Visit Space ๐Ÿ”—
</a>
</div>
"""
html_content += "</div></div>"
# ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ์ƒ์„ฑ
df = pd.DataFrame([{
'Rank': space.get('rank', 'N/A'),
'Space ID': space.get('id', ''),
'Likes': space.get('likes', 'N/A'),
'Title': space.get('title', 'N/A'),
'URL': target_spaces[space.get('id', '')]
} for space in spaces])
progress(1.0, desc="Complete!")
return fig, html_content, df
except Exception as e:
error_html = f'<div style="color: red; padding: 20px;">Error: {str(e)}</div>'
error_plot = create_error_plot()
return error_plot, error_html, pd.DataFrame()
def create_trend_visualization(spaces_data):
if not spaces_data:
return create_error_plot()
fig = go.Figure()
# ์ˆœ์œ„ ๋ฐ์ดํ„ฐ ์ค€๋น„
ranks = []
for idx, space in enumerate(spaces_data, 1):
space_id = space.get('id', '')
if space_id in target_spaces:
ranks.append({
'id': space_id,
'rank': idx,
'likes': space.get('likes', 0),
'title': space.get('title', 'N/A'),
'views': space.get('views', 0)
})
if not ranks:
return create_error_plot()
# ์ˆœ์œ„๋ณ„๋กœ ์ •๋ ฌ
ranks.sort(key=lambda x: x['rank'])
# ํ”Œ๋กฏ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ
ids = [r['id'] for r in ranks]
rank_values = [r['rank'] for r in ranks]
likes = [r['likes'] for r in ranks]
views = [r['views'] for r in ranks]
# ๋ง‰๋Œ€ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ
fig.add_trace(go.Bar(
x=ids,
y=rank_values,
text=[f"Rank: {r}<br>Likes: {l}<br>Views: {v}" for r, l, v in zip(rank_values, likes, views)],
textposition='auto',
marker_color='rgb(158,202,225)',
opacity=0.8
))
fig.update_layout(
title={
'text': 'Current Trending Ranks (All Target Spaces)',
'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'
},
xaxis_title='Space ID',
yaxis_title='Trending Rank',
yaxis_autorange='reversed',
height=800,
showlegend=False,
template='plotly_white',
xaxis_tickangle=-45
)
return fig
# ํ† ํฐ์ด ์—†๋Š” ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•œ ๋Œ€์ฒด ํ•จ์ˆ˜
def get_trending_spaces_without_token():
try:
url = "https://huggingface.co/api/spaces"
params = {
'sort': 'likes',
'direction': -1,
'limit': 1000,
'full': 'true'
}
response = requests.get(url, params=params)
if response.status_code == 200:
return response.json()
else:
print(f"API ์š”์ฒญ ์‹คํŒจ (ํ† ํฐ ์—†์Œ): {response.status_code}")
print(f"Response: {response.text}")
return None
except Exception as e:
print(f"API ํ˜ธ์ถœ ์ค‘ ์—๋Ÿฌ ๋ฐœ์ƒ (ํ† ํฐ ์—†์Œ): {str(e)}")
return None
# API ํ† ํฐ ์„ค์ • ๋ฐ ํ•จ์ˆ˜ ์„ ํƒ
if not HF_TOKEN:
get_trending_spaces = get_trending_spaces_without_token
def create_error_plot():
fig = go.Figure()
fig.add_annotation(
text="๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.\n(API ์ธ์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค)",
xref="paper",
yref="paper",
x=0.5,
y=0.5,
showarrow=False,
font=dict(size=20)
)
fig.update_layout(
title="Error Loading Data",
height=400
)
return fig
def create_space_info_html(spaces_data):
if not spaces_data:
return "<div style='padding: 20px;'><h2>๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š”๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.</h2></div>"
html_content = """
<div style='padding: 20px;'>
<h2 style='color: #2c3e50;'>Current Trending Rankings</h2>
<div style='display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;'>
"""
# ๋ชจ๋“  target spaces๋ฅผ ํฌํ•จํ•˜๋„๋ก ์ˆ˜์ •
for space_id in target_spaces.keys():
space_info = next((s for s in spaces_data if s.get('id') == space_id), None)
if space_info:
rank = next((idx for idx, s in enumerate(spaces_data, 1) if s.get('id') == space_id), 'N/A')
html_content += f"""
<div style='
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.2s;
'>
<h3 style='color: #34495e;'>#{rank} - {space_id}</h3>
<p style='color: #7f8c8d;'>๐Ÿ‘ Likes: {space_info.get('likes', 'N/A')}</p>
<p style='color: #7f8c8d;'>๐Ÿ‘€ Views: {space_info.get('views', 'N/A')}</p>
<p style='color: #2c3e50;'>{space_info.get('title', 'N/A')}</p>
<p style='color: #7f8c8d; font-size: 0.9em;'>{space_info.get('description', 'N/A')[:100]}...</p>
<a href='{target_spaces[space_id]}'
target='_blank'
style='
display: inline-block;
padding: 8px 16px;
background: #3498db;
color: white;
text-decoration: none;
border-radius: 5px;
transition: background 0.3s;
'>
Visit Space ๐Ÿ”—
</a>
</div>
"""
else:
html_content += f"""
<div style='
background: #f8f9fa;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
'>
<h3 style='color: #34495e;'>{space_id}</h3>
<p style='color: #7f8c8d;'>Not in trending</p>
<a href='{target_spaces[space_id]}'
target='_blank'
style='
display: inline-block;
padding: 8px 16px;
background: #95a5a6;
color: white;
text-decoration: none;
border-radius: 5px;
'>
Visit Space ๐Ÿ”—
</a>
</div>
"""
html_content += "</div></div>"
return html_content
def create_data_table(spaces_data):
if not spaces_data:
return pd.DataFrame()
rows = []
for idx, space in enumerate(spaces_data, 1):
space_id = space.get('id', '')
if space_id in target_spaces:
rows.append({
'Rank': idx,
'Space ID': space_id,
'Likes': space.get('likes', 'N/A'),
'Title': space.get('title', 'N/A'),
'URL': target_spaces[space_id]
})
return pd.DataFrame(rows)
def refresh_data():
spaces_data = get_trending_spaces()
if spaces_data:
plot = create_trend_visualization(spaces_data)
info = create_space_info_html(spaces_data)
df = create_data_table(spaces_data)
return plot, info, df
else:
return create_error_plot(), "<div>API ์ธ์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.</div>", pd.DataFrame()
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# ๐Ÿค— ํ—ˆ๊น…ํŽ˜์ด์Šค 'ํ•œ๊ตญ ๋ฆฌ๋”๋ณด๋“œ'
์‹ค์‹œ๊ฐ„์œผ๋กœ Hugging Face์˜ Spaces์™€ Models ์ธ๊ธฐ ์ˆœ์œ„๋ฅผ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. ์‹ ๊ทœ ๋“ฑ๋ก ์š”์ฒญ: arxivgpt@gmail.com
""")
with gr.Tab("Spaces Trending"):
trending_plot = gr.Plot()
trending_info = gr.HTML()
trending_df = gr.DataFrame()
with gr.Tab("Models Trending"):
models_plot = gr.Plot()
models_info = gr.HTML()
models_df = gr.DataFrame()
refresh_btn = gr.Button("๐Ÿ”„ Refresh Data", variant="primary")
def refresh_all_data():
spaces_results = get_spaces_data("trending")
models_results = get_models_data()
return [*spaces_results, *models_results]
refresh_btn.click(
refresh_all_data,
outputs=[
trending_plot, trending_info, trending_df,
models_plot, models_info, models_df
]
)
# ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ๋กœ๋“œ
spaces_results = get_spaces_data("trending")
models_results = get_models_data()
trending_plot.value, trending_info.value, trending_df.value = spaces_results
models_plot.value, models_info.value, models_df.value = models_results
# Gradio ์•ฑ ์‹คํ–‰
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False
)