tinkersnot commited on
Commit
b2cf8ef
·
verified ·
1 Parent(s): 06513ff

Upload spike-qwen2b.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. spike-qwen2b.html +21 -4
spike-qwen2b.html CHANGED
@@ -28,8 +28,13 @@ const log = (m) => { $("log").textContent += m + "\n"; $("log").scrollTop = 1e9;
28
  const esc = (s) => String(s).replace(/[&<>]/g, (c) => ({ "&":"&amp;","<":"&lt;",">":"&gt;" }[c]));
29
  // Official web-llm prebuilts (web-llm resolves weights+wasm from its own config).
30
  // ?model=2b|4b selects the tier — 4B is the reasoner half of the 0.8B/4B pairing.
31
- const MODELS = { "2b": "Qwen3.5-2B-q4f16_1-MLC", "4b": "Qwen3.5-4B-q4f16_1-MLC" };
32
- const MODEL_ID = MODELS[new URLSearchParams(location.search).get("model")] || MODELS["2b"];
 
 
 
 
 
33
  document.getElementById("h1").textContent = `${MODEL_ID} — browser WebGPU check`;
34
 
35
  // Qwen3.5 native tool-call format (XML). Parse both the native <function=…> and
@@ -117,8 +122,18 @@ async function main() {
117
  const t0 = performance.now();
118
  log(`loading ${MODEL_ID} (first run downloads to browser cache: ~1.3GB for 2B, ~2.5GB for 4B)…`);
119
  let engine;
 
120
  try {
121
- engine = await webllm.CreateMLCEngine(MODEL_ID, { initProgressCallback: (p) => { $("env").innerHTML = `<span class="warn">loading… ${(p.progress*100|0)}%</span> ${esc(p.text||"")}`; } });
 
 
 
 
 
 
 
 
 
122
  } catch (e) { $("env").innerHTML = `<span class="bad">✗ load failed:</span> ${esc(e.message)}`; log("LOAD ERROR: " + e.message); return; }
123
  const loadMs = performance.now() - t0;
124
  $("env").innerHTML = `<span class="ok">✓ model loaded</span> in ${(loadMs/1000).toFixed(1)}s`;
@@ -129,7 +144,9 @@ async function main() {
129
  let res, text = "", toolCalls = null;
130
  try {
131
  const prompt = renderQwen(test.system, test.user, test.withTools);
132
- res = await engine.completions.create({ prompt, ...SAMP, max_tokens: THINK ? 900 : 640, stream: false, stop: ["<|im_end|>"] });
 
 
133
  text = (THINK ? "<think>\n" : "") + (res.choices?.[0]?.text || "");
134
  } catch (e) { text = "[ERROR] " + e.message; }
135
  const ms = performance.now() - c0;
 
28
  const esc = (s) => String(s).replace(/[&<>]/g, (c) => ({ "&":"&amp;","<":"&lt;",">":"&gt;" }[c]));
29
  // Official web-llm prebuilts (web-llm resolves weights+wasm from its own config).
30
  // ?model=2b|4b selects the tier — 4B is the reasoner half of the 0.8B/4B pairing.
31
+ const MODELS = { "2b": "Qwen3.5-2B-q4f16_1-MLC", "4b": "Qwen3.5-4B-q4f16_1-MLC",
32
+ // khazarai = our OWN q4f16 conversion (weights-only); reuses web-llm's vanilla
33
+ // Qwen3.5-2B wasm (same arch) at load time — see the appConfig branch below.
34
+ "khazarai": "khazarai-2b-q4f16-MLC" };
35
+ const MODEL_KEY = new URLSearchParams(location.search).get("model") || "2b";
36
+ const MODEL_ID = MODELS[MODEL_KEY] || MODELS["2b"];
37
+ const KHAZARAI_WEIGHTS = "https://huggingface.co/tinkersnot/qwen3.5-2b-khazarai-q4f16-MLC/resolve/main";
38
  document.getElementById("h1").textContent = `${MODEL_ID} — browser WebGPU check`;
39
 
40
  // Qwen3.5 native tool-call format (XML). Parse both the native <function=…> and
 
122
  const t0 = performance.now();
123
  log(`loading ${MODEL_ID} (first run downloads to browser cache: ~1.3GB for 2B, ~2.5GB for 4B)…`);
124
  let engine;
125
+ const onprog = (p) => { $("env").innerHTML = `<span class="warn">loading… ${(p.progress*100|0)}%</span> ${esc(p.text||"")}`; };
126
  try {
127
+ if (MODEL_KEY === "khazarai") {
128
+ // Custom appConfig: our khazarai weights + web-llm's OWN vanilla Qwen3.5-2B
129
+ // model_lib (wasm) — weight-independent for the identical qwen3_5 arch.
130
+ const vanilla = webllm.prebuiltAppConfig.model_list.find((m) => m.model_id === "Qwen3.5-2B-q4f16_1-MLC");
131
+ if (!vanilla) throw new Error("vanilla Qwen3.5-2B not in web-llm prebuilt config (can't borrow wasm)");
132
+ const appConfig = { model_list: [{ model: KHAZARAI_WEIGHTS, model_id: MODEL_ID, model_lib: vanilla.model_lib }] };
133
+ engine = await webllm.CreateMLCEngine(MODEL_ID, { appConfig, initProgressCallback: onprog });
134
+ } else {
135
+ engine = await webllm.CreateMLCEngine(MODEL_ID, { initProgressCallback: onprog });
136
+ }
137
  } catch (e) { $("env").innerHTML = `<span class="bad">✗ load failed:</span> ${esc(e.message)}`; log("LOAD ERROR: " + e.message); return; }
138
  const loadMs = performance.now() - t0;
139
  $("env").innerHTML = `<span class="ok">✓ model loaded</span> in ${(loadMs/1000).toFixed(1)}s`;
 
144
  let res, text = "", toolCalls = null;
145
  try {
146
  const prompt = renderQwen(test.system, test.user, test.withTools);
147
+ // khazarai artifact is ctx=1024 cap gen budget so prompt+gen fits (it converges well under this).
148
+ const maxTok = MODEL_KEY === "khazarai" ? (THINK ? 720 : 480) : (THINK ? 900 : 640);
149
+ res = await engine.completions.create({ prompt, ...SAMP, max_tokens: maxTok, stream: false, stop: ["<|im_end|>"] });
150
  text = (THINK ? "<think>\n" : "") + (res.choices?.[0]?.text || "");
151
  } catch (e) { text = "[ERROR] " + e.message; }
152
  const ms = performance.now() - c0;