import gradio as gr import spaces import requests import pandas as pd import plotly.graph_objects as go from datetime import datetime import os import asyncio import aiohttp # Neumorphism CSS 스타일 CUSTOM_CSS = """ /* ═══════════════════════════════════════════════════════════ 🔘 NEUMORPHISM 스타일 ═══════════════════════════════════════════════════════════ */ :root { --neu-bg: #e0e5ec; --neu-shadow-dark: #b8bec5; --neu-shadow-light: #ffffff; --neu-text: #6d7b8d; --neu-text-dark: #5a6677; --neu-accent: #FF6B6B; --neu-accent-2: #4ECDC4; } body, .gradio-container { background: var(--neu-bg) !important; } .neu-container { background: var(--neu-bg); padding: 30px; border-radius: 25px; } .neu-raised { background: var(--neu-bg); border-radius: 20px; box-shadow: 8px 8px 16px var(--neu-shadow-dark), -8px -8px 16px var(--neu-shadow-light); padding: 25px; margin-bottom: 20px; } .neu-inset { background: var(--neu-bg); border-radius: 15px; box-shadow: inset 6px 6px 12px var(--neu-shadow-dark), inset -6px -6px 12px var(--neu-shadow-light); padding: 20px; } .neu-button, button.primary { background: var(--neu-bg) !important; border: none !important; border-radius: 50px !important; padding: 18px 50px !important; color: var(--neu-text) !important; font-weight: 700 !important; box-shadow: 8px 8px 16px var(--neu-shadow-dark), -8px -8px 16px var(--neu-shadow-light) !important; transition: all 0.2s ease !important; } .neu-button:hover, button.primary:hover { box-shadow: 4px 4px 8px var(--neu-shadow-dark), -4px -4px 8px var(--neu-shadow-light) !important; transform: translateY(-2px); } .neu-button:active, button.primary:active { box-shadow: inset 4px 4px 8px var(--neu-shadow-dark), inset -4px -4px 8px var(--neu-shadow-light) !important; } .neu-text { color: var(--neu-text); text-shadow: 2px 2px 4px var(--neu-shadow-light), -1px -1px 3px rgba(0,0,0,0.1); } .gradio-container .tabs { background: var(--neu-bg) !important; } .gradio-container .tab-nav button { background: var(--neu-bg) !important; border-radius: 15px !important; margin: 5px !important; box-shadow: 5px 5px 10px var(--neu-shadow-dark), -5px -5px 10px var(--neu-shadow-light) !important; color: var(--neu-text) !important; font-weight: 600 !important; } .gradio-container .tab-nav button.selected { box-shadow: inset 4px 4px 8px var(--neu-shadow-dark), inset -4px -4px 8px var(--neu-shadow-light) !important; color: var(--neu-accent) !important; } #spaces_pie, #models_pie, #spaces_bar, #models_bar { min-height: 400px; border-radius: 20px; box-shadow: 8px 8px 16px var(--neu-shadow-dark), -8px -8px 16px var(--neu-shadow-light); background: var(--neu-bg); padding: 15px; } .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 25px; padding: 20px; } .space-card { background: var(--neu-bg); border-radius: 20px; padding: 25px; box-shadow: 8px 8px 16px var(--neu-shadow-dark), -8px -8px 16px var(--neu-shadow-light); transition: transform 0.3s ease, box-shadow 0.3s ease; } .space-card:hover { transform: translateY(-5px); box-shadow: 12px 12px 24px var(--neu-shadow-dark), -12px -12px 24px var(--neu-shadow-light); } .visit-link { display: inline-block; padding: 12px 24px; background: var(--neu-bg); color: var(--neu-text); text-decoration: none; border-radius: 50px; font-weight: 600; box-shadow: 5px 5px 10px var(--neu-shadow-dark), -5px -5px 10px var(--neu-shadow-light); transition: all 0.2s ease; } .visit-link:hover { box-shadow: 3px 3px 6px var(--neu-shadow-dark), -3px -3px 6px var(--neu-shadow-light); color: var(--neu-accent); } .korea-badge { display: inline-block; padding: 5px 15px; background: linear-gradient(145deg, #FF6B6B, #FF8E8E); color: white; border-radius: 20px; font-size: 12px; font-weight: 600; } .main-title { color: var(--neu-text-dark); font-size: 2em; font-weight: 800; text-shadow: 2px 2px 4px var(--neu-shadow-light), -1px -1px 3px rgba(0,0,0,0.1); } ::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar-track { background: var(--neu-bg); border-radius: 10px; } ::-webkit-scrollbar-thumb { background: linear-gradient(145deg, #c8cdd4, #f0f5fc); border-radius: 10px; } """ # ZeroGPU 더미 함수 @spaces.GPU(duration=1) def dummy_gpu_function(): return "GPU initialized" def initialize_app(): try: result = dummy_gpu_function() print(f"[ZeroGPU] {result}") except Exception as e: print(f"[ZeroGPU] Running without GPU: {e}") return True app_initialized = initialize_app() HF_TOKEN = os.getenv("HF_TOKEN") # 한국 관련 조직/사용자 계정 목록 (모델 및 스페이스 검색에 사용) KOREAN_ORGS = [ "keeperballon", "openfree", "VIDraft", "vidraft", "ginigen", "ginipick", "Heartsync", "heartsync", "seawolf2357", "aiqcamp", "aiqtech", "fantaxy", "fantos", "immunobiotech", "yokoha", "cutechicken", "kolaslab", "gunship999", "moreh", "OnomaAIResearch", "LGAI-EXAONE", "naver-hyperclovax", "naver-ai", "kakaocorp", "kakaobrain", "kakaobank", "K-intelligence", "skt", "SamsungResearch", "SamsungSAILMontreal", "upstage", "NCSOFT", "LDCC", "nari-labs", "etri-vilab", "etri-xainlp", "etri-lirs", "ETRI-XAINLP", "Bllossom", "MLP-KTLim", "DILAB-HYU", "nlpai-lab", "kyujinpy", "beomi", "maywell", "yanolja", "saltlux", "42dot", "Edentns", "snunlp", "SKT-AI", "monologg", "cosmoquester", "krevas", "EleutherAI", "kaist-ai", "KAERI-MLP", "dnotitia", "OLAResearch" ] target_models = { "K-intelligence/Midm-2.0-Mini-Instruct": "https://huggingface.co/K-intelligence/Midm-2.0-Mini-Instruct", "K-intelligence/Midm-2.0-Base-Instruct": "https://huggingface.co/K-intelligence/Midm-2.0-Base-Instruct", "VIDraft/Qwen3-R1984-30B-A3B": "https://huggingface.co/VIDraft/Qwen3-R1984-30B-A3B", "VIDraft/Gemma-3-R1984-1B": "https://huggingface.co/VIDraft/Gemma-3-R1984-1B", "VIDraft/Qwen3-R1984-0.6B": "https://huggingface.co/VIDraft/Qwen3-R1984-0.6B", "VIDraft/Qwen3-R1984-4B": "https://huggingface.co/VIDraft/Qwen3-R1984-4B", "seawolf2357/kim-korea": "https://huggingface.co/seawolf2357/kim-korea", "ginipick/QwQ-32B-NF4": "https://huggingface.co/ginipick/QwQ-32B-NF4", "naver-hyperclovax/HyperCLOVAX-SEED-Text-Instruct-0.5B": "https://huggingface.co/naver-hyperclovax/HyperCLOVAX-SEED-Text-Instruct-0.5B", "naver-hyperclovax/HyperCLOVAX-SEED-Text-Instruct-1.5B": "https://huggingface.co/naver-hyperclovax/HyperCLOVAX-SEED-Text-Instruct-1.5B", "naver-hyperclovax/HyperCLOVAX-SEED-Vision-Instruct-3B": "https://huggingface.co/naver-hyperclovax/HyperCLOVAX-SEED-Vision-Instruct-3B", "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", "LGAI-EXAONE/EXAONE-Deep-32B": "https://huggingface.co/LGAI-EXAONE/EXAONE-Deep-32B", "LGAI-EXAONE/EXAONE-Deep-2.4B": "https://huggingface.co/LGAI-EXAONE/EXAONE-Deep-2.4B", "LGAI-EXAONE/EXAONE-Deep-7.8B": "https://huggingface.co/LGAI-EXAONE/EXAONE-Deep-7.8B", "moreh/Llama-3-Motif-102B-Instruct": "https://huggingface.co/moreh/Llama-3-Motif-102B-Instruct", "moreh/Llama-3-Motif-102B": "https://huggingface.co/moreh/Llama-3-Motif-102B", "moreh/MoMo-72B-lora-1.8.7-DPO": "https://huggingface.co/moreh/MoMo-72B-lora-1.8.7-DPO", "OnomaAIResearch/Illustrious-XL-v2.0": "https://huggingface.co/OnomaAIResearch/Illustrious-XL-v2.0", "OnomaAIResearch/Illustrious-Lumina-v0.03": "https://huggingface.co/OnomaAIResearch/Illustrious-Lumina-v0.03", "OnomaAIResearch/Illustrious-xl-early-release-v0": "https://huggingface.co/OnomaAIResearch/Illustrious-xl-early-release-v0", "OnomaAIResearch/Illustrious-XL-v1.0": "https://huggingface.co/OnomaAIResearch/Illustrious-XL-v1.0", "OnomaAIResearch/Illustrious-XL-v1.1": "https://huggingface.co/OnomaAIResearch/Illustrious-XL-v1.1", "upstage/solar-pro-preview-instruct": "https://huggingface.co/upstage/solar-pro-preview-instruct", "NCSOFT/VARCO-VISION-14B": "https://huggingface.co/NCSOFT/VARCO-VISION-14B", "NCSOFT/Llama-VARCO-8B-Instruct": "https://huggingface.co/NCSOFT/Llama-VARCO-8B-Instruct", "NCSOFT/VARCO-VISION-14B-HF": "https://huggingface.co/NCSOFT/VARCO-VISION-14B-HF", "kakaocorp/kanana-nano-2.1b-base": "https://huggingface.co/kakaocorp/kanana-nano-2.1b-base", "kakaocorp/kanana-nano-2.1b-instruct": "https://huggingface.co/kakaocorp/kanana-nano-2.1b-instruct", "kakaobrain/kogpt": "https://huggingface.co/kakaobrain/kogpt", "nari-labs/Dia-1.6B": "https://huggingface.co/nari-labs/Dia-1.6B", "Bllossom/llama-3.2-Korean-Bllossom-3B": "https://huggingface.co/Bllossom/llama-3.2-Korean-Bllossom-3B", "MLP-KTLim/llama-3-Korean-Bllossom-8B": "https://huggingface.co/MLP-KTLim/llama-3-Korean-Bllossom-8B", "etri-lirs/eagle-3b-preview": "https://huggingface.co/etri-lirs/eagle-3b-preview", "etri-xainlp/llama3-8b-dpo_v1": "https://huggingface.co/etri-xainlp/llama3-8b-dpo_v1", "etri-xainlp/polyglot-ko-12.8b-instruct": "https://huggingface.co/etri-xainlp/polyglot-ko-12.8b-instruct", "LDCC/LDCC-SOLAR-10.7B": "https://huggingface.co/LDCC/LDCC-SOLAR-10.7B", "nlpai-lab/KULLM3": "https://huggingface.co/nlpai-lab/KULLM3", "nlpai-lab/kullm-polyglot-5.8b-v2": "https://huggingface.co/nlpai-lab/kullm-polyglot-5.8b-v2", "yanolja/EEVE-Korean-Instruct-10.8B-v1.0": "https://huggingface.co/yanolja/EEVE-Korean-Instruct-10.8B-v1.0", "yanolja/Bookworm-10.7B-v0.4-DPO": "https://huggingface.co/yanolja/Bookworm-10.7B-v0.4-DPO", "saltlux/Ko-Llama3-Luxia-8B": "https://huggingface.co/saltlux/Ko-Llama3-Luxia-8B", "maywell/Llama-3-Ko-8B-Instruct": "https://huggingface.co/maywell/Llama-3-Ko-8B-Instruct", "maywell/Synatra-10.7B-v0.4": "https://huggingface.co/maywell/Synatra-10.7B-v0.4", "beomi/Llama-3-Open-Ko-8B-Instruct-preview": "https://huggingface.co/beomi/Llama-3-Open-Ko-8B-Instruct-preview", "beomi/Yi-Ko-6B": "https://huggingface.co/beomi/Yi-Ko-6B", "kyujinpy/Korean-OpenOrca-v3": "https://huggingface.co/kyujinpy/Korean-OpenOrca-v3", "kyujinpy/KO-Platypus2-13B": "https://huggingface.co/kyujinpy/KO-Platypus2-13B", "dnotitia/DNA-R1": "https://huggingface.co/dnotitia/DNA-R1", "dnotitia/Llama-DNA-1.0-8B-Instruct": "https://huggingface.co/dnotitia/Llama-DNA-1.0-8B-Instruct", "Edentns/DataVortexS-10.7B-dpo-v1.0": "https://huggingface.co/Edentns/DataVortexS-10.7B-dpo-v1.0", "kaist-ai/prometheus-13b-v1.0": "https://huggingface.co/kaist-ai/prometheus-13b-v1.0", "KAERI-MLP/llama-3.1-Korean-AtomicGPT-Bllossom-8B": "https://huggingface.co/KAERI-MLP/llama-3.1-Korean-AtomicGPT-Bllossom-8B", "DILAB-HYU/koquality-polyglot-12.8b": "https://huggingface.co/DILAB-HYU/koquality-polyglot-12.8b", "EleutherAI/polyglot-ko-1.3b": "https://huggingface.co/EleutherAI/polyglot-ko-1.3b", } target_spaces = { "ginigen/Fashion-Fit360": "https://huggingface.co/spaces/ginigen/Fashion-Fit360", "aiqtech/Nano-Banana-API": "https://huggingface.co/spaces/aiqtech/Nano-Banana-API", "ginigen/Nano-Banana-Video": "https://huggingface.co/spaces/ginigen/Nano-Banana-Video", "openfree/News-AI": "https://huggingface.co/spaces/openfree/News-AI", "openfree/Creative-Arena-Leaderboard": "https://huggingface.co/spaces/openfree/Creative-Arena-Leaderboard", "Heartsync/Nano-Banana": "https://huggingface.co/spaces/Heartsync/Nano-Banana", "ginigen/webtoon-studio": "https://huggingface.co/spaces/ginigen/webtoon-studio", "VIDraft/gpt-oss-RAG": "https://huggingface.co/spaces/VIDraft/gpt-oss-RAG", "openfree/OpenAI-gpt-oss": "https://huggingface.co/spaces/openfree/OpenAI-gpt-oss", "openfree/AGI-NOVEL": "https://huggingface.co/spaces/openfree/AGI-NOVEL", "cutechicken/3D-Airforce-Simulator": "https://huggingface.co/spaces/cutechicken/3D-Airforce-Simulator", "ginipick/Private-AI": "https://huggingface.co/spaces/ginipick/Private-AI", "openfree/Best-AI": "https://huggingface.co/spaces/openfree/Best-AI", "aiqtech/Heatmap-Leaderboard": "https://huggingface.co/spaces/aiqtech/Heatmap-Leaderboard", "ginigen/Seedance-Free": "https://huggingface.co/spaces/ginigen/Seedance-Free", "openfree/K-AI": "https://huggingface.co/spaces/openfree/K-AI", "VIDraft/SOMA-AGI": "https://huggingface.co/spaces/VIDraft/SOMA-AGI", "openfree/AI": "https://huggingface.co/spaces/openfree/AI", "openfree/Chart-GPT": "https://huggingface.co/spaces/openfree/Chart-GPT", "fantaxy/fantasy-novel": "https://huggingface.co/spaces/fantaxy/fantasy-novel", "VIDraft/Gemma-3-R1984-1B": "https://huggingface.co/spaces/VIDraft/Gemma-3-R1984-1B", "ginigen/FLUX-Ghibli-LoRA2": "https://huggingface.co/spaces/ginigen/FLUX-Ghibli-LoRA2", "ginigen/Flux-VIDEO": "https://huggingface.co/spaces/ginigen/Flux-VIDEO", "aiqcamp/deepseek-r1-0528": "https://huggingface.co/spaces/aiqcamp/deepseek-r1-0528", "VIDraft/BAGEL-Websearch": "https://huggingface.co/spaces/VIDraft/BAGEL-Websearch", "ginigen/3D-LLAMA-V1": "https://huggingface.co/spaces/ginigen/3D-LLAMA-V1", "ginipick/Change-Hair": "https://huggingface.co/spaces/ginipick/Change-Hair", "VIDraft/Voice-Clone-Podcast": "https://huggingface.co/spaces/VIDraft/Voice-Clone-Podcast", "ginipick/PDF-EXAM": "https://huggingface.co/spaces/ginipick/PDF-EXAM", "openfree/Naming": "https://huggingface.co/spaces/openfree/Naming", "VIDraft/ACE-Singer": "https://huggingface.co/spaces/VIDraft/ACE-Singer", "openfree/Live-Podcast": "https://huggingface.co/spaces/openfree/Live-Podcast", "openfree/AI-Podcast": "https://huggingface.co/spaces/openfree/AI-Podcast", "ginipick/AI-BOOK": "https://huggingface.co/spaces/ginipick/AI-BOOK", "openfree/Web-Manager": "https://huggingface.co/spaces/openfree/Web-Manager", "openfree/Game-Gallery": "https://huggingface.co/spaces/openfree/Game-Gallery", "openfree/RPG-GAME": "https://huggingface.co/spaces/openfree/RPG-GAME", "openfree/Evolution-Simulation": "https://huggingface.co/spaces/openfree/Evolution-Simulation", "ginigen/3D-VIDEO": "https://huggingface.co/spaces/ginigen/3D-VIDEO", "ginipick/Pharmacy": "https://huggingface.co/spaces/ginipick/Pharmacy", "openfree/Battle-Royale-GAME": "https://huggingface.co/spaces/openfree/Battle-Royale-GAME", "openfree/repo-graph": "https://huggingface.co/spaces/openfree/repo-graph", "openfree/Chain-of-Recursive-Thoughts": "https://huggingface.co/spaces/openfree/Chain-of-Recursive-Thoughts", "ginigen/Mistral-Perflexity": "https://huggingface.co/spaces/ginigen/Mistral-Perflexity", "ginigen/Every-Text": "https://huggingface.co/spaces/ginigen/Every-Text", "openfree/svg": "https://huggingface.co/spaces/openfree/svg", "VIDraft/phi-4-reasoning-plus": "https://huggingface.co/spaces/VIDraft/phi-4-reasoning-plus", "ginigen/VisualCloze": "https://huggingface.co/spaces/ginigen/VisualCloze", "ginigen/framepack-i2v": "https://huggingface.co/spaces/ginigen/framepack-i2v", "fantos/Physics-Playground": "https://huggingface.co/spaces/fantos/Physics-Playground", "fantos/EveryText": "https://huggingface.co/spaces/fantos/EveryText", "ginipick/Qwen3-32B": "https://huggingface.co/spaces/ginipick/Qwen3-32B", "ginipick/Qwen3-235B-A22B": "https://huggingface.co/spaces/ginipick/Qwen3-235B-A22B", "keeperballon/vibe-coding-tetris": "https://huggingface.co/spaces/keeperballon/vibe-coding-tetris", "keeperballon/multi-llm": "https://huggingface.co/spaces/keeperballon/multi-llm", "VIDraft/Qwen3-8B": "https://huggingface.co/spaces/VIDraft/Qwen3-8B", "ginigen/interior-design": "https://huggingface.co/spaces/ginigen/interior-design", "ginigen/perflexity-clone": "https://huggingface.co/spaces/ginigen/perflexity-clone", "ginigen/blogger": "https://huggingface.co/spaces/ginigen/blogger", "openfree/Badge": "https://huggingface.co/spaces/openfree/Badge", "openfree/ZeroGPU-Leader": "https://huggingface.co/spaces/openfree/ZeroGPU-Leader", "cutechicken/World-of-Tank-GAME": "https://huggingface.co/spaces/cutechicken/World-of-Tank-GAME", "openfree/Llama-4-Maverick-17B-Research": "https://huggingface.co/spaces/openfree/Llama-4-Maverick-17B-Research", "fantaxy/Model-Leaderboard": "https://huggingface.co/spaces/fantaxy/Model-Leaderboard", "ginigen/FLUX-Open-Ghibli-Studio": "https://huggingface.co/spaces/ginigen/FLUX-Open-Ghibli-Studio", "openfree/Gemma-3-R1984-12B": "https://huggingface.co/spaces/openfree/Gemma-3-R1984-12B", "openfree/Stock-Trading-Analysis": "https://huggingface.co/spaces/openfree/Stock-Trading-Analysis", "aiqtech/Contributors-Leaderboard": "https://huggingface.co/spaces/aiqtech/Contributors-Leaderboard", "VIDraft/Gemma-3-R1984-27B": "https://huggingface.co/spaces/VIDraft/Gemma-3-R1984-27B", "openfree/Deepseek-v3-0324-Research": "https://huggingface.co/spaces/openfree/Deepseek-v3-0324-Research", "openfree/Korean-Exam-Leaderboard": "https://huggingface.co/spaces/openfree/Korean-Exam-Leaderboard", "openfree/Idea-Transformer": "https://huggingface.co/spaces/openfree/Idea-Transformer", "VIDraft/Unique3D": "https://huggingface.co/spaces/VIDraft/Unique3D", "openfree/Compare-RAG-CHAT": "https://huggingface.co/spaces/openfree/Compare-RAG-CHAT", "openfree/AgentX-Travel": "https://huggingface.co/spaces/openfree/AgentX-Travel", "openfree/SonicOrbit": "https://huggingface.co/spaces/openfree/SonicOrbit", "VIDraft/Space-Leaderboard": "https://huggingface.co/spaces/VIDraft/Space-Leaderboard", "ginipick/3D-GAME": "https://huggingface.co/spaces/ginipick/3D-GAME", "ginigen/Graph-Mind": "https://huggingface.co/spaces/ginigen/Graph-Mind", "openfree/deepseek_r1_API": "https://huggingface.co/spaces/openfree/deepseek_r1_API", "openfree/Mouse2-HF": "https://huggingface.co/spaces/openfree/Mouse2-HF", "ginipick/open_Deep-Research": "https://huggingface.co/spaces/ginipick/open_Deep-Research", "ginigen/LLaDA": "https://huggingface.co/spaces/ginigen/LLaDA", "VIDraft/PHI4-Multimodal": "https://huggingface.co/spaces/VIDraft/PHI4-Multimodal", "openfree/Datasets-Convertor": "https://huggingface.co/spaces/openfree/Datasets-Convertor", "ginigen/Ovis2-8B": "https://huggingface.co/spaces/ginigen/Ovis2-8B", "ginigen/FLUX-Eternity": "https://huggingface.co/spaces/ginigen/FLUX-Eternity", "ginigen/OmniParser-v2-pro": "https://huggingface.co/spaces/ginigen/OmniParser-v2-pro", "ginigen/panorama-images": "https://huggingface.co/spaces/ginigen/panorama-images", "ginigen/Celebrity": "https://huggingface.co/spaces/ginigen/Celebrity", "ginigen/Fashion-Pose-Control": "https://huggingface.co/spaces/ginigen/Fashion-Pose-Control", "ginigen/VoiceClone-TTS": "https://huggingface.co/spaces/ginigen/VoiceClone-TTS", "openfree/Article-Generator": "https://huggingface.co/spaces/openfree/Article-Generator", "openfree/chess": "https://huggingface.co/spaces/openfree/chess", "fantos/Panorama": "https://huggingface.co/spaces/fantos/Panorama", "ginigen/Multi-LoRAgen": "https://huggingface.co/spaces/ginigen/Multi-LoRAgen", "ginigen/canvas-studio": "https://huggingface.co/spaces/ginigen/canvas-studio", "fantos/Magic-Drawings": "https://huggingface.co/spaces/fantos/Magic-Drawings", "ginigen/Lumina-Image-PLUS": "https://huggingface.co/spaces/ginigen/Lumina-Image-PLUS", "VIDraft/mouse-webgen": "https://huggingface.co/spaces/VIDraft/mouse-webgen", "immunobiotech/MUSIC-Jukebox": "https://huggingface.co/spaces/immunobiotech/MUSIC-Jukebox", "kolaslab/Binaural-Beat-Generator": "https://huggingface.co/spaces/kolaslab/Binaural-Beat-Generator", "ginigen/Flux-LayerDiffuse": "https://huggingface.co/spaces/ginigen/Flux-LayerDiffuse", "VIDraft/Portrait-Animation": "https://huggingface.co/spaces/VIDraft/Portrait-Animation", "ginigen/text3d-r1": "https://huggingface.co/spaces/ginigen/text3d-r1", "immunobiotech/drug-discovery": "https://huggingface.co/spaces/immunobiotech/drug-discovery", "openfree/VisionOCR-Chat": "https://huggingface.co/spaces/openfree/VisionOCR-Chat", "immunobiotech/MICHELIN": "https://huggingface.co/spaces/immunobiotech/MICHELIN", "ginipick/PharmAI-Korea": "https://huggingface.co/spaces/ginipick/PharmAI-Korea", "ginigen/MagicFace-V3": "https://huggingface.co/spaces/ginigen/MagicFace-V3", "aiqcamp/MindMap": "https://huggingface.co/spaces/aiqcamp/MindMap", "ginigen/3D-LLAMA": "https://huggingface.co/spaces/ginigen/3D-LLAMA", "openfree/VectorFlow": "https://huggingface.co/spaces/openfree/VectorFlow", "openfree/webtoon-gen": "https://huggingface.co/spaces/openfree/webtoon-gen", "VIDraft/topic-prediction": "https://huggingface.co/spaces/VIDraft/topic-prediction", "openfree/MoneyRadar2": "https://huggingface.co/spaces/openfree/MoneyRadar2", "openfree/trending-board-2025": "https://huggingface.co/spaces/openfree/trending-board-2025", "VIDraft/PapersImpact": "https://huggingface.co/spaces/VIDraft/PapersImpact", "VIDraft/EveryRAG": "https://huggingface.co/spaces/VIDraft/EveryRAG", "ginipick/Any3D": "https://huggingface.co/spaces/ginipick/Any3D", "ginigen/Canvas-pro": "https://huggingface.co/spaces/ginigen/Canvas-pro", "openfree/image-to-vector": "https://huggingface.co/spaces/openfree/image-to-vector", "ginipick/QR-Canvas-plus": "https://huggingface.co/spaces/ginipick/QR-Canvas-plus", "openfree/Korean-Leaderboard-2025": "https://huggingface.co/spaces/openfree/Korean-Leaderboard-2025", "ginipick/DeepSeekR1-LIVE": "https://huggingface.co/spaces/ginipick/DeepSeekR1-LIVE", "ginigen/ColPali-multi": "https://huggingface.co/spaces/ginigen/ColPali-multi", "ginigen/Janus-Pro-7B": "https://huggingface.co/spaces/ginigen/Janus-Pro-7B", "ginigen/Animagine": "https://huggingface.co/spaces/ginigen/Animagine", "ginipick/OpenSUNO": "https://huggingface.co/spaces/ginipick/OpenSUNO", "openfree/PDF-RAG": "https://huggingface.co/spaces/openfree/PDF-RAG", "fantos/Ranking-Tracker": "https://huggingface.co/spaces/fantos/Ranking-Tracker", "aiqcamp/Multilingual-Images": "https://huggingface.co/spaces/aiqcamp/Multilingual-Images", "aiqcamp/Gemini2-Flash-Thinking": "https://huggingface.co/spaces/aiqcamp/Gemini2-Flash-Thinking", "kolaslab/8bit-gamemusic": "https://huggingface.co/spaces/kolaslab/8bit-gamemusic", "openfree/pepe": "https://huggingface.co/spaces/openfree/pepe", "openfree/MoneyRadar": "https://huggingface.co/spaces/openfree/MoneyRadar", "ginipick/QR-Canvas": "https://huggingface.co/spaces/ginipick/QR-Canvas", "openfree/MagicFace": "https://huggingface.co/spaces/openfree/MagicFace", "openfree/pick-spaces": "https://huggingface.co/spaces/openfree/pick-spaces", "aiqcamp/diagram": "https://huggingface.co/spaces/aiqcamp/diagram", "openfree/korea-president-yoon": "https://huggingface.co/spaces/openfree/korea-president-yoon", "VIDraft/PaperImpact": "https://huggingface.co/spaces/VIDraft/PaperImpact", "openfree/CryptoVision": "https://huggingface.co/spaces/openfree/CryptoVision", "gunship999/Gunship-3D-FPS": "https://huggingface.co/spaces/gunship999/Gunship-3D-FPS", "fantos/VoiceClone": "https://huggingface.co/spaces/fantos/VoiceClone", "VIDraft/ChemGenesis": "https://huggingface.co/spaces/VIDraft/ChemGenesis", "openfree/webtoon": "https://huggingface.co/spaces/openfree/webtoon", "kolaslab/Quantum": "https://huggingface.co/spaces/kolaslab/Quantum", "openfree/ProteinGenesis": "https://huggingface.co/spaces/openfree/ProteinGenesis", "openfree/2025saju": "https://huggingface.co/spaces/openfree/2025saju", "kolaslab/VisionART": "https://huggingface.co/spaces/kolaslab/VisionART", "ginigen/CANVAS-o3": "https://huggingface.co/spaces/ginigen/CANVAS-o3", "kolaslab/world-sdr": "https://huggingface.co/spaces/kolaslab/world-sdr", "openfree/ultpixgen": "https://huggingface.co/spaces/openfree/ultpixgen", "ginigen/theater": "https://huggingface.co/spaces/ginigen/theater", "VIDraft/stock": "https://huggingface.co/spaces/VIDraft/stock", "ginipick/FLUX-Prompt-Generator": "https://huggingface.co/spaces/ginipick/FLUX-Prompt-Generator", "ginigen/Dokdo": "https://huggingface.co/spaces/ginigen/Dokdo", "aiqcamp/imagemagic": "https://huggingface.co/spaces/aiqcamp/imagemagic", "openfree/ColorRevive": "https://huggingface.co/spaces/openfree/ColorRevive", "VIDraft/RAGOndevice": "https://huggingface.co/spaces/VIDraft/RAGOndevice", "ginigen/FLUXllama-Multilingual": "https://huggingface.co/spaces/ginigen/FLUXllama-Multilingual", "aiqcamp/Fashion-FLUX": "https://huggingface.co/spaces/aiqcamp/Fashion-FLUX", "ginipick/StyleGen": "https://huggingface.co/spaces/ginipick/StyleGen", "openfree/StoryStar": "https://huggingface.co/spaces/openfree/StoryStar", "openfree/Korean-Leaderboard": "https://huggingface.co/spaces/openfree/Korean-Leaderboard", "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", "ginigen/Canvas": "https://huggingface.co/spaces/ginigen/Canvas", "ginipick/time-machine": "https://huggingface.co/spaces/ginipick/time-machine", "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", "openfree/GiniGEN": "https://huggingface.co/spaces/openfree/GiniGEN", "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", "kolaslab/shooting": "https://huggingface.co/spaces/kolaslab/shooting", "VIDraft/Mouse-Hackathon": "https://huggingface.co/spaces/VIDraft/Mouse-Hackathon", "cutechicken/TankWar3D": "https://huggingface.co/spaces/cutechicken/TankWar3D", "kolaslab/RC4-EnDecoder": "https://huggingface.co/spaces/kolaslab/RC4-EnDecoder", "kolaslab/simulator": "https://huggingface.co/spaces/kolaslab/simulator", "kolaslab/calculator": "https://huggingface.co/spaces/kolaslab/calculator", # 기업 관련 스페이스 "nari-labs/Dia-1.6B": "https://huggingface.co/spaces/nari-labs/Dia-1.6B", "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", "LeeSangHoon/HierSpeech_TTS": "https://huggingface.co/spaces/LeeSangHoon/HierSpeech_TTS", "etri-vilab/Ko-LLaVA": "https://huggingface.co/spaces/etri-vilab/Ko-LLaVA", "etri-vilab/KOALA": "https://huggingface.co/spaces/etri-vilab/KOALA", "naver-clova-ix/donut-base-finetuned-cord-v2": "https://huggingface.co/spaces/naver-clova-ix/donut-base-finetuned-cord-v2", "NCSOFT/VARCO_Arena": "https://huggingface.co/spaces/NCSOFT/VARCO_Arena", } def get_korea_models(): """Korea 관련 모델 검색""" params = {"search": "korea", "full": "True", "config": "True", "limit": 1000} try: response = requests.get("https://huggingface.co/api/models", headers={'Accept': 'application/json'}, params=params) if response.status_code == 200: return response.json() return [] except Exception as e: print(f"Error fetching Korea models: {str(e)}") return [] def get_all_models(limit=3000): """모든 모델과 Korea 관련 모델 가져오기""" all_models = [] page_size = 1000 for offset in range(0, limit, page_size): params = {'limit': min(page_size, limit - offset), 'full': 'True', 'config': 'True', 'offset': offset} response = requests.get("https://huggingface.co/api/models", headers={'Accept': 'application/json'}, params=params) if response.status_code == 200: all_models.extend(response.json()) else: break korea_response = requests.get("https://huggingface.co/api/models", headers={'Accept': 'application/json'}, params={"search": "korea", "full": "True", "config": "True", "limit": limit}) if korea_response.status_code == 200: korea_models = korea_response.json() existing_ids = {model.get('id', '') for model in all_models} for model in korea_models: if model.get('id', '') not in existing_ids: all_models.append(model) return all_models[:limit] async def fetch_model_data(session, model_id): url = f"https://huggingface.co/api/models/{model_id.strip('/')}" try: async with session.get(url, headers={'Accept': 'application/json'}) as response: if response.status == 200: return await response.json() return None except: return None async def fetch_all_target_models(model_ids): async with aiohttp.ClientSession() as session: tasks = [fetch_model_data(session, model_id) for model_id in model_ids] return await asyncio.gather(*tasks) def create_error_plot(): fig = go.Figure() fig.add_annotation(text="데이터를 불러올 수 없습니다", 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, paper_bgcolor='#e0e5ec', plot_bgcolor='#e0e5ec') return fig def get_models_data(progress=gr.Progress()): def calculate_rank(model_id, all_global_models, korea_models): global_rank = next((idx for idx, m in enumerate(all_global_models, 1) if m.get('id', '').strip() == model_id.strip()), None) is_korea = any(m.get('id', '').strip() == model_id.strip() for m in korea_models) if is_korea: korea_rank = next((idx for idx, m in enumerate(korea_models, 1) if m.get('id', '').strip() == model_id.strip()), None) if korea_rank: return min(global_rank or 3001, korea_rank + 1000), True return global_rank if global_rank else 'Not in top 3000', is_korea try: progress(0, desc="Fetching models...") all_global_models = get_all_models(limit=3000) korea_models = get_korea_models() fig = go.Figure() target_model_ids = set(target_models.keys()) extra_model_ids = set() for m in all_global_models: model_id = m.get('id', '') if isinstance(model_id, str): for org in KOREAN_ORGS: if model_id.lower().startswith(org.lower() + "/"): extra_model_ids.add(model_id) break final_model_ids = target_model_ids.union(extra_model_ids) model_results = asyncio.run(fetch_all_target_models(final_model_ids)) filtered_models = [] for model_id, model_data in zip(final_model_ids, model_results): if model_data is not None: rank, is_korea = calculate_rank(model_id, all_global_models, korea_models) filtered_models.append({ 'id': model_id, 'global_rank': rank, 'downloads': model_data.get('downloads', 0), 'likes': model_data.get('likes', 0), 'title': model_data.get('title', 'No Title'), 'is_korea': is_korea }) else: filtered_models.append({ 'id': model_id, 'global_rank': 'Not in top 3000', 'downloads': 0, 'likes': 0, 'title': 'No Title', 'is_korea': False }) filtered_models.sort(key=lambda x: x['global_rank'] if isinstance(x['global_rank'], (int, float)) else float('inf')) valid_models = [m for m in filtered_models if isinstance(m['global_rank'], (int, float))] if valid_models: fig.add_trace(go.Bar( x=[m['id'] for m in valid_models], y=[3001 - m['global_rank'] for m in valid_models], text=[f"Rank: #{m['global_rank']}
Downloads: {format(m['downloads'], ',')}
Likes: {format(m['likes'], ',')}" for m in valid_models], textposition='auto', marker_color=['rgba(255,107,107,0.8)' if m['is_korea'] else 'rgba(78,205,196,0.8)' for m in valid_models] )) fig.update_layout( title={'text': "🏆 HuggingFace Models Global Rankings", 'font': {'size': 24, 'color': '#5a6677'}}, xaxis_title="Model ID", yaxis_title="Global Rank", yaxis=dict(ticktext=[f"#{i}" for i in range(1, 3001, 100)], tickvals=[3001 - i for i in range(1, 3001, 100)], range=[0, 3000]), height=800, showlegend=False, template='plotly_white', xaxis_tickangle=-45, paper_bgcolor='rgba(224,229,236,0.5)', plot_bgcolor='rgba(224,229,236,0.3)' ) html_content = f"""

