Occamy-Explorer / app.js
Eang's picture
Add MLX 5-bit, floating formats and calibrated APEX including Mini
0657db8 verified
Raw History Blame Contribute Delete
9.57 kB
'use strict';
const $ = (selector) => document.querySelector(selector);
let data;
let platform = 'gguf';
let selectedId = 'q4_k_m';
let currentCommand = '';
let mlxRecipe = 'generate';
let currentApiRequest = '';
let toastTimer;
const notes = {
gguf: 'Twenty-four GGUF options: seventeen standard recipes plus seven APEX profiles, including four calibrated variants and Mini. All files use qwen2 metadata; normalize input to NFC. Vision uses the separate projector. Read the validation scope for each option.',
nvidia: 'Full-model checkpoints for GPU servers. File sizes include preserved vision weights. NVFP4 on H200 uses Marlin W4A16; native FP4 requires compatible hardware and kernels. Adjust context and memory settings to your GPU.',
mlx: 'Text-only native MLX candidates. Linux native validation passed; Mac Metal acceptance is pending. The recipes below await Mac validation. Allow extra unified memory beyond the weight files.',
research: 'Experimental MTP draft head, not a standalone model. Download a base separately and follow the patched SGLang setup. Performance after the final MTP3 fix has not been measured.'
};
function escapeHtml(value) {
return String(value).replace(/[&<>"']/g, char => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[char]));
}
function link(url, label, cls = '') {
return `<a class="${cls}" href="${escapeHtml(url)}" target="_blank" rel="noopener noreferrer">${label}</a>`;
}
function visionEnabled() { return platform === 'gguf' && $('#vision').checked; }
function weightBytes(model) { return model.bytes + (visionEnabled() ? data.projector.bytes : 0); }
function render() {
const budget = $('#budget');
const limit = budget.value === '' || !budget.validity.valid ? Infinity : Number(budget.value) * 2 ** 30;
const models = data.models.filter(m => m.platform === platform && weightBytes(m) <= limit);
$('#vision').disabled = platform !== 'gguf';
$('#platform-note').textContent = notes[platform];
$('#checkpoint-panel').setAttribute('aria-labelledby', `tab-${platform}`);
if (!models.some(m => m.id === selectedId)) selectedId = models[0]?.id ?? null;
$('#model-list').innerHTML = models.length ? models.map(m => `<button class="model-row" data-model="${escapeHtml(m.id)}" aria-pressed="${m.id === selectedId}"><span class="row-name">${escapeHtml(m.label)}${m.status !== 'Published' ? `<small>${escapeHtml(m.status)}</small>` : ''}</span><span class="row-size">${(weightBytes(m) / 2 ** 30).toFixed(2)} GiB<small>${(weightBytes(m) / 1e9).toFixed(2)} GB</small></span></button>`).join('') : '<div class="empty-state">No checkpoint fits this weight budget. Increase the budget or clear it to see all options.</div>';
$('#result-count').textContent = `${models.length} of ${data.models.filter(m => m.platform === platform).length} checkpoints · weight files only`;
const model = models.find(m => m.id === selectedId);
if (!model) {
currentCommand = '';
$('#details').innerHTML = '<div class="empty-state">Set a larger weight budget or choose another runtime. Runtime memory will exceed file size; the MTP head also needs a base model.</div>';
return;
}
currentCommand = model.command;
currentApiRequest = '';
if (model.platform === 'mlx' && mlxRecipe === 'server') {
currentCommand = String.raw`python -m pip install "mlx==0.32.2" "mlx-lm==0.31.3" "transformers==5.8.1"
mlx_lm.server --model ${model.repo} \
--host 127.0.0.1 --port 8000 \
--chat-template-args '{"enable_thinking":false}'`;
const payload = JSON.stringify({model: model.repo, messages: [{role: 'user', content: 'Compute 2+2. Answer briefly.'}], temperature: 0, max_tokens: 128});
currentApiRequest = String.raw`curl http://127.0.0.1:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '${payload}'`;
}
if (visionEnabled()) {
currentCommand = currentCommand.replace('\n\nllama-server', '\n' + 'hf download Accio-Lab/occamy-1.0-GGUF mmproj-occamy-1.0-F16.gguf --local-dir ./occamy-gguf' + '\n\nllama-server');
currentCommand += ' \\\n --mmproj ./occamy-gguf/mmproj-occamy-1.0-F16.gguf';
}
const recipeSwitch = model.platform === 'mlx' ? `<div class="recipe-switch" role="group" aria-label="MLX usage"><button type="button" data-recipe="generate" aria-pressed="${mlxRecipe === 'generate'}">Run a prompt</button><button type="button" data-recipe="server" aria-pressed="${mlxRecipe === 'server'}">Start local API</button></div>` : '';
const apiPanel = currentApiRequest ? `<div class="api-panel"><div class="command-header"><h4>Send a request · second terminal</h4><button class="copy-button" id="copy-api" type="button">Copy request</button></div><pre id="api-request"><code>${escapeHtml(currentApiRequest)}</code></pre><p>Use <code>http://127.0.0.1:8000/v1</code> as the base URL in an OpenAI-compatible client. The server runs on your machine. Mac Metal acceptance remains pending.</p></div>` : '';
const pending = model.status !== 'Published';
let actions = model.download ? link(model.download, 'Download weights ↓', 'primary') : link(model.url + '/tree/main', 'Browse weight files ↗', 'primary');
actions += link(model.url, 'Model card ↗');
if (visionEnabled()) actions += link(data.projector.url, 'Vision projector ↓');
const inputText = model.platform === 'research' ? 'Base required' : model.platform === 'mlx' ? 'Text only' : model.platform === 'gguf' ? (visionEnabled() ? 'Text + projector' : 'Text · vision optional') : 'Text + vision';
const codeHeading = model.platform === 'research' ? 'Download & setup notes' : model.platform === 'mlx' ? 'Usage recipe · Mac validation pending' : 'Deployment command';
$('#details').innerHTML = `<div class="detail-top"><h3 class="detail-title">${escapeHtml(model.label)}</h3><span class="status ${pending ? 'pending' : ''}">${escapeHtml(model.status)}</span></div><p class="detail-description">${escapeHtml(model.description)}</p><div class="detail-stats"><div><b>${(weightBytes(model) / 2 ** 30).toFixed(2)} GiB${model.platform === 'research' ? ' + base' : ''}</b><span>${visionEnabled() ? 'Weights + vision projector' : 'Weight files'}</span></div><div><b>${escapeHtml(inputText)}</b><span>Input / requirements</span></div></div><div class="actions">${actions}</div>${recipeSwitch}<div class="command-header"><h4>${codeHeading}</h4><button class="copy-button" id="copy-command" type="button">Copy command</button></div><pre id="command"><code>${escapeHtml(currentCommand)}</code></pre>${apiPanel}<div class="validation"><h4>Validation scope</h4><p>${escapeHtml(model.evidence)}</p>${link(model.url + '/tree/' + model.revision, 'Inspected source · ' + model.revision.slice(0, 8) + ' ↗', 'source-link')}</div>`;
$('#copy-command').addEventListener('click', copyCommand);
document.querySelectorAll('[data-recipe]').forEach(button => button.addEventListener('click', () => { mlxRecipe = button.dataset.recipe; render(); }));
if (currentApiRequest) $('#copy-api').addEventListener('click', () => copyText(currentApiRequest, '#api-request'));
}
async function copyCommand() { return copyText(currentCommand, '#command'); }
async function copyText(text, selector) {
try {
await navigator.clipboard.writeText(text);
showToast('Command copied');
} catch {
const range = document.createRange();
range.selectNodeContents($(selector));
const selection = window.getSelection();
selection.removeAllRanges(); selection.addRange(range);
showToast('Command selected — press Ctrl+C or ⌘C to copy');
}
}
function showToast(message) {
$('#toast').textContent = message;
$('#toast').classList.add('visible');
clearTimeout(toastTimer);
toastTimer = setTimeout(() => $('#toast').classList.remove('visible'), 3000);
}
function choosePlatform(next) {
platform = next;
const preferred = {gguf: 'q4_k_m', nvidia: 'fp8', mlx: 'mlx-4-bit', research: 'mtp-head'};
selectedId = preferred[platform];
document.querySelectorAll('[role="tab"]').forEach(tab => {
const active = tab.dataset.platform === platform;
tab.setAttribute('aria-selected', String(active));
tab.tabIndex = active ? 0 : -1;
});
render();
}
document.querySelectorAll('[role="tab"]').forEach((tab, index, tabs) => {
tab.addEventListener('click', () => choosePlatform(tab.dataset.platform));
tab.addEventListener('keydown', event => {
if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return;
event.preventDefault();
const next = event.key === 'Home' ? 0 : event.key === 'End' ? tabs.length - 1 : (index + (event.key === 'ArrowRight' ? 1 : -1) + tabs.length) % tabs.length;
tabs[next].focus(); choosePlatform(tabs[next].dataset.platform);
});
});
$('#budget').addEventListener('input', () => { if (data) render(); });
$('#vision').addEventListener('change', () => { if (data) render(); });
$('#model-list').addEventListener('click', event => {
const button = event.target.closest('[data-model]');
if (button) { selectedId = button.dataset.model; render(); }
});
fetch('catalog.json').then(response => {
if (!response.ok) throw new Error('Catalog unavailable');
return response.json();
}).then(catalog => {
data = catalog;
$('#collection-link').href = data.collection;
$('#mlx-collection-link').href = data.mlx_collection;
render();
}).catch(() => {
$('#details').innerHTML = '<p class="error-message">The checkpoint catalog could not be loaded. <a href="https://huggingface.co/Accio-Lab/occamy-1.0">Open the model card</a> for downloads and deployment instructions.</p>';
});