aleada commited on
Commit
173ff89
·
verified ·
1 Parent(s): 93ab527

pack precision map

Browse files
Files changed (1) hide show
  1. tools.js +151 -124
tools.js CHANGED
@@ -1,124 +1,151 @@
1
- /**
2
- * The five tools, declared once.
3
- *
4
- * Each Space linked to the others from its own footer, which meant the
5
- * same five URLs written out in five files — twenty-five places for a
6
- * rename to break, and a Space rename is invisible from the linking
7
- * side: the link keeps returning a page, and the page is a 404.
8
- *
9
- * So the registry lives here and is copied into each Space at deploy
10
- * time, next to `progress.js`. One file to change when a tool moves.
11
- *
12
- * The order is the order somebody actually needs them: find a model,
13
- * see how much context it can serve, learn how to run it, then check
14
- * what the pack really contains before spending the download.
15
- */
16
-
17
- export const TOOLS = {
18
- search: {
19
- space: 'model-search-that-answers',
20
- title: 'Find a model that fits',
21
- asks: 'which models fit my card at all',
22
- // What the visitor has just learned, and why the next tool follows.
23
- leadsTo: 'context',
24
- takes: 'query',
25
- },
26
- context: {
27
- space: 'what-context-fits',
28
- title: 'What context will actually fit?',
29
- asks: 'how long a conversation this one can serve',
30
- leadsTo: 'parser',
31
- takes: 'repo',
32
- },
33
- parser: {
34
- space: 'reasoning-parser-advisor',
35
- title: 'Does this model need a reasoning parser?',
36
- asks: 'how to serve it without silently empty answers',
37
- leadsTo: 'precision',
38
- takes: 'repo',
39
- },
40
- precision: {
41
- space: 'pack-precision-map',
42
- title: 'How much of this pack is actually 4-bit?',
43
- asks: 'what a quantized pack really compressed, and what it kept',
44
- leadsTo: 'integrity',
45
- takes: 'repo',
46
- },
47
- integrity: {
48
- space: 'pack-integrity-check',
49
- title: 'Does this pack keep what it claims?',
50
- asks: 'whether anything was dropped or left undeclared',
51
- leadsTo: null,
52
- takes: 'repo',
53
- },
54
- };
55
-
56
- export const ORDER = ['search', 'context', 'parser', 'precision', 'integrity'];
57
-
58
- const BASE = 'https://huggingface.co/spaces/aleada';
59
-
60
- /**
61
- * A link to one tool, carrying the model with it.
62
- *
63
- * A funnel where each step starts empty is five separate tools with
64
- * links between them. `?repo=` is read on load by every page that takes
65
- * one, so clicking through keeps the model you were looking at.
66
- */
67
- export function url(key, repo = null) {
68
- const t = TOOLS[key];
69
- if (!t) return BASE;
70
- const q = repo && t.takes === 'repo'
71
- ? `?repo=${encodeURIComponent(repo)}`
72
- : repo && t.takes === 'query'
73
- ? `?q=${encodeURIComponent(repo)}` : '';
74
- return `${BASE}/${t.space}${q}`;
75
- }
76
-
77
- /** The model this page was opened with, if a link carried one over. */
78
- export function repoFromUrl() {
79
- const p = new URLSearchParams(window.location.search);
80
- return (p.get('repo') || p.get('q') || '').trim() || null;
81
- }
82
-
83
- const esc = (s) => String(s).replace(/[&<>"]/g, (c) =>
84
- ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]));
85
-
86
- /**
87
- * The next questions, rendered under a result.
88
- *
89
- * Offered only once there is an answer on screen: a next step shown
90
- * before the current one is finished is clutter, and a next step that
91
- * cannot carry the model over is a link to an empty form.
92
- */
93
- export function nextSteps(fromKey, repo = null, keys = null) {
94
- const rest = keys || ORDER.filter((k) => k !== fromKey);
95
- if (!rest.length) return '';
96
- const items = rest.map((k) => {
97
- const t = TOOLS[k];
98
- return `<li><a href="${url(k, repo)}" target="_blank" rel="noopener">${esc(t.title)}</a>
99
- <span class="ns-why">${esc(t.asks)}</span></li>`;
100
- }).join('');
101
- return `<nav class="nextsteps" aria-label="Related tools">
102
- <h4>Next${repo ? ` for <code>${esc(repo)}</code>` : ''}</h4>
103
- <ul>${items}</ul>
104
- </nav>`;
105
- }
106
-
107
- /** Styles for the block above, injected once so each Space need not carry them. */
108
- export function ensureNextStepStyles() {
109
- if (document.getElementById('ns-style')) return;
110
- const el = document.createElement('style');
111
- el.id = 'ns-style';
112
- el.textContent = `
113
- .nextsteps { margin: 1.6rem 0 0; padding-top: 1rem; border-top: 1px solid var(--line); }
114
- .nextsteps h4 { margin: 0 0 .5rem; font-size: .74rem; font-weight: 600;
115
- text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
116
- .nextsteps h4 code { text-transform: none; letter-spacing: 0; }
117
- .nextsteps ul { list-style: none; margin: 0; padding: 0; }
118
- .nextsteps li { margin: .3rem 0; font-size: .89rem; }
119
- .nextsteps a { color: var(--accent); text-decoration: none; }
120
- .nextsteps a:hover { text-decoration: underline; }
121
- .ns-why { color: var(--muted); }
122
- .ns-why::before { content: " "; }`;
123
- document.head.appendChild(el);
124
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * The five tools, declared once.
3
+ *
4
+ * Each Space linked to the others from its own footer, which meant the
5
+ * same five URLs written out in five files — twenty-five places for a
6
+ * rename to break, and a Space rename is invisible from the linking
7
+ * side: the link keeps returning a page, and the page is a 404.
8
+ *
9
+ * So the registry lives here and is copied into each Space at deploy
10
+ * time, next to `progress.js`. One file to change when a tool moves.
11
+ *
12
+ * The order is the order somebody actually needs them: find a model,
13
+ * see how much context it can serve, learn how to run it, then check
14
+ * what the pack really contains before spending the download.
15
+ */
16
+
17
+ export const TOOLS = {
18
+ search: {
19
+ space: 'model-search-that-answers',
20
+ title: 'Find a model that fits',
21
+ asks: 'which models fit my card at all',
22
+ // What the visitor has just learned, and why the next tool follows.
23
+ leadsTo: 'context',
24
+ takes: 'query',
25
+ },
26
+ context: {
27
+ space: 'what-context-fits',
28
+ title: 'What context will actually fit?',
29
+ asks: 'how long a conversation this one can serve',
30
+ leadsTo: 'parser',
31
+ takes: 'repo',
32
+ },
33
+ parser: {
34
+ space: 'reasoning-parser-advisor',
35
+ title: 'Does this model need a reasoning parser?',
36
+ asks: 'how to serve it without silently empty answers',
37
+ leadsTo: 'precision',
38
+ takes: 'repo',
39
+ },
40
+ precision: {
41
+ space: 'pack-precision-map',
42
+ title: 'How much of this pack is actually 4-bit?',
43
+ asks: 'what a quantized pack really compressed, and what it kept',
44
+ leadsTo: 'integrity',
45
+ takes: 'repo',
46
+ },
47
+ integrity: {
48
+ space: 'pack-integrity-check',
49
+ title: 'Does this pack keep what it claims?',
50
+ asks: 'whether anything was dropped or left undeclared',
51
+ leadsTo: null,
52
+ takes: 'repo',
53
+ },
54
+ };
55
+
56
+ export const ORDER = ['search', 'context', 'parser', 'precision', 'integrity'];
57
+
58
+ const BASE = 'https://huggingface.co/spaces/aleada';
59
+ const HUB = `${BASE}/start-here`;
60
+
61
+ /**
62
+ * A link to one tool, carrying the model with it.
63
+ *
64
+ * A funnel where each step starts empty is five separate tools with
65
+ * links between them. `?repo=` is read on load by every page that takes
66
+ * one, so clicking through keeps the model you were looking at.
67
+ */
68
+ export function url(key, repo = null) {
69
+ const t = TOOLS[key];
70
+ if (!t) return BASE;
71
+ const q = repo && t.takes === 'repo'
72
+ ? `?repo=${encodeURIComponent(repo)}`
73
+ : repo && t.takes === 'query'
74
+ ? `?q=${encodeURIComponent(repo)}` : '';
75
+ return `${BASE}/${t.space}${q}`;
76
+ }
77
+
78
+ /** The model this page was opened with, if a link carried one over. */
79
+ export function repoFromUrl() {
80
+ const p = new URLSearchParams(window.location.search);
81
+ return (p.get('repo') || p.get('q') || '').trim() || null;
82
+ }
83
+
84
+ const esc = (s) => String(s).replace(/[&<>"]/g, (c) =>
85
+ ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]));
86
+
87
+ /**
88
+ * The next questions, rendered under a result.
89
+ *
90
+ * The whole chain is rendered, not just the parts that come after: the
91
+ * current step is marked so a visitor who arrived from a link can see
92
+ * where they are, and the steps behind stay reachable because the order
93
+ * is a suggestion and not a gate.
94
+ *
95
+ * Offered only once there is an answer on screen — a next step shown
96
+ * before the current one is finished is clutter, and one that cannot
97
+ * carry the model over is a link to an empty form.
98
+ */
99
+ export function nextSteps(fromKey, repo = null) {
100
+ const here = ORDER.indexOf(fromKey);
101
+ const items = ORDER.map((k, i) => {
102
+ const t = TOOLS[k];
103
+ if (i === here) {
104
+ // The step you are on, shown rather than hidden. A list of "other
105
+ // tools" tells you what exists; a chain with your place marked
106
+ // tells you how far along you are, which is the thing somebody
107
+ // arriving from a link actually wants to know.
108
+ return `<li class="ns-here"><span class="ns-mark">✓</span>
109
+ <span class="ns-title">${esc(t.title)}</span>
110
+ <span class="ns-why">you are here</span></li>`;
111
+ }
112
+ const ahead = i > here;
113
+ return `<li class="${ahead ? 'ns-next' : 'ns-back'}">
114
+ <span class="ns-mark">${ahead ? '→' : '·'}</span>
115
+ <a href="${url(k, repo)}" target="_blank" rel="noopener">${esc(t.title)}</a>
116
+ <span class="ns-why">${esc(t.asks)}</span></li>`;
117
+ }).join('');
118
+
119
+ return `<nav class="nextsteps" aria-label="The rest of the chain">
120
+ <h4>Your next question${repo ? ` for <code>${esc(repo)}</code>` : ''}</h4>
121
+ <ul>${items}</ul>
122
+ <a class="ns-hub" href="${HUB}${repo ? `?repo=${encodeURIComponent(repo)}` : ''}"
123
+ target="_blank" rel="noopener">All five, and why they are in this order →</a>
124
+ </nav>`;
125
+ }
126
+
127
+ /** Styles for the block above, injected once so each Space need not carry them. */
128
+ export function ensureNextStepStyles() {
129
+ if (document.getElementById('ns-style')) return;
130
+ const el = document.createElement('style');
131
+ el.id = 'ns-style';
132
+ el.textContent = `
133
+ .nextsteps { margin: 1.6rem 0 0; padding-top: 1rem; border-top: 1px solid var(--line); }
134
+ .nextsteps h4 { margin: 0 0 .5rem; font-size: .74rem; font-weight: 600;
135
+ text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
136
+ .nextsteps h4 code { text-transform: none; letter-spacing: 0; }
137
+ .nextsteps ul { list-style: none; margin: 0; padding: 0; }
138
+ .nextsteps li { margin: .32rem 0; font-size: .89rem; display: flex;
139
+ gap: .5rem; align-items: baseline; }
140
+ .ns-mark { font-family: var(--mono); font-size: .8rem; color: var(--muted);
141
+ width: 1rem; flex: 0 0 1rem; }
142
+ .ns-here .ns-mark { color: var(--accent); }
143
+ .ns-here .ns-title { font-weight: 600; }
144
+ .ns-back { opacity: .72; }
145
+ .ns-hub { display: inline-block; margin-top: .7rem; font-size: .84rem; }
146
+ .nextsteps a { color: var(--accent); text-decoration: none; }
147
+ .nextsteps a:hover { text-decoration: underline; }
148
+ .ns-why { color: var(--muted); }
149
+ .ns-why::before { content: " — "; }`;
150
+ document.head.appendChild(el);
151
+ }