🤖 Models Rankings (Up to #3000)

""" for model in filtered_models: rank_display = f"Global Rank #{model['global_rank']}" if isinstance(model['global_rank'], (int, float)) else "Not in top 3000" korea_badge = "🇰🇷 Korea" if model['is_korea'] else "" model_url = target_models.get(model['id'], f"https://huggingface.co/{model['id']}") html_content += f"""

{rank_display}

{model['id']}

{korea_badge}

⬇️ {format(model['downloads'], ',')} | 👍 {format(model['likes'], ',')}

Visit 🔗
""" html_content += "
" df = pd.DataFrame([{ 'Global Rank': f"#{m['global_rank']}" if isinstance(m['global_rank'], (int, float)) else m['global_rank'], 'Model ID': m['id'], 'Title': m['title'], 'Downloads': format(m['downloads'], ','), 'Likes': format(m['likes'], ','), 'Korea': '🇰🇷' if m['is_korea'] else '', 'URL': target_models.get(m['id'], f"https://huggingface.co/{m['id']}") } for m in filtered_models]) progress(1.0, desc="Complete!") return fig, html_content, df except Exception as e: return create_error_plot(), f"

Error: {str(e)}

", pd.DataFrame() def get_spaces_data(sort_type="trending", progress=gr.Progress()): """스페이스 데이터 가져오기""" url = "https://huggingface.co/api/spaces" params = {'full': 'true', 'limit': 1000} if sort_type == "modes": params['sort'] = 'likes' 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 = {} for idx, space in enumerate(all_spaces, 1): space_id = space.get('id', '') if space_id in target_spaces or any(space_id.lower().startswith(org.lower() + "/") for org in KOREAN_ORGS): space['rank'] = idx space_ranks[space_id] = space spaces = sorted([space_ranks[sid] for sid in space_ranks], key=lambda x: x['rank']) progress(0.3, desc="Creating visualization...") fig = go.Figure() if spaces: fig.add_trace(go.Bar( x=[s['id'] for s in spaces], y=[s['rank'] for s in spaces], text=[f"Rank: {s['rank']}
Likes: {s.get('likes', 0)}" for s in spaces], textposition='auto', marker_color='rgba(158,202,225,0.8)' )) fig.update_layout( title={'text': f'🚀 HuggingFace Spaces {sort_type.title()} Rankings (Top 500)', 'font': {'size': 24, 'color': '#5a6677'}}, xaxis_title='Space ID', yaxis_title='Rank', yaxis=dict(autorange='reversed', tickmode='array', ticktext=[str(i) for i in range(1, 501, 20)], tickvals=[i for i in range(1, 501, 20)], range=[1, 500]), height=800, showlegend=False, template='plotly_white', xaxis_tickangle=-45, paper_bgcolor='rgba(224,229,236,0.5)', plot_bgcolor='rgba(224,229,236,0.3)' ) progress(0.6, desc="Creating space cards...") html_content = f"""

🚀 {sort_type.title()} Rankings

""" for space in spaces: space_id = space['id'] title = space.get('cardData', {}).get('title') or space.get('title', 'No Title') likes = space.get('likes', 0) space_url = target_spaces.get(space_id, f"https://huggingface.co/spaces/{space_id}") html_content += f"""

Rank #{space['rank']} - {space_id}

{title}

👍 Likes: {likes}

Visit Space 🔗
""" html_content += "
" df = pd.DataFrame([{ 'Rank': s['rank'], 'Space ID': s['id'], 'Title': s.get('cardData', {}).get('title') or s.get('title', 'No Title'), 'Likes': s.get('likes', 0), 'URL': target_spaces.get(s['id'], f"https://huggingface.co/spaces/{s['id']}") } for s in spaces]) progress(1.0, desc="Complete!") return fig, html_content, df except Exception as e: return create_error_plot(), f'
Error: {str(e)}
', pd.DataFrame() def create_registration_bar_chart(data, type_name="Spaces"): try: top_limit = 500 if type_name == "Spaces" else 3000 if isinstance(data, pd.DataFrame): if type_name == "Models": data = data[data['Global Rank'].apply(lambda x: isinstance(x, str) and x.startswith('#'))] data = data[data['Global Rank'].apply(lambda x: int(str(x).replace('#', '')) <= top_limit)] else: data = data[data['Rank'].apply(lambda x: isinstance(x, (int, float)) and x <= top_limit)] id_col = 'Space ID' if type_name == "Spaces" else 'Model ID' registrations = data[id_col].apply(lambda x: x.split('/')[0]).value_counts() else: registrations = pd.Series({}) registrations = registrations.sort_values(ascending=False) fig = go.Figure(data=[go.Bar( x=registrations.index, y=registrations.values, text=registrations.values, textposition='auto', marker_color='#FF6B6B' )]) fig.update_layout( title=f"Korean {type_name} by Creator (Top {top_limit})", xaxis_title="Creator ID", yaxis_title="Count", showlegend=False, height=400, width=700, paper_bgcolor='#e0e5ec', plot_bgcolor='rgba(224,229,236,0.3)' ) return fig except: return go.Figure() def create_pie_chart(data, total_count, type_name="Spaces"): try: top_limit = 500 if type_name == "Spaces" else 3000 if isinstance(data, pd.DataFrame): if type_name == "Models": korean_count = len(data[data['Global Rank'].apply(lambda x: isinstance(x, str) and x.startswith('#') and int(x.replace('#', '')) <= top_limit)]) else: korean_count = len(data[data['Rank'].apply(lambda x: isinstance(x, (int, float)) and x <= top_limit)]) else: korean_count = 0 other_count = total_count - korean_count fig = go.Figure(data=[go.Pie( labels=[f'Korean {type_name}', f'Other {type_name}'], values=[korean_count, other_count], hole=.3, marker_colors=['#FF6B6B', '#4ECDC4'], textinfo='percent+value' )]) fig.update_layout( title=f"Korean vs Other {type_name} (Top {top_limit})", showlegend=True, height=400, width=500, paper_bgcolor='#e0e5ec' ) return fig except: return go.Figure() def refresh_all_data(): try: spaces_results = get_spaces_data("trending") models_results = get_models_data() spaces_pie = create_pie_chart(spaces_results[2], 500, "Spaces") spaces_bar = create_registration_bar_chart(spaces_results[2], "Spaces") models_pie = create_pie_chart(models_results[2], 3000, "Models") models_bar = create_registration_bar_chart(models_results[2], "Models") return [spaces_results[0], spaces_results[1], spaces_results[2], spaces_pie, spaces_bar, models_results[0], models_results[1], models_results[2], models_pie, models_bar] except Exception as e: print(f"Error: {str(e)}") return [None] * 10 # Gradio 앱 정의 with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Soft()) as demo: gr.Markdown(""" # 🤗 허깅페이스 '한국(언어) 리더보드' HuggingFace가 제공하는 Spaces와 Models 실시간 인기 순위 반영하여 '한국인(기업/언어)'의 리스트(공개,검색,리더보드 등)만 분석. (c)'한국인공지능진흥협회' / 요청: arxivgpt@gmail.com """) gr.Markdown(""" ### [Hot NEWS] 허깅페이스 선정 12월 'TOP 12'에 한국 'ginipick'의 'FLUXllama'와 'Text3D' 2종이 선정됨 """) refresh_btn = gr.Button("🔄 새로 고침", variant="primary", elem_classes=["neu-button"]) with gr.Tab("Spaces Trending"): trending_plot = gr.Plot() with gr.Row(): with gr.Column(scale=1): spaces_pie_chart = gr.Plot(label="Korean Spaces Distribution", elem_id="spaces_pie") with gr.Column(scale=2): spaces_bar_chart = gr.Plot(label="Registrations by Creator", elem_id="spaces_bar") trending_info = gr.HTML() trending_df = gr.DataFrame( headers=["Rank", "Space ID", "Title", "Likes", "URL"], datatype=["number", "str", "str", "number", "str"], row_count=(10, "dynamic") ) with gr.Tab("Models Trending"): models_plot = gr.Plot() with gr.Row(): with gr.Column(scale=1): models_pie_chart = gr.Plot(label="Korean Models Distribution", elem_id="models_pie") with gr.Column(scale=2): models_bar_chart = gr.Plot(label="Registrations by Creator", elem_id="models_bar") models_info = gr.HTML() models_df = gr.DataFrame( headers=["Global Rank", "Model ID", "Title", "Downloads", "Likes", "Korea", "URL"], datatype=["str", "str", "str", "str", "str", "str", "str"], row_count=(10, "dynamic") ) refresh_btn.click( fn=refresh_all_data, outputs=[ trending_plot, trending_info, trending_df, spaces_pie_chart, spaces_bar_chart, models_plot, models_info, models_df, models_pie_chart, models_bar_chart ] ) # 초기 데이터 로드 try: initial_data = refresh_all_data() if initial_data[0]: trending_plot.value = initial_data[0] if initial_data[1]: trending_info.value = initial_data[1] if initial_data[2] is not None: trending_df.value = initial_data[2] if initial_data[3]: spaces_pie_chart.value = initial_data[3] if initial_data[4]: spaces_bar_chart.value = initial_data[4] if initial_data[5]: models_plot.value = initial_data[5] if initial_data[6]: models_info.value = initial_data[6] if initial_data[7] is not None: models_df.value = initial_data[7] if initial_data[8]: models_pie_chart.value = initial_data[8] if initial_data[9]: models_bar_chart.value = initial_data[9] except Exception as e: print(f"Error loading initial data: {str(e)}") demo.launch(server_name="0.0.0.0", server_port=7860, share=False, show_error=True)