Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>RedHatAI Model Explorer</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
.model-card:hover { | |
transform: translateY(-5px); | |
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); | |
} | |
.loading-spinner { | |
animation: spin 1s linear infinite; | |
} | |
@keyframes spin { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
.tag:hover { | |
background-color: #e5e7eb; | |
} | |
.tag.active { | |
background-color: #dc2626; | |
color: white; | |
} | |
.pagination-btn:disabled { | |
opacity: 0.5; | |
cursor: not-allowed; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-50 min-h-screen"> | |
<header class="bg-white shadow-sm"> | |
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6"> | |
<div class="flex flex-col md:flex-row md:items-center md:justify-between"> | |
<div class="flex items-center"> | |
<div class="bg-red-600 p-2 rounded-lg mr-4"> | |
<i class="fas fa-robot text-white text-2xl"></i> | |
</div> | |
<h1 class="text-3xl font-bold text-gray-900">RedHatAI Model Explorer</h1> | |
</div> | |
<div class="mt-4 md:mt-0"> | |
<a href="https://huggingface.co/RedHatAI" target="_blank" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"> | |
<i class="fab fa-hubspot mr-2"></i> View on Hugging Face | |
</a> | |
</div> | |
</div> | |
<p class="mt-2 text-sm text-gray-600">Browse and filter through all models from the RedHatAI organization</p> | |
</div> | |
</header> | |
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> | |
<div class="mb-8 bg-white p-6 rounded-lg shadow"> | |
<div class="flex flex-col md:flex-row md:items-center md:space-x-4"> | |
<div class="flex-1 mb-4 md:mb-0"> | |
<label for="search" class="block text-sm font-medium text-gray-700 mb-1">Search Models</label> | |
<div class="relative"> | |
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> | |
<i class="fas fa-search text-gray-400"></i> | |
</div> | |
<input type="text" id="search" placeholder="Search by model name, description..." class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-red-500 focus:border-red-500"> | |
</div> | |
</div> | |
<div class="w-full md:w-auto"> | |
<label for="filter" class="block text-sm font-medium text-gray-700 mb-1">Filter by Type</label> | |
<select id="filter" class="block w-full pl-3 pr-10 py-2 text-base border border-gray-300 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm rounded-md"> | |
<option value="all">All Models</option> | |
<option value="text-generation">Text Generation</option> | |
<option value="text-classification">Text Classification</option> | |
<option value="image-text-to-text">Multimodal</option> | |
<option value="conversational">Conversational</option> | |
</select> | |
</div> | |
<div class="w-full md:w-auto"> | |
<label for="sort" class="block text-sm font-medium text-gray-700 mb-1">Sort By</label> | |
<select id="sort" class="block w-full pl-3 pr-10 py-2 text-base border border-gray-300 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm rounded-md"> | |
<option value="downloads">Most Downloads</option> | |
<option value="likes">Most Likes</option> | |
<option value="recent">Most Recent</option> | |
</select> | |
</div> | |
</div> | |
<div class="mt-4 flex flex-wrap gap-2"> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="all">All</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="llama">Llama</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="mistral">Mistral</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="deepseek">DeepSeek</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="qwen">Qwen</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="gemma">Gemma</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="fp8">FP8</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="int4">4-bit</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="int8">8-bit</span> | |
<span class="tag px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 cursor-pointer" data-tag="vllm">vLLM</span> | |
</div> | |
</div> | |
<div id="stats" class="mb-6 bg-white p-4 rounded-lg shadow hidden"> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-4"> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<div class="flex items-center"> | |
<div class="bg-red-100 p-2 rounded-full mr-3"> | |
<i class="fas fa-download text-red-600"></i> | |
</div> | |
<div> | |
<p class="text-sm text-gray-500">Downloads this month</p> | |
<p id="total-downloads" class="text-xl font-semibold">-</p> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<div class="flex items-center"> | |
<div class="bg-red-100 p-2 rounded-full mr-3"> | |
<i class="fas fa-heart text-red-600"></i> | |
</div> | |
<div> | |
<p class="text-sm text-gray-500">Total Likes</p> | |
<p id="total-likes" class="text-xl font-semibold">-</p> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<div class="flex items-center"> | |
<div class="bg-red-100 p-2 rounded-full mr-3"> | |
<i class="fas fa-cube text-red-600"></i> | |
</div> | |
<div> | |
<p class="text-sm text-gray-500">Total Models</p> | |
<p id="total-models" class="text-xl font-semibold">-</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div id="loading" class="flex justify-center items-center py-12"> | |
<div class="loading-spinner h-12 w-12 border-4 border-red-500 border-t-transparent rounded-full"></div> | |
<span class="ml-3 text-gray-600">Loading models...</span> | |
</div> | |
<div id="models-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 hidden"> | |
<!-- Models will be inserted here by JavaScript --> | |
</div> | |
<div id="no-results" class="hidden text-center py-12"> | |
<i class="fas fa-exclamation-circle text-gray-400 text-5xl mb-4"></i> | |
<h3 class="text-lg font-medium text-gray-900">No models found</h3> | |
<p class="mt-1 text-sm text-gray-500">Try adjusting your search or filter criteria</p> | |
</div> | |
<div class="mt-8 flex justify-between items-center"> | |
<button id="prev-page" class="px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 disabled:opacity-50" disabled> | |
<i class="fas fa-chevron-left mr-2"></i> Previous | |
</button> | |
<span id="page-info" class="text-sm text-gray-600">Page 1 of 1</span> | |
<button id="next-page" class="px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 disabled:opacity-50" disabled> | |
Next <i class="fas fa-chevron-right ml-2"></i> | |
</button> | |
</div> | |
</main> | |
<footer class="bg-white border-t border-gray-200 mt-12"> | |
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6"> | |
<div class="flex flex-col md:flex-row justify-between items-center"> | |
<div class="flex items-center"> | |
<div class="bg-red-600 p-2 rounded-lg mr-4"> | |
<i class="fas fa-robot text-white text-xl"></i> | |
</div> | |
<p class="text-gray-500 text-sm">RedHatAI Model Explorer - Not affiliated with Red Hat or Hugging Face</p> | |
</div> | |
<div class="mt-4 md:mt-0"> | |
<a href="https://github.com/RedHatAI" target="_blank" class="text-gray-400 hover:text-gray-500"> | |
<i class="fab fa-github text-2xl"></i> | |
</a> | |
</div> | |
</div> | |
</div> | |
</footer> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// DOM elements | |
const searchInput = document.getElementById('search'); | |
const filterSelect = document.getElementById('filter'); | |
const sortSelect = document.getElementById('sort'); | |
const modelsContainer = document.getElementById('models-container'); | |
const loadingElement = document.getElementById('loading'); | |
const noResultsElement = document.getElementById('no-results'); | |
const prevPageButton = document.getElementById('prev-page'); | |
const nextPageButton = document.getElementById('next-page'); | |
const pageInfoElement = document.getElementById('page-info'); | |
const tags = document.querySelectorAll('.tag'); | |
const statsContainer = document.getElementById('stats'); | |
const totalDownloadsElement = document.getElementById('total-downloads'); | |
const totalLikesElement = document.getElementById('total-likes'); | |
const totalModelsElement = document.getElementById('total-models'); | |
// State variables | |
let allModels = []; | |
let filteredModels = []; | |
let currentPage = 1; | |
const modelsPerPage = 9; | |
let activeTag = 'all'; | |
// Initialize the app | |
fetchModels(); | |
// Event listeners | |
searchInput.addEventListener('input', debounce(filterModels, 300)); | |
filterSelect.addEventListener('change', filterModels); | |
sortSelect.addEventListener('change', filterModels); | |
prevPageButton.addEventListener('click', goToPreviousPage); | |
nextPageButton.addEventListener('click', goToNextPage); | |
tags.forEach(tag => tag.addEventListener('click', filterByTag)); | |
// Fetch models from Hugging Face API | |
async function fetchModels() { | |
try { | |
loadingElement.classList.remove('hidden'); | |
// In a real app, you would fetch from the API: | |
const response = await fetch('https://huggingface.co/api/models?author=RedHatAI'); | |
allModels = await response.json(); | |
// // For demo purposes, we'll use the sample data from your example | |
// allModels = [ | |
// { | |
// "_id": "67f7a165ec6cd206ef5da57f", | |
// "id": "RedHatAI/Llama-4-Scout-17B-16E-Instruct-FP8-dynamic", | |
// "likes": 6, | |
// "trendingScore": 6, | |
// "private": false, | |
// "downloads": 1232, | |
// "tags": ["safetensors", "llama4", "base_model:meta-llama/Llama-4-Scout-17B-16E-Instruct", "base_model:quantized:meta-llama/Llama-4-Scout-17B-16E-Instruct", "compressed-tensors", "region:us"], | |
// "createdAt": "2025-04-10T10:45:57.000Z", | |
// "modelId": "RedHatAI/Llama-4-Scout-17B-16E-Instruct-FP8-dynamic", | |
// "pipeline_tag": "text-generation" | |
// }, | |
// { | |
// "_id": "66a02afb813431cd7a6bca12", | |
// "id": "RedHatAI/Meta-Llama-3.1-70B-Instruct-FP8", | |
// "likes": 45, | |
// "trendingScore": 3, | |
// "private": false, | |
// "downloads": 182800, | |
// "tags": ["transformers", "safetensors", "llama", "text-generation", "fp8", "vllm", "conversational", "en", "de", "fr", "it", "pt", "hi", "es", "th", "base_model:meta-llama/Llama-3.1-70B-Instruct", "base_model:quantized:meta-llama/Llama-3.1-70B-Instruct", "license:llama3.1", "autotrain_compatible", "text-generation-inference", "endpoints_compatible", "compressed-tensors", "region:us"], | |
// "pipeline_tag": "text-generation", | |
// "library_name": "transformers", | |
// "createdAt": "2024-07-23T22:13:15.000Z", | |
// "modelId": "RedHatAI/Meta-Llama-3.1-70B-Instruct-FP8" | |
// }, | |
// { | |
// "_id": "664b9a005df8c7926f78be84", | |
// "id": "RedHatAI/Meta-Llama-3-8B-Instruct-FP8-KV", | |
// "likes": 8, | |
// "trendingScore": 1, | |
// "private": false, | |
// "downloads": 3950, | |
// "tags": ["transformers", "safetensors", "llama", "text-generation", "fp8", "vllm", "conversational", "autotrain_compatible", "text-generation-inference", "endpoints_compatible", "region:us"], | |
// "pipeline_tag": "text-generation", | |
// "library_name": "transformers", | |
// "createdAt": "2025-05-20T18:44:16.000Z", | |
// "modelId": "RedHatAI/Meta-Llama-3-8B-Instruct-FP8-KV" | |
// }, | |
// { | |
// "_id": "66a3f1c5ee3de8c56ef34fa3", | |
// "id": "RedHatAI/Meta-Llama-3.1-8B-Instruct-quantized.w4a16", | |
// "likes": 27, | |
// "trendingScore": 1, | |
// "private": false, | |
// "downloads": 156851, | |
// "tags": ["transformers", "safetensors", "llama", "text-generation", "int4", "vllm", "conversational", "en", "de", "fr", "it", "pt", "hi", "es", "th", "base_model:meta-llama/Llama-3.1-8B-Instruct", "base_model:quantized:meta-llama/Llama-3.1-8B-Instruct", "license:llama3.1", "autotrain_compatible", "text-generation-inference", "endpoints_compatible", "4-bit", "gptq", "region:us"], | |
// "pipeline_tag": "text-generation", | |
// "library_name": "transformers", | |
// "createdAt": "2024-07-26T18:58:13.000Z", | |
// "modelId": "RedHatAI/Meta-Llama-3.1-8B-Instruct-quantized.w4a16" | |
// }, | |
// { | |
// "_id": "66aa715f1b4923ce7bb7d49d", | |
// "id": "RedHatAI/Meta-Llama-3.1-8B-quantized.w8a8", | |
// "likes": 3, | |
// "trendingScore": 1, | |
// "private": false, | |
// "downloads": 224, | |
// "tags": ["transformers", "safetensors", "llama", "text-generation", "int8", "vllm", "quantized", "8-bit", "en", "de", "fr", "it", "pt", "hi", "es", "th", "arxiv:2210.17323", "base_model:meta-llama/Llama-3.1-8B", "base_model:quantized:meta-llama/Llama-3.1-8B", "license:llama3.1", "autotrain_compatible", "text-generation-inference", "endpoints_compatible", "compressed-tensors", "region:us"], | |
// "pipeline_tag": "text-generation", | |
// "library_name": "transformers", | |
// "createdAt": "2024-07-31T17:16:15.000Z", | |
// "modelId": "RedHatAI/Meta-Llama-3.1-8B-quantized.w8a8" | |
// }, | |
// { | |
// "_id": "66be6896182d5a69aee95889", | |
// "id": "RedHatAI/gemma-2-9b-it-quantized.w4a16", | |
// "likes": 2, | |
// "trendingScore": 1, | |
// "private": false, | |
// "downloads": 88, | |
// "tags": ["safetensors", "gemma2", "text-generation", "conversational", "en", "arxiv:2210.17323", "license:llama2", "compressed-tensors", "region:us"], | |
// "pipeline_tag": "text-generation", | |
// "createdAt": "2024-08-15T20:44:06.000Z", | |
// "modelId": "RedHatAI/gemma-2-9b-it-quantized.w4a16" | |
// }, | |
// { | |
// "_id": "678e9356b12fa7d661ccf013", | |
// "id": "RedHatAI/Llama-3.3-70B-Instruct-quantized.w8a8", | |
// "likes": 6, | |
// "trendingScore": 1, | |
// "private": false, | |
// "downloads": 4707, | |
// "tags": ["safetensors", "llama", "int8", "vllm", "chat", "neuralmagic", "llmcompressor", "text-generation", "conversational", "en", "de", "fr", "it", "pt", "hi", "es", "th", "base_model:meta-llama/Llama-3.3-70B-Instruct", "base_model:quantized:meta-llama/Llama-3.3-70B-Instruct", "license:llama3.3", "8-bit", "compressed-tensors", "region:us"], | |
// "pipeline_tag": "text-generation", | |
// "createdAt": "2025-01-20T18:17:58.000Z", | |
// "modelId": "RedHatAI/Llama-3.3-70B-Instruct-quantized.w8a8" | |
// }, | |
// { | |
// "_id": "679e94cd49b5b38e4fa2d8d0", | |
// "id": "RedHatAI/DeepSeek-R1-Distill-Llama-70B-FP8-dynamic", | |
// "likes": 8, | |
// "trendingScore": 1, | |
// "private": false, | |
// "downloads": 135908, | |
// "tags": ["transformers", "safetensors", "llama", "text-generation", "deepseek", "fp8", "vllm", "conversational", "base_model:deepseek-ai/DeepSeek-R1-Distill-Llama-70B", "base_model:quantized:deepseek-ai/DeepSeek-R1-Distill-Llama-70B", "license:mit", "autotrain_compatible", "text-generation-inference", "endpoints_compatible", "compressed-tensors", "region:us"], | |
// "pipeline_tag": "text-generation", | |
// "library_name": "transformers", | |
// "createdAt": "2025-02-01T21:40:29.000Z", | |
// "modelId": "RedHatAI/DeepSeek-R1-Distill-Llama-70B-FP8-dynamic" | |
// }, | |
// { | |
// "_id": "679becee4378dbc3579ac11a", | |
// "id": "RedHatAI/Mistral-Small-24B-Instruct-2501-FP8-dynamic", | |
// "private": false, | |
// "pipeline_tag": "text-generation", | |
// "library_name": "transformers", | |
// "tags": ["transformers", "safetensors", "mistral", "text-generation", "mistral-small", "fp8", "vllm", "conversational", "en", "base_model:mistralai/Mistral-Small-24B-Instruct-2501", "base_model:quantized:mistralai/Mistral-Small-24B-Instruct-2501", "license:apache-2.0", "autotrain_compatible", "text-generation-inference", "endpoints_compatible", "compressed-tensors", "region:us"], | |
// "downloads": 229986, | |
// "likes": 12, | |
// "modelId": "RedHatAI/Mistral-Small-24B-Instruct-2501-FP8-dynamic", | |
// "author": "RedHatAI", | |
// "sha": "9cb69aeda1e1162aa9c00c399105703c06214220", | |
// "lastModified": "2025-01-31T08:41:28.000Z", | |
// "gated": false, | |
// "disabled": false, | |
// "widgetData": [ | |
// {"text": "Hi, what can you help me with?"}, | |
// {"text": "What is 84 * 3 / 2?"}, | |
// {"text": "Tell me an interesting fact about the universe!"}, | |
// {"text": "Explain quantum computing in simple terms."} | |
// ], | |
// "config": { | |
// "architectures": ["MistralForCausalLM"], | |
// "model_type": "mistral", | |
// "quantization_config": {"quant_method": "compressed-tensors"}, | |
// "tokenizer_config": { | |
// "bos_token": "<s>", | |
// "chat_template": "{%- set today = strftime_now(\"%Y-%m-%d\") %}\n{%- set default_system_message = \"You are Mistral Small 3, a Large Language Model (LLM) created by Mistral AI, a French startup headquartered in Paris.\\nYour knowledge base was last updated on 2023-10-01. The current date is \" + today + \".\\n\\nWhen you're not sure about some information, you say that you don't have the information and don't make up anything.\\nIf the user's question is not clear, ambiguous, or does not provide enough context for you to accurately answer the question, you do not try to answer it right away and you rather ask the user to clarify their request (e.g. \\\"What are some good restaurants around me?\\\" => \\\"Where are you?\\\" or \\\"When is the next flight to Tokyo\\\" => \\\"Where do you travel from?\\\")\" %}\n\n{{- bos_token }}\n\n{%- if messages[0]['role'] == 'system' %}\n {%- set system_message = messages[0]['content'] %}\n {%- set loop_messages = messages[1:] %}\n{%- else %}\n {%- set system_message = default_system_message %}\n {%- set loop_messages = messages %}\n{%- endif %}\n{{- '[SYSTEM_PROMPT]' + system_message + '[/SYSTEM_PROMPT]' }}\n\n{%- for message in loop_messages %}\n {%- if message['role'] == 'user' %}\n {{- '[INST]' + message['content'] + '[/INST]' }}\n {%- elif message['role'] == 'system' %}\n {{- '[SYSTEM_PROMPT]' + message['content'] + '[/SYSTEM_PROMPT]' }}\n {%- elif message['role'] == 'assistant' %}\n {{- message['content'] + eos_token }}\n {%- else %}\n {{- raise_exception('Only user, system and assistant roles are supported!') }}\n {%- endif %}\n{%- endfor %}", | |
// "eos_token": "</s>", | |
// "unk_token": "<unk>", | |
// "use_default_system_prompt": false | |
// } | |
// }, | |
// "cardData": { | |
// "license": "apache-2.0", | |
// "language": ["en"], | |
// "tags": ["mistral", "mistral-small", "fp8", "vllm"], | |
// "base_model": "mistralai/Mistral-Small-24B-Instruct-2501", | |
// "library_name": "transformers" | |
// }, | |
// "transformersInfo": { | |
// "auto_model": "AutoModelForCausalLM", | |
// "pipeline_tag": "text-generation", | |
// "processor": "AutoTokenizer" | |
// }, | |
// "siblings": [ | |
// {"rfilename": ".gitattributes"}, | |
// {"rfilename": "README.md"}, | |
// {"rfilename": "config.json"}, | |
// {"rfilename": "generation_config.json"}, | |
// {"rfilename": "model-00001-of-00006.safetensors"}, | |
// {"rfilename": "model-00002-of-00006.safetensors"}, | |
// {"rfilename": "model-00003-of-00006.safetensors"}, | |
// {"rfilename": "model-00004-of-00006.safetensors"}, | |
// {"rfilename": "model-00005-of-00006.safetensors"}, | |
// {"rfilename": "model-00006-of-00006.safetensors"}, | |
// {"rfilename": "model.safetensors.index.json"}, | |
// {"rfilename": "recipe.yaml"}, | |
// {"rfilename": "special_tokens_map.json"}, | |
// {"rfilename": "tokenizer.json"}, | |
// {"rfilename": "tokenizer_config.json"} | |
// ], | |
// "spaces": ["KBaba7/Quant", "bhaskartripathi/LLM_Quantization", "totolook/Quant", "FallnAI/Quantize-HF-Models", "ruslanmv/convert_to_gguf", "K00B404/LLM_Quantization"], | |
// "createdAt": "2025-01-30T21:19:42.000Z", | |
// "safetensors": { | |
// "parameters": { | |
// "BF16": 1345868800, | |
// "F8_E4M3": 22229811200 | |
// }, | |
// "total": 23575680000 | |
// }, | |
// "usedStorage": 24938701317 | |
// } | |
// ]; | |
// Calculate stats | |
calculateStats(allModels); | |
// Initial display | |
filterModels(); | |
} catch (error) { | |
console.error('Error fetching models:', error); | |
loadingElement.innerHTML = ` | |
<div class="text-center"> | |
<i class="fas fa-exclamation-triangle text-red-500 text-4xl mb-3"></i> | |
<p class="text-red-600">Failed to load models. Please try again later.</p> | |
</div> | |
`; | |
} | |
} | |
// Calculate statistics | |
function calculateStats(models) { | |
const totalDownloads = models.reduce((sum, model) => sum + (model.downloads || 0), 0); | |
const totalLikes = models.reduce((sum, model) => sum + (model.likes || 0), 0); | |
totalDownloadsElement.textContent = totalDownloads.toLocaleString(); | |
totalLikesElement.textContent = totalLikes.toLocaleString(); | |
totalModelsElement.textContent = models.length.toLocaleString(); | |
statsContainer.classList.remove('hidden'); | |
} | |
// Filter models based on search, filter and sort criteria | |
function filterModels() { | |
const searchTerm = searchInput.value.toLowerCase(); | |
const filterValue = filterSelect.value; | |
const sortValue = sortSelect.value; | |
filteredModels = allModels.filter(model => { | |
// Skip private models | |
if (model.private) return false; | |
// Search term matching | |
const matchesSearch = model.id.toLowerCase().includes(searchTerm) || | |
(model.cardData && model.cardData.language && | |
model.cardData.language.join(' ').toLowerCase().includes(searchTerm)) || | |
(model.tags && model.tags.join(' ').toLowerCase().includes(searchTerm)); | |
// Filter matching | |
const matchesFilter = filterValue === 'all' || | |
(model.pipeline_tag && model.pipeline_tag === filterValue) || | |
(model.tags && model.tags.includes(filterValue)); | |
return matchesSearch && matchesFilter; | |
}); | |
// Sort models | |
if (sortValue === 'downloads') { | |
filteredModels.sort((a, b) => (b.downloads || 0) - (a.downloads || 0)); | |
} else if (sortValue === 'likes') { | |
filteredModels.sort((a, b) => (b.likes || 0) - (a.likes || 0)); | |
} else if (sortValue === 'recent') { | |
filteredModels.sort((a, b) => new Date(b.createdAt || b.lastModified || 0) - new Date(a.createdAt || a.lastModified || 0)); | |
} | |
// Reset to first page when filtering | |
currentPage = 1; | |
displayPaginatedModels(); | |
} | |
// Filter by tag | |
function filterByTag(e) { | |
const tag = e.target.dataset.tag; | |
activeTag = tag; | |
// Update active tag styling | |
tags.forEach(t => { | |
if (t.dataset.tag === tag) { | |
t.classList.add('active'); | |
} else { | |
t.classList.remove('active'); | |
} | |
}); | |
if (tag === 'all') { | |
filterSelect.value = 'all'; | |
searchInput.value = ''; | |
filteredModels = [...allModels]; | |
} else { | |
filteredModels = allModels.filter(model => | |
model.tags && model.tags.some(t => t.includes(tag)) | |
); | |
} | |
currentPage = 1; | |
displayPaginatedModels(); | |
} | |
// Display paginated models | |
function displayPaginatedModels() { | |
loadingElement.classList.add('hidden'); | |
if (filteredModels.length === 0) { | |
noResultsElement.classList.remove('hidden'); | |
modelsContainer.classList.add('hidden'); | |
return; | |
} | |
noResultsElement.classList.add('hidden'); | |
modelsContainer.classList.remove('hidden'); | |
// Calculate pagination | |
const totalPages = Math.ceil(filteredModels.length / modelsPerPage); | |
const startIndex = (currentPage - 1) * modelsPerPage; | |
const endIndex = Math.min(startIndex + modelsPerPage, filteredModels.length); | |
const paginatedModels = filteredModels.slice(startIndex, endIndex); | |
// Update pagination controls | |
pageInfoElement.textContent = `Page ${currentPage} of ${totalPages}`; | |
prevPageButton.disabled = currentPage === 1; | |
nextPageButton.disabled = currentPage === totalPages; | |
// Clear and repopulate models container | |
modelsContainer.innerHTML = ''; | |
paginatedModels.forEach(model => { | |
const modelCard = document.createElement('div'); | |
modelCard.className = 'model-card bg-white rounded-lg shadow-md overflow-hidden transition-all duration-200 ease-in-out'; | |
// Determine icon based on model type | |
let icon, iconColor; | |
if (model.pipeline_tag === 'text-generation' || model.tags?.includes('text-generation')) { | |
icon = 'fa-comment-alt'; | |
iconColor = 'text-blue-500'; | |
} else if (model.pipeline_tag === 'image-text-to-text' || model.tags?.includes('vision')) { | |
icon = 'fa-image'; | |
iconColor = 'text-green-500'; | |
} else if (model.pipeline_tag === 'conversational' || model.tags?.includes('conversational')) { | |
icon = 'fa-comments'; | |
iconColor = 'text-purple-500'; | |
} else { | |
icon = 'fa-cube'; | |
iconColor = 'text-gray-500'; | |
} | |
// Format date | |
const date = model.createdAt || model.lastModified; | |
const formattedDate = date ? new Date(date).toLocaleDateString() : 'Unknown'; | |
// Create model card | |
modelCard.innerHTML = ` | |
<div class="p-6"> | |
<div class="flex items-start"> | |
<div class="flex-shrink-0"> | |
<i class="fas ${icon} ${iconColor} text-3xl"></i> | |
</div> | |
<div class="ml-4"> | |
<h3 class="text-lg font-medium text-gray-900">${model.id.split('/')[1]}</h3> | |
<p class="mt-1 text-sm text-gray-500">${model.id}</p> | |
</div> | |
</div> | |
${model.cardData?.license ? `<p class="mt-2 text-xs text-gray-500"><span class="font-medium">License:</span> ${model.cardData.license}</p>` : ''} | |
${model.cardData?.language ? `<p class="mt-1 text-xs text-gray-500"><span class="font-medium">Languages:</span> ${model.cardData.language.join(', ')}</p>` : ''} | |
<div class="mt-4 flex flex-wrap gap-2"> | |
${model.tags ? model.tags.slice(0, 5).map(tag => `<span class="px-2 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800">${tag}</span>`).join('') : ''} | |
</div> | |
</div> | |
<div class="bg-gray-50 px-6 py-4 border-t border-gray-200"> | |
<div class="flex justify-between items-center"> | |
<div class="flex items-center"> | |
<i class="fas fa-download text-gray-400 mr-1"></i> | |
<span class="text-xs text-gray-500">${(model.downloads || 0).toLocaleString()}</span> | |
</div> | |
<div class="flex items-center"> | |
<i class="fas fa-heart text-gray-400 mr-1"></i> | |
<span class="text-xs text-gray-500">${(model.likes || 0).toLocaleString()}</span> | |
</div> | |
<div class="flex items-center"> | |
<i class="fas fa-calendar-alt text-gray-400 mr-1"></i> | |
<span class="text-xs text-gray-500">${formattedDate}</span> | |
</div> | |
</div> | |
</div> | |
<div class="px-6 py-3 bg-gray-50 border-t border-gray-200"> | |
<a href="https://huggingface.co/${model.id}" target="_blank" class="w-full flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700"> | |
<i class="fab fa-hubspot mr-2"></i> View Model | |
</a> | |
</div> | |
`; | |
modelsContainer.appendChild(modelCard); | |
}); | |
} | |
// Pagination functions | |
function goToPreviousPage() { | |
if (currentPage > 1) { | |
currentPage--; | |
displayPaginatedModels(); | |
} | |
} | |
function goToNextPage() { | |
const totalPages = Math.ceil(filteredModels.length / modelsPerPage); | |
if (currentPage < totalPages) { | |
currentPage++; | |
displayPaginatedModels(); | |
} | |
} | |
// Utility function for debouncing | |
function debounce(func, wait) { | |
let timeout; | |
return function() { | |
const context = this; | |
const args = arguments; | |
clearTimeout(timeout); | |
timeout = setTimeout(() => { | |
func.apply(context, args); | |
}, wait); | |
}; | |
} | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=mgoin/redhatai-model-explorer" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |