PeterPinetree commited on
Commit
212e389
·
1 Parent(s): afa3fe8

Update index.html

Browse files

Fix Qwen3 load error by forcing Transformers.js to use Qwen2 class

- Switched Qwen3-0.6B to remote-only (onnx-community/Qwen3-0.6B-ONNX)
- Added config override (model_type=qwen2, Qwen2ForCausalLM) to bypass
"Unsupported model type: qwen3" error

Files changed (1) hide show
  1. index.html +55 -38
index.html CHANGED
@@ -10,7 +10,7 @@
10
  header { position:sticky; top:0; z-index:5; display:flex; gap:12px; align-items:center; padding:12px 16px; background:#0e1629; border-bottom:1px solid #1c2945; }
11
  h1 { font-size:16px; font-weight:600; margin:0; letter-spacing:.2px; }
12
  main { padding:14px; }
13
- .grid { display:grid; gap:14px; grid-template-columns: 0.35fr 0.65fr; }
14
  @media (max-width: 1000px){ .grid { grid-template-columns:1fr; } }
15
 
16
  .card { background:#0e162b; border:1px solid #1c2945; border-radius:14px; padding:12px; }
@@ -40,7 +40,7 @@
40
  .small { font-size:12px; }
41
  </style>
42
 
43
- <!-- Transformers.js for browsers (CDN). The npm snippet in your screenshot is for bundlers; this is correct for Spaces. -->
44
  <script type="module">
45
  import {
46
  env,
@@ -68,7 +68,7 @@
68
  <div class="inline">
69
  <span class="muted small">Model:</span>
70
  <select id="model" class="select">
71
- <option value="qwen" selected>Qwen3-0.6B (local int8 → Hub fallback)</option>
72
  <option value="distilgpt2">distilgpt2 (local → Hub fallback)</option>
73
  </select>
74
  </div>
@@ -116,14 +116,14 @@
116
  <script type="module">
117
  const { env, AutoTokenizer, AutoModelForCausalLM } = window.HF;
118
 
119
- // Env tuning
120
  env.useBrowserCache = true;
121
  env.backends.onnx.wasm.proxy = true;
122
  env.backends.onnx.wasm.numThreads = Math.min(
123
  4, Math.max(1, Math.floor((navigator.hardwareConcurrency || 4)/2))
124
  );
125
 
126
- // DOM
127
  const $ = (s) => document.querySelector(s);
128
  const statusEl = $('#status'), barEl = $('#bar'), errEl = $('#error');
129
  const textEl = $('#text'), klistEl = $('#klist'), timeEl = $('#time');
@@ -132,6 +132,7 @@
132
  const embCanvas = $('#embCanvas'), embCtx = embCanvas.getContext('2d');
133
  const embStatus = $('#embStatus');
134
 
 
135
  function setStatus(t){ if(statusEl) statusEl.textContent = t; }
136
  function onProgress(evt){
137
  if (!barEl) return;
@@ -148,38 +149,36 @@
148
  function showToken(s){ if (s === "\n") return "⏎"; if (s.trim() === "") return `␣${s.length>1 ? "×"+s.length : ""}`; return s; }
149
  const PUNC_ONLY = /^[\s.,;:!?—-]+$/;
150
 
151
- // IMPORTANT: force same-origin absolute URLs for "local" to avoid CORS/404
152
- const LOCAL = (p) => new URL(p, window.location.href).href;
153
-
154
  const MODELS = {
155
  qwen: {
156
  remote: "onnx-community/Qwen3-0.6B-ONNX",
157
  dtype: "int8",
158
  emb: {
159
- coords: LOCAL("./assets/embeddings/qwen_pca_top5k_coords.json"),
160
- nbrs: LOCAL("./assets/embeddings/qwen_neighbors_top5k_k40.json")
161
  }
162
  },
163
  distilgpt2: {
164
- local: LOCAL("./assets/models/distilgpt2/"),
165
  remote: "Xenova/distilgpt2",
166
  dtype: undefined,
167
  emb: {
168
- coords: LOCAL("./assets/embeddings/pca_top5k_coords.json"),
169
- nbrs: LOCAL("./assets/embeddings/neighbors_top5k_k40.json")
170
  }
171
  }
172
  };
173
 
174
- // Embedding viewer
175
  const Emb = (() => {
176
  let coordsPath = "", nbrsPath = "";
177
  let points = [], index = new Map(), neighbors = new Map();
178
  let baseDrawn = false;
179
 
180
  function setSources(modelKey){
181
- coordsPath = MODELS.modelKey ? MODELS.modelKey.emb.coords : MODELS[modelKey].emb.coords;
182
- nbrsPath = MODELS.modelKey ? MODELS.modelKey.emb.nbrs : MODELS[modelKey].emb.nbrs;
183
  }
184
  async function load(){
185
  baseDrawn = false; index.clear(); points = []; neighbors.clear();
@@ -209,34 +208,51 @@
209
  return { setSources, load, drawBase, highlight };
210
  })();
211
 
212
- // Model state
213
  let tokenizer=null, model=null;
214
 
 
 
 
 
 
 
215
  async function loadModel(key){
216
  const cfg = MODELS[key];
217
 
 
218
  Emb.setSources(key);
219
  try { await Emb.load(); } catch { embStatus.textContent = "Map failed to load"; }
220
 
221
- setErr(""); setStatus("Loading tokenizer…"); barEl.style.width = "0%";
222
- try {
223
- tokenizer = await AutoTokenizer.from_pretrained(MODELS.qwen.remote, { progress_callback: onProgress });
224
- } catch (e1) {
225
- console.warn("Local tokenizer failed; falling back to Hub", e1);
226
- tokenizer = await AutoTokenizer.from_pretrained(cfg.remote, { progress_callback: onProgress });
227
- }
228
 
229
- setStatus("Loading model…");
230
- try {
231
- model = await AutoModelForCausalLM.from_pretrained(MODELS.qwen.remote, { dtype: cfg.dtype, progress_callback: onProgress });
232
- } catch (e2) {
233
- console.warn("Local model failed; falling back to Hub", e2);
234
- model = await AutoModelForCausalLM.from_pretrained(MODELS.qwen.remote, { dtype: cfg.dtype, progress_callback: onProgress });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  }
236
 
237
- if (!tokenizer || !model) {MODELS.qwen.remote,
238
  setStatus("Load failed");
239
- setErr("Couldn’t load model. Check config.json (model_type) and local paths.");
240
  return;
241
  }
242
 
@@ -246,8 +262,9 @@
246
  setStatus("Ready");
247
  }
248
 
 
249
  async function greedyNext(text, topK=10){
250
- if (!tokenizer || !model) { setErr("Model not loaded yet — check the status bar for load errors."); return {rows:[],dt:0}; }
251
  const enc = await tokenizer(text || " ", { add_special_tokens:false });
252
  const t0 = performance.now();
253
  const out = await model(enc.input_ids, { attention_mask: enc.attention_mask });
@@ -269,8 +286,8 @@
269
  }
270
 
271
  function renderRows(rows){
272
- klistEl.innerHTML = "";
273
  const hide = hidePunc.checked;
 
274
  for (const r of rows){
275
  if (hide && PUNC_ONLY.test(r.token)) continue;
276
  const row = document.createElement('div'); row.className='tokrow';
@@ -297,7 +314,7 @@
297
  }
298
  }
299
 
300
- // UI
301
  predictBtn.addEventListener('click', predict);
302
  textEl.addEventListener('input', (() => { let to; return () => { clearTimeout(to); to = setTimeout(predict, 250); }; })());
303
  hidePunc.addEventListener('change', predict);
@@ -305,12 +322,12 @@
305
  demoBtn.addEventListener('click', () => { textEl.value = "Twinkle, twinkle, little "; predict(); });
306
  modelSel.addEventListener('change', async (e) => { await loadModel(e.target.value); predict(); });
307
 
308
- // Boot
309
  (async function init(){
310
- await loadModel(modelSel.value); // defaults to 'qwen'
311
  if (!textEl.value) textEl.value = "Twinkle, twinkle, little ";
312
  await predict();
313
  })();
314
  </script>
315
  </body>
316
- </html>
 
10
  header { position:sticky; top:0; z-index:5; display:flex; gap:12px; align-items:center; padding:12px 16px; background:#0e1629; border-bottom:1px solid #1c2945; }
11
  h1 { font-size:16px; font-weight:600; margin:0; letter-spacing:.2px; }
12
  main { padding:14px; }
13
+ .grid { display:grid; gap:14px; grid-template-columns: 0.35fr 0.65fr; } /* fixed 'fr' spacing */
14
  @media (max-width: 1000px){ .grid { grid-template-columns:1fr; } }
15
 
16
  .card { background:#0e162b; border:1px solid #1c2945; border-radius:14px; padding:12px; }
 
40
  .small { font-size:12px; }
41
  </style>
42
 
43
+ <!-- Transformers.js for browsers (CDN). The npm snippet is for bundlers; this is correct for Spaces. -->
44
  <script type="module">
45
  import {
46
  env,
 
68
  <div class="inline">
69
  <span class="muted small">Model:</span>
70
  <select id="model" class="select">
71
+ <option value="qwen" selected>Qwen3-0.6B (Hub, int8)</option>
72
  <option value="distilgpt2">distilgpt2 (local → Hub fallback)</option>
73
  </select>
74
  </div>
 
116
  <script type="module">
117
  const { env, AutoTokenizer, AutoModelForCausalLM } = window.HF;
118
 
119
+ /* ---------- Environment tuning ---------- */
120
  env.useBrowserCache = true;
121
  env.backends.onnx.wasm.proxy = true;
122
  env.backends.onnx.wasm.numThreads = Math.min(
123
  4, Math.max(1, Math.floor((navigator.hardwareConcurrency || 4)/2))
124
  );
125
 
126
+ /* ---------- DOM ---------- */
127
  const $ = (s) => document.querySelector(s);
128
  const statusEl = $('#status'), barEl = $('#bar'), errEl = $('#error');
129
  const textEl = $('#text'), klistEl = $('#klist'), timeEl = $('#time');
 
132
  const embCanvas = $('#embCanvas'), embCtx = embCanvas.getContext('2d');
133
  const embStatus = $('#embStatus');
134
 
135
+ /* ---------- Progress ---------- */
136
  function setStatus(t){ if(statusEl) statusEl.textContent = t; }
137
  function onProgress(evt){
138
  if (!barEl) return;
 
149
  function showToken(s){ if (s === "\n") return "⏎"; if (s.trim() === "") return `␣${s.length>1 ? "×"+s.length : ""}`; return s; }
150
  const PUNC_ONLY = /^[\s.,;:!?—-]+$/;
151
 
152
+ /* ---------- Model registry (Qwen = remote-only) ---------- */
 
 
153
  const MODELS = {
154
  qwen: {
155
  remote: "onnx-community/Qwen3-0.6B-ONNX",
156
  dtype: "int8",
157
  emb: {
158
+ coords: "assets/embeddings/qwen_pca_top5k_coords.json",
159
+ nbrs: "assets/embeddings/qwen_neighbors_top5k_k40.json"
160
  }
161
  },
162
  distilgpt2: {
163
+ local: new URL("./assets/models/distilgpt2/", window.location.href).href,
164
  remote: "Xenova/distilgpt2",
165
  dtype: undefined,
166
  emb: {
167
+ coords: "assets/embeddings/pca_top5k_coords.json",
168
+ nbrs: "assets/embeddings/neighbors_top5k_k40.json"
169
  }
170
  }
171
  };
172
 
173
+ /* ---------- Embedding viewer ---------- */
174
  const Emb = (() => {
175
  let coordsPath = "", nbrsPath = "";
176
  let points = [], index = new Map(), neighbors = new Map();
177
  let baseDrawn = false;
178
 
179
  function setSources(modelKey){
180
+ coordsPath = MODELS[modelKey].emb.coords;
181
+ nbrsPath = MODELS[modelKey].emb.nbrs;
182
  }
183
  async function load(){
184
  baseDrawn = false; index.clear(); points = []; neighbors.clear();
 
208
  return { setSources, load, drawBase, highlight };
209
  })();
210
 
211
+ /* ---------- Core model state ---------- */
212
  let tokenizer=null, model=null;
213
 
214
+ // Small config shim: tell Transformers.js to treat Qwen3 as Qwen2
215
+ const QWEN3_CONFIG_FIX = {
216
+ model_type: "qwen2",
217
+ architectures: ["Qwen2ForCausalLM"]
218
+ };
219
+
220
  async function loadModel(key){
221
  const cfg = MODELS[key];
222
 
223
+ // Load embeddings for this model
224
  Emb.setSources(key);
225
  try { await Emb.load(); } catch { embStatus.textContent = "Map failed to load"; }
226
 
227
+ setErr(""); setStatus("Loading tokenizer…"); if (barEl) barEl.style.width = "0%";
 
 
 
 
 
 
228
 
229
+ if (key === "qwen") {
230
+ // --- Remote-only for Qwen (Hub) ---
231
+ tokenizer = await AutoTokenizer.from_pretrained(cfg.remote, { progress_callback: onProgress });
232
+ setStatus("Loading model…");
233
+ model = await AutoModelForCausalLM.from_pretrained(cfg.remote, {
234
+ dtype: cfg.dtype,
235
+ progress_callback: onProgress,
236
+ config: QWEN3_CONFIG_FIX // <-- the crucial override
237
+ });
238
+ } else {
239
+ // --- distilgpt2: prefer local, fallback to Hub ---
240
+ try {
241
+ tokenizer = await AutoTokenizer.from_pretrained(cfg.local, { progress_callback: onProgress });
242
+ } catch {
243
+ tokenizer = await AutoTokenizer.from_pretrained(cfg.remote, { progress_callback: onProgress });
244
+ }
245
+ setStatus("Loading model…");
246
+ try {
247
+ model = await AutoModelForCausalLM.from_pretrained(cfg.local, { dtype: cfg.dtype, progress_callback: onProgress });
248
+ } catch {
249
+ model = await AutoModelForCausalLM.from_pretrained(cfg.remote, { dtype: cfg.dtype, progress_callback: onProgress });
250
+ }
251
  }
252
 
253
+ if (!tokenizer || !model) {
254
  setStatus("Load failed");
255
+ setErr("Couldn’t load model. Check console for details.");
256
  return;
257
  }
258
 
 
262
  setStatus("Ready");
263
  }
264
 
265
+ /* ---------- Next-token logic ---------- */
266
  async function greedyNext(text, topK=10){
267
+ if (!tokenizer || !model) { setErr("Model not loaded yet — check the status bar."); return {rows:[],dt:0}; }
268
  const enc = await tokenizer(text || " ", { add_special_tokens:false });
269
  const t0 = performance.now();
270
  const out = await model(enc.input_ids, { attention_mask: enc.attention_mask });
 
286
  }
287
 
288
  function renderRows(rows){
 
289
  const hide = hidePunc.checked;
290
+ klistEl.innerHTML = "";
291
  for (const r of rows){
292
  if (hide && PUNC_ONLY.test(r.token)) continue;
293
  const row = document.createElement('div'); row.className='tokrow';
 
314
  }
315
  }
316
 
317
+ /* ---------- UI ---------- */
318
  predictBtn.addEventListener('click', predict);
319
  textEl.addEventListener('input', (() => { let to; return () => { clearTimeout(to); to = setTimeout(predict, 250); }; })());
320
  hidePunc.addEventListener('change', predict);
 
322
  demoBtn.addEventListener('click', () => { textEl.value = "Twinkle, twinkle, little "; predict(); });
323
  modelSel.addEventListener('change', async (e) => { await loadModel(e.target.value); predict(); });
324
 
325
+ /* ---------- Boot ---------- */
326
  (async function init(){
327
+ await loadModel(modelSel.value); // defaults to 'qwen' (remote-only + config override)
328
  if (!textEl.value) textEl.value = "Twinkle, twinkle, little ";
329
  await predict();
330
  })();
331
  </script>
332
  </body>
333
+ </html>