Download script.js from sirunchained/model-needed-ram-calculator: direct link, hf CLI and curl.
- Browser
- Download file 5.83 kB
-
https://huggingface.co/spaces/sirunchained/model-needed-ram-calculator/resolve/main/script.js
- Command line
-
hf download hf://spaces/sirunchained/model-needed-ram-calculator/script.js
-
curl -L -o script.js https://huggingface.co/spaces/sirunchained/model-needed-ram-calculator/resolve/main/script.js
5.83 kB
| (function () { | |
| "use strict"; | |
| // ---- Data types & quantization ---- | |
| const dataTypes = [ | |
| { name: "float32", bits: 32, bytes: 4 }, | |
| { name: "float16", bits: 16, bytes: 2 }, | |
| { name: "bfloat16", bits: 16, bytes: 2 }, | |
| { name: "8-bit (INT8)", bits: 8, bytes: 1 }, | |
| { name: "6-bit (Q_6)", bits: 6, bytes: 0.75 }, | |
| { name: "4-bit (Q_4)", bits: 4, bytes: 0.5 }, | |
| { name: "3-bit (Q_3)", bits: 3, bytes: 0.375 }, | |
| { name: "2-bit (Q_2)", bits: 2, bytes: 0.25 } | |
| ]; | |
| // ---- DOM refs ---- | |
| const paramInput = document.getElementById('paramInput'); | |
| const calculateBtn = document.getElementById('calculateBtn'); | |
| const tableBody = document.getElementById('tableBody'); | |
| const paramDisplay = document.getElementById('paramDisplay'); | |
| const themeToggle = document.getElementById('themeToggle'); | |
| const themeIcon = document.getElementById('themeIcon'); | |
| // ---- Helper: parse "1.5B", "100M", "7B", "1,000,000", etc. ---- | |
| function parseParameters(rawInput) { | |
| let cleaned = String(rawInput).replace(/,/g, '').replace(/\s/g, '').trim(); | |
| if (cleaned === '') return NaN; | |
| const lower = cleaned.toLowerCase(); | |
| let multiplier = 1; | |
| let numStr = cleaned; | |
| if (lower.endsWith('b')) { | |
| multiplier = 1e9; | |
| numStr = cleaned.slice(0, -1); | |
| } else if (lower.endsWith('m')) { | |
| multiplier = 1e6; | |
| numStr = cleaned.slice(0, -1); | |
| } | |
| const num = parseFloat(numStr); | |
| if (isNaN(num) || num < 0) return NaN; | |
| return num * multiplier; | |
| } | |
| // ---- Helpers for formatting ---- | |
| function formatNumber(num, decimals = 2) { | |
| if (num === undefined || !isFinite(num)) return '—'; | |
| return num.toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ','); | |
| } | |
| function formatBytes(bytes) { | |
| if (bytes === undefined || !isFinite(bytes)) return '—'; | |
| if (Math.abs(bytes) >= 1e15) { | |
| return bytes.toExponential(2); | |
| } | |
| return formatNumber(bytes, 2); | |
| } | |
| function bytesToGiB(bytes) { return bytes / (1024 * 1024 * 1024); } | |
| function bytesToMiB(bytes) { return bytes / (1024 * 1024); } | |
| // ---- Map data type name to CSS class for color coding ---- | |
| function getDataTypeClass(name) { | |
| if (name.includes('float')) return 'float'; | |
| if (name.includes('8-bit')) return 'int8'; | |
| if (name.includes('6-bit')) return 'q6'; | |
| if (name.includes('4-bit')) return 'q4'; | |
| if (name.includes('3-bit')) return 'q3'; | |
| if (name.includes('2-bit')) return 'q2'; | |
| return ''; | |
| } | |
| // ---- Main calculation ---- | |
| function calculateAndRender(rawInput) { | |
| const numParams = parseParameters(rawInput); | |
| if (isNaN(numParams)) { | |
| tableBody.innerHTML = `<tr><td colspan="5" class="text-center text-danger">Please enter a valid number (e.g., 7B, 1.5b, 100M).</td></tr>`; | |
| paramDisplay.textContent = 'Invalid input'; | |
| return; | |
| } | |
| // Update badge | |
| let displayText = formatNumber(numParams, 0) + ' parameters'; | |
| if (numParams >= 1e9) { | |
| displayText = (numParams / 1e9).toFixed(2) + 'B parameters'; | |
| } else if (numParams >= 1e6) { | |
| displayText = (numParams / 1e6).toFixed(2) + 'M parameters'; | |
| } | |
| paramDisplay.textContent = displayText; | |
| // Build rows | |
| let rowsHtml = ''; | |
| dataTypes.forEach(dt => { | |
| const bytes = numParams * dt.bytes; | |
| const gb = bytesToGiB(bytes); | |
| const mib = bytesToMiB(bytes); | |
| const typeClass = getDataTypeClass(dt.name); | |
| rowsHtml += ` | |
| <tr data-type="${typeClass}"> | |
| <td><strong>${dt.name}</strong></td> | |
| <td>${dt.bits}</td> | |
| <td>${formatNumber(gb, 2)}</td> | |
| <td>${formatNumber(mib, 2)}</td> | |
| <td>${formatBytes(bytes)}</td> | |
| </tr> | |
| `; | |
| }); | |
| tableBody.innerHTML = rowsHtml; | |
| } | |
| // ---- Event listeners ---- | |
| calculateBtn.addEventListener('click', function () { | |
| calculateAndRender(paramInput.value); | |
| }); | |
| paramInput.addEventListener('keydown', function (e) { | |
| if (e.key === 'Enter') { | |
| e.preventDefault(); | |
| calculateAndRender(paramInput.value); | |
| } | |
| }); | |
| document.querySelectorAll('.btn-preset').forEach(btn => { | |
| btn.addEventListener('click', function () { | |
| const value = this.getAttribute('data-value'); | |
| paramInput.value = value; | |
| calculateAndRender(value); | |
| }); | |
| }); | |
| // Initial load (7B) | |
| calculateAndRender(paramInput.value); | |
| // ---- Dark / Light toggle (custom class, default = dark) ---- | |
| function setTheme(theme) { | |
| const html = document.documentElement; | |
| if (theme === 'dark') { | |
| html.classList.add('dark-mode'); | |
| themeIcon.textContent = '☀️'; // sun icon for switching to light | |
| } else { | |
| html.classList.remove('dark-mode'); | |
| themeIcon.textContent = '🌙'; // moon icon for switching to dark | |
| } | |
| localStorage.setItem('theme', theme); | |
| } | |
| themeToggle.addEventListener('click', function () { | |
| const current = document.documentElement.classList.contains('dark-mode') ? 'dark' : 'light'; | |
| setTheme(current === 'dark' ? 'light' : 'dark'); | |
| }); | |
| // Load saved theme, or default to dark | |
| function loadTheme() { | |
| const saved = localStorage.getItem('theme'); | |
| if (saved) { | |
| setTheme(saved); | |
| } else { | |
| setTheme('dark'); // default to dark | |
| } | |
| } | |
| loadTheme(); | |
| })(); |