File size: 4,085 Bytes
339f48e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**

 * 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);