start-here / app.js
aleada's picture
toolkit index
339f48e verified
Raw History Blame Contribute Delete
4.09 kB
/**
* The index page: the five questions, in the order they come up.
*
* The list is rendered from the shared registry in `tools.js` rather
* than written out here — the same registry the five tools link each
* other with. A landing page that lists the tools from its own copy is
* the first place a rename goes stale, and it is the one page where a
* dead link costs the most.
*/
import { ORDER, TOOLS, url } from './tools.js';
import { DIAGRAMS, ensureDiagramStyles } from './diagrams.js';
const $ = (id) => document.getElementById(id);
ensureDiagramStyles();
const esc = (s) => String(s).replace(/[&<>"]/g, (c) =>
({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]));
/** What each step is for, in the words somebody arrives with. */
const SAYS = {
search: 'Filter the Hub by what decides usability rather than by task and '
+ 'licence: real size, how much of a pack is genuinely quantized, mixture '
+ 'of experts or dense, and whether serving it needs a reasoning parser.',
context: 'Weights fitting is not the same as the model running. The KV cache '
+ 'grows with context, and how fast depends on an attention topology most '
+ 'estimates assume rather than read. This gives you a starting '
+ '--max-model-len.',
parser: 'A model that thinks needs vLLM to split that thinking out of the '
+ 'answer. Guess wrong in one direction and users see the thinking; wrong '
+ 'in the other and the reply comes back empty with no error at all.',
precision: 'A pack named 4-bit is never 4-bit throughout — embeddings, the '
+ 'output head and the norms are usually kept whole. This says how much '
+ 'was really compressed and, more usefully, what was not.',
integrity: 'Quantization can drop or disable part of a model without '
+ 'failing: the pack loads, serves, answers correctly, and something its '
+ 'card promises is missing. This compares what it claims against what is '
+ 'in it.',
};
/** The question each step answers, phrased as the visitor would ask it. */
const ASKS = {
search: 'Which model should I even try?',
context: 'How much context can I actually serve?',
parser: 'How do I run it correctly?',
precision: 'What did this quantized pack really compress?',
integrity: 'Is the pack what it claims to be?',
};
function render(repo) {
$('steps').innerHTML = ORDER.map((key) => {
const t = TOOLS[key];
const href = url(key, repo);
const label = repo && t.takes === 'repo'
? `open for ${repo}`
: repo && t.takes === 'query' ? `search for ${repo}` : 'open';
// The diagram is drawn from a real measurement this toolkit
// produced, never a shape picked to look right — see diagrams.js.
const figure = DIAGRAMS[key] ? `<div class="fig">${DIAGRAMS[key]()}</div>` : '';
return `<li>
<div class="row">
<div class="text">
<span class="q">${esc(ASKS[key])}</span>
<a href="${href}" target="_blank" rel="noopener">${esc(t.title)}</a>
<p>${esc(SAYS[key])}</p>
<a class="go" href="${href}" target="_blank" rel="noopener">${esc(label)} →</a>
</div>
${figure}
</div>
</li>`;
}).join('');
}
// Every link re-renders as the box is typed in, so the page never offers
// a link that carries a model the visitor has since changed.
$('repo').addEventListener('input', () => render($('repo').value.trim()));
$('form').addEventListener('submit', (e) => e.preventDefault());
document.querySelectorAll('[data-fill]').forEach((a) =>
a.addEventListener('click', (e) => {
e.preventDefault();
$('repo').value = a.dataset.fill;
render(a.dataset.fill);
}));
// A model can be handed to this page too, so a link into the toolkit
// from anywhere lands with it already set.
const params = new URLSearchParams(window.location.search);
const initial = (params.get('repo') || '').trim();
if (initial) $('repo').value = initial;
render(initial || null);