| |
|
|
| const HF_MODELS = [ |
| { id: "meta-llama/Meta-Llama-3.1-8B-Instruct", name: "Llama 3.1 8B Instruct", org: "meta-llama", type: "llm", tags: ["chat", "instruction", "tool-calling"], vram: 16, downloads: 1200000, likes: 8500, featured: true, description: "Latest Llama 3.1 with 128K context, multilingual, tool calling. Best open LLM for general use." }, |
| { id: "mistralai/Mistral-7B-Instruct-v0.3", name: "Mistral 7B Instruct v0.3", org: "mistralai", type: "llm", tags: ["chat", "instruction", "fast"], vram: 8, downloads: 2100000, likes: 12000, featured: true, description: "Fast, efficient 7B model. Excellent for chat, coding, and reasoning. Low VRAM requirement." }, |
| { id: "Qwen/Qwen2.5-7B-Instruct", name: "Qwen 2.5 7B Instruct", org: "Qwen", type: "llm", tags: ["chat", "multilingual", "coding", "reasoning"], vram: 8, downloads: 900000, likes: 6200, featured: true, description: "Strong multilingual (29 langs), coding, and reasoning. 128K context. Apache 2.0." }, |
| { id: "microsoft/Phi-3.5-mini-instruct", name: "Phi-3.5 Mini Instruct", org: "microsoft", type: "llm", tags: ["small", "fast", "reasoning", "128k"], vram: 4, downloads: 600000, likes: 4800, featured: true, description: "3.8B params, 128K context. Remarkable reasoning for size. Runs on 4GB VRAM." }, |
| { id: "codellama/CodeLlama-13b-Instruct-hf", name: "CodeLlama 13B Instruct", org: "codellama", type: "code", tags: ["coding", "python", "completion", "infilling"], vram: 24, downloads: 400000, likes: 3200, featured: true, description: "Specialized for code generation, completion, infilling. Python, JS, TS, C++, Rust, Go." }, |
| { id: "deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct", name: "DeepSeek Coder V2 Lite", org: "deepseek-ai", type: "code", tags: ["coding", "reasoning", "128k", "math"], vram: 16, downloads: 300000, likes: 2800, featured: false, description: "16B MoE (2.4B active). Top-tier coding + math reasoning. 128K context." }, |
| { id: "openai/whisper-large-v3", name: "Whisper Large v3", org: "openai", type: "audio", tags: ["asr", "transcription", "multilingual", "translation"], vram: 8, downloads: 1500000, likes: 9500, featured: true, description: "State-of-the-art speech recognition. 99+ languages. Translation to English." }, |
| { id: "openai/whisper-large-v3-turbo", name: "Whisper Large v3 Turbo", org: "openai", type: "audio", tags: ["asr", "fast", "transcription"], vram: 6, downloads: 800000, likes: 5200, featured: false, description: "8x faster than large-v3 with minimal quality loss. Best for real-time." }, |
| { id: "suno/bark", name: "Bark TTS", org: "suno", type: "audio", tags: ["tts", "voice", "multilingual", "music"], vram: 12, downloads: 200000, likes: 3500, featured: false, description: "Generative audio model. Text-to-speech, music, sound effects. Multiple speakers." }, |
| { id: "coqui-ai/TTS", name: "Coqui TTS (XTTS v2)", org: "coqui-ai", type: "audio", tags: ["tts", "voice-cloning", "multilingual"], vram: 6, downloads: 150000, likes: 2800, featured: false, description: "Zero-shot voice cloning in 17 languages. 6s reference audio needed." }, |
| { id: "google/siglip-so400m-patch14-384", name: "SigLIP SO400M", org: "google", type: "vision", tags: ["clip", "embeddings", "zero-shot", "classification"], vram: 4, downloads: 100000, likes: 1200, featured: false, description: "Sigmoid loss CLIP. Better zero-shot classification. 384x384 resolution." }, |
| { id: "openai/clip-vit-large-patch14", name: "CLIP ViT-L/14", org: "openai", type: "vision", tags: ["clip", "embeddings", "retrieval", "classification"], vram: 4, downloads: 500000, likes: 4500, featured: false, description: "Classic CLIP. Image-text embeddings for search, classification, retrieval." }, |
| { id: "BAAI/bge-large-en-v1.5", name: "BGE Large EN v1.5", org: "BAAI", type: "embed", tags: ["embeddings", "retrieval", "rag", "english"], vram: 2, downloads: 800000, likes: 5800, featured: true, description: "Top MTEB retrieval model. 1024-dim. Best for English RAG." }, |
| { id: "intfloat/multilingual-e5-large", name: "Multilingual E5 Large", org: "intfloat", type: "embed", tags: ["embeddings", "multilingual", "retrieval", "100-langs"], vram: 2, downloads: 400000, likes: 3200, featured: false, description: "100 languages. Strong cross-lingual retrieval. 1024-dim." }, |
| { id: "microsoft/Phi-3-vision-128k-instruct", name: "Phi-3 Vision 128K", org: "microsoft", type: "vision", tags: ["vlm", "ocr", "charts", "documents", "128k"], vram: 8, downloads: 150000, likes: 2100, featured: false, description: "4.2B VLM. OCR, chart reading, document understanding. 128K context." }, |
| { id: "llava-hf/llava-v1.6-mistral-7b-hf", name: "LLaVA 1.6 Mistral 7B", org: "llava-hf", type: "vision", tags: ["vlm", "chat", "reasoning", "images"], vram: 16, downloads: 200000, likes: 2500, featured: false, description: "Visual chat assistant. Strong reasoning on images. Mistral 7B backbone." }, |
| { id: "Salesforce/blip2-opt-2.7b", name: "BLIP-2 OPT 2.7B", org: "Salesforce", type: "vision", tags: ["captioning", "vqa", "lightweight"], vram: 6, downloads: 100000, likes: 1800, featured: false, description: "Lightweight image captioning and VQA. Good for edge deployment." }, |
| { id: "google/gemma-2-9b-it", name: "Gemma 2 9B Instruct", org: "google", type: "llm", tags: ["chat", "instruction", "safety", "multilingual"], vram: 12, downloads: 400000, likes: 3800, featured: false, description: "Google's open model. Strong safety alignment. 8K context." }, |
| { id: "allenai/OLMo-7B-Instruct", name: "OLMo 7B Instruct", org: "allenai", type: "llm", tags: ["open", "transparent", "chat", "research"], vram: 8, downloads: 50000, likes: 800, featured: false, description: "Fully open (data, code, weights). Truly transparent LLM for research." }, |
| { id: "NVIDIA/Nemotron-3-8B-Instruct-4k", name: "Nemotron-3 8B Instruct", org: "NVIDIA", type: "llm", tags: ["chat", "reasoning", "alignment", "helpful"], vram: 16, downloads: 80000, likes: 1200, featured: false, description: "NVIDIA's aligned model. Strong helpfulness and reasoning. 4K context." }, |
| { id: "HuggingFaceH4/zephyr-7b-beta", name: "Zephyr 7B Beta", org: "HuggingFaceH4", type: "llm", tags: ["chat", "dpo", "alignment", "helpful"], vram: 8, downloads: 600000, likes: 4200, featured: false, description: "DPO-aligned Mistral. Very helpful assistant. No system prompt needed." }, |
| ]; |
|
|
| const GPU_OPTIONS = [ |
| { id: "rtx-3080", name: "RTX 3080", vram: "10 GB", price: 0.17, spot: 0.085, featured: false, minVram: 0, maxVram: 10 }, |
| { id: "rtx-3090", name: "RTX 3090", vram: "24 GB", price: 0.22, spot: 0.11, featured: true, minVram: 0, maxVram: 24 }, |
| { id: "rtx-4090", name: "RTX 4090", vram: "24 GB", price: 0.44, spot: 0.22, featured: false, minVram: 0, maxVram: 24 }, |
| { id: "a10g", name: "A10G", vram: "24 GB", price: 0.55, spot: 0.275, featured: false, minVram: 0, maxVram: 24 }, |
| { id: "a100-40", name: "A100 40GB", vram: "40 GB", price: 1.10, spot: 0.55, featured: false, minVram: 24, maxVram: 40 }, |
| { id: "a100-80", name: "A100 80GB", vram: "80 GB", price: 2.20, spot: 1.10, featured: false, minVram: 40, maxVram: 80 }, |
| { id: "h100", name: "H100 80GB", vram: "80 GB", price: 4.50, spot: 2.25, featured: false, minVram: 40, maxVram: 999 }, |
| ]; |
|
|
| let selectedModel = null; |
| let selectedGpu = null; |
| let currentFilter = 'all'; |
| let searchQuery = ''; |
|
|
| function formatNumber(n) { |
| if (n >= 1000000) return (n/1000000).toFixed(1) + 'M'; |
| if (n >= 1000) return (n/1000).toFixed(1) + 'K'; |
| return n.toString(); |
| } |
|
|
| function getTypeIcon(type) { |
| const icons = { llm: '🤖', code: '💻', audio: '🔊', vision: '👁️', embed: '🔍' }; |
| return icons[type] || '📦'; |
| } |
|
|
| function getTypeLabel(type) { |
| const labels = { llm: 'LLM', code: 'Code', audio: 'Audio', vision: 'Vision', embed: 'Embeddings' }; |
| return labels[type] || type; |
| } |
|
|
| function renderStats() { |
| const stats = [ |
| { num: HF_MODELS.length, label: 'Models Indexed' }, |
| { num: HF_MODELS.filter(m => m.featured).length, label: 'Featured' }, |
| { num: GPU_OPTIONS.length, label: 'GPU Types' }, |
| { num: HF_MODELS.reduce((a,b) => a + b.downloads, 0), label: 'Total Downloads' }, |
| ]; |
| document.getElementById('stats-bar').innerHTML = stats.map(s => ` |
| <div class="stat-card"> |
| <div class="stat-number">${typeof s.num === 'number' && s.num > 10000 ? formatNumber(s.num) : s.num}</div> |
| <div class="stat-label">${s.label}</div> |
| </div> |
| `).join(''); |
| } |
|
|
| function renderFeatured() { |
| const featured = HF_MODELS.filter(m => m.featured); |
| document.getElementById('featured-grid').innerHTML = featured.map(m => createModelCard(m)).join(''); |
| } |
|
|
| function createFilterTabs() { |
| const types = ['all', 'llm', 'code', 'audio', 'vision', 'embed']; |
| const labels = { all: 'All', llm: 'LLM/Chat', code: 'Code', audio: 'Audio', vision: 'Vision', embed: 'Embeddings' }; |
| document.getElementById('filter-tabs').innerHTML = types.map(t => ` |
| <button class="filter-tab ${t === currentFilter ? 'active' : ''}" data-filter="${t}">${labels[t]}</button> |
| `).join(''); |
| document.querySelectorAll('.filter-tab').forEach(btn => { |
| btn.addEventListener('click', () => { |
| currentFilter = btn.dataset.filter; |
| document.querySelectorAll('.filter-tab').forEach(b => b.classList.toggle('active', b.dataset.filter === currentFilter)); |
| renderModels(); |
| }); |
| }); |
| } |
|
|
| function renderModels() { |
| let models = HF_MODELS; |
| if (currentFilter !== 'all') models = models.filter(m => m.type === currentFilter); |
| if (searchQuery) { |
| const q = searchQuery.toLowerCase(); |
| models = models.filter(m => |
| m.name.toLowerCase().includes(q) || |
| m.id.toLowerCase().includes(q) || |
| m.org.toLowerCase().includes(q) || |
| m.tags.some(t => t.toLowerCase().includes(q)) |
| ); |
| } |
| document.getElementById('models-grid').innerHTML = models.map(m => createModelCard(m)).join(''); |
| document.querySelectorAll('.model-card').forEach(card => { |
| card.addEventListener('click', (e) => { |
| if (!e.target.closest('.deploy-btn')) { |
| const modelId = card.dataset.modelId; |
| const model = HF_MODELS.find(m => m.id === modelId); |
| if (model) openDeployModal(model); |
| } |
| }); |
| }); |
| } |
|
|
| function createModelCard(model) { |
| const recommendedGpus = GPU_OPTIONS.filter(g => g.maxVram >= model.vram && g.minVram <= model.vram).slice(0, 2); |
| return ` |
| <article class="model-card ${model.featured ? 'featured' : ''}" data-model-id="${model.id}"> |
| <div class="model-header"> |
| <div class="model-avatar">${getTypeIcon(model.type)}</div> |
| <div class="model-info"> |
| <div class="model-name">${model.name}</div> |
| <div class="model-org"><span class="hf-logo">🤗</span> ${model.org}</div> |
| </div> |
| </div> |
| <div class="model-meta"> |
| <span class="model-tag ${model.type}">${getTypeLabel(model.type)}</span> |
| <span class="gpu-badge">≥${model.vram}GB VRAM</span> |
| </div> |
| <p class="model-desc">${model.description}</p> |
| <div class="model-footer"> |
| <div class="model-stats"> |
| <span class="model-stat">⬇ ${formatNumber(model.downloads)}</span> |
| <span class="model-stat">♥ ${formatNumber(model.likes)}</span> |
| </div> |
| <button class="deploy-btn" onclick="event.stopPropagation(); openDeployModal(HF_MODELS.find(m => m.id === '${model.id}'))"> |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg> |
| Deploy |
| </button> |
| </div> |
| </article> |
| `; |
| } |
|
|
| function renderGpus() { |
| document.getElementById('gpu-grid').innerHTML = GPU_OPTIONS.map(gpu => ` |
| <div class="dimension-card ${gpu.featured ? 'dim-prism' : 'dim-nexus'}"> |
| <span class="dim-icon">${gpu.featured ? '⭐' : '🎮'}</span> |
| <h3>${gpu.name}</h3> |
| <p>${gpu.vram} VRAM · ${gpu.minVram > 0 ? 'Best for ' + gpu.minVram + 'GB+' : 'Entry level'}</p> |
| <div style="margin: 16px 0; text-align: left;"> |
| <div style="display:flex; justify-content:space-between; margin-bottom:4px;"> |
| <span style="color:var(--text2); font-size:0.8rem;">On-Demand</span> |
| <span style="font-weight:700; color:var(--hf-yellow);">$${gpu.price}/hr</span> |
| </div> |
| <div style="display:flex; justify-content:space-between;"> |
| <span style="color:var(--text2); font-size:0.8rem;">Spot (save ${Math.round((1-gpu.spot/gpu.price)*100)}%)</span> |
| <span style="font-weight:700; color:var(--model-green);">$${gpu.spot}/hr</span> |
| </div> |
| </div> |
| <a href="#models" class="dim-cta">Select for Deployment →</a> |
| </div> |
| `).join(''); |
| } |
|
|
| let deployModalModel = null; |
| let deployModalGpu = null; |
|
|
| function openDeployModal(model, gpuHint = null) { |
| deployModalModel = model; |
| deployModalGpu = null; |
| const modal = document.getElementById('deploy-modal'); |
| const title = document.getElementById('modal-title'); |
| const info = document.getElementById('modal-model-info'); |
| const gpuOptions = document.getElementById('gpu-options'); |
|
|
| if (model) { |
| title.textContent = `Deploy ${model.name}`; |
| info.innerHTML = ` |
| <div class="glass" style="padding: 16px; border-radius: var(--radius-sm);"> |
| <div class="model-header" style="margin-bottom: 12px;"> |
| <div class="model-avatar">${getTypeIcon(model.type)}</div> |
| <div class="model-info"> |
| <div class="model-name">${model.name}</div> |
| <div class="model-org"><span class="hf-logo">🤗</span> ${model.org} · ${model.id}</div> |
| </div> |
| </div> |
| <div class="model-meta"> |
| <span class="model-tag ${model.type}">${getTypeLabel(model.type)}</span> |
| <span class="gpu-badge">Min VRAM: ${model.vram}GB</span> |
| </div> |
| </div> |
| `; |
| const suitable = GPU_OPTIONS.filter(g => g.maxVram >= model.vram); |
| gpuOptions.innerHTML = suitable.map(g => ` |
| <div class="gpu-option ${g.featured ? 'featured' : ''}" data-gpu="${g.id}" onclick="selectGpu('${g.id}')"> |
| <div class="gpu-name">${g.name} ${g.featured ? '⭐' : ''}</div> |
| <div class="gpu-vram">${g.vram} VRAM</div> |
| <div class="gpu-price">$${g.price}/hr <span style="color:var(--model-green); font-size:0.8rem;">(spot $${g.spot})</span></div> |
| </div> |
| `).join(''); |
| if (gpuHint === 'featured') { |
| const rec = suitable.find(g => g.featured) || suitable[0]; |
| if (rec) selectGpu(rec.id); |
| } |
| } else { |
| title.textContent = 'Quick Deploy'; |
| info.innerHTML = '<p style="color:var(--text2);">Select a model from the catalog first, or enter a Hugging Face model ID.</ gpuOptions.innerHTML = GPU_OPTIONS.map(g => ` |
| <div class="gpu-option ${g.featured ? 'featured' : ''}" data-gpu="${g.id}" onclick="selectGpu('${g.id}')"> |
| <div class="gpu-name">${g.name} ${g.featured ? '⭐' : ''}</div> |
| <div class="gpu-vram">${g.vram} VRAM</div> |
| <div class="gpu-price">$${g.price}/hr</div> |
| </div> |
| `).join(''); |
| } |
| modal.classList.add('open'); |
| document.body.style.overflow = 'hidden'; |
| } |
| |
| function closeDeployModal() { |
| document.getElementById('deploy-modal').classList.remove('open'); |
| document.body.style.overflow = ''; |
| deployModalModel = null; |
| deployModalGpu = null; |
| } |
| |
| function selectGpu(gpuId) { |
| deployModalGpu = gpuId; |
| document.querySelectorAll('.gpu-option').forEach(el => { |
| el.classList.toggle('selected', el.dataset.gpu === gpuId); |
| }); |
| } |
| |
| function submitDeployment() { |
| if (!deployModalModel) { |
| alert('Please select a model first'); |
| return; |
| } |
| if (!deployModalGpu) { |
| alert('Please select a GPU'); |
| return; |
| } |
| const gpu = GPU_OPTIONS.find(g => g.id === deployModalGpu); |
| const model = deployModalModel; |
| const endpoint = `https://${model.id.replace('/', '-')}-${deployModalGpu}.runpod.io`; |
| alert(`🚀 Deploying ${model.name} on ${gpu.name}...\n\nEndpoint: ${endpoint}\n\nThis would trigger RunPod API to create a serverless endpoint.\nEstimated cost: $${gpu.price}/hr (spot: $${gpu.spot}/hr)\n\n💡 Pro tip: Sign up at https://runpod.io?ref=lc0jiiz3 for $10 free credits!`); |
| closeDeployModal(); |
| } |
| |
| // Handle form submission |
| const searchForm = document.getElementById('search-form'); |
| if (searchForm) { |
| searchForm.addEventListener('submit', (e) => { |
| e.preventDefault(); |
| document.getElementById('models').scrollIntoView({ behavior: 'smooth' }); |
| }); |
| } |
| |
| document.getElementById('search-input').addEventListener('input', (e) => { |
| searchQuery = e.target.value.trim(); |
| renderModels(); |
| }); |
| |
| document.getElementById('search-input').addEventListener('keydown', (e) => { |
| if (e.key === 'Enter') { |
| e.preventDefault(); |
| document.getElementById('models').scrollIntoView({ behavior: 'smooth' }); |
| } |
| }); |
| |
| document.getElementById('deploy-modal').addEventListener('click', (e) => { |
| if (e.target === e.currentTarget) closeDeployModal(); |
| }); |
| |
| document.addEventListener('keydown', (e) => { |
| if (e.key === 'Escape') closeDeployModal(); |
| }); |
| |
| function scrollToModels() { |
| document.getElementById('models').scrollIntoView({ behavior: 'smooth' }); |
| } |
| |
| document.addEventListener('DOMContentLoaded', () => { |
| renderStats(); |
| renderFeatured(); |
| createFilterTabs(); |
| renderModels(); |
| renderGpus(); |
| |
| // Signal bar animation |
| let signal = 0; |
| setInterval(() => { |
| signal = Math.min(100, signal + Math.random() * 15); |
| if (signal > 95) signal = Math.random() * 20; |
| document.getElementById('signal-fill').style.width = signal + '%'; |
| document.getElementById('signal-pct').textContent = Math.round(signal) + '%'; |
| }, 2000); |
| }); |
| |
| function scrollToModels() { |
| document.getElementById('models').scrollIntoView({ behavior: 'smooth' }); |
| } |