blessingmwiti commited on
Commit
92f6062
·
1 Parent(s): 0df684e

Improve WebGPU model load fallback

Browse files
Files changed (2) hide show
  1. app.py +19 -3
  2. static/engine.js +37 -6
app.py CHANGED
@@ -67,6 +67,17 @@ custom_html = f"""
67
  const warning = document.getElementById("webgpu-warning");
68
  const loadButton = document.getElementById("load-btn");
69
 
 
 
 
 
 
 
 
 
 
 
 
70
  function findGradioInput(id) {{
71
  const root = document.getElementById(id);
72
  if (!root) return null;
@@ -92,19 +103,24 @@ window.initEngine = async function() {{
92
  document.getElementById("load-status").textContent = "Loading model weights...";
93
  try {{
94
  await loadModel((progress) => {{
 
 
 
 
95
  const value = progress.progress ? Math.round(progress.progress) : 0;
96
  document.getElementById("load-progress").style.width = `${{value}}%`;
97
  if (progress.file) {{
98
- document.getElementById("load-status").textContent = `${{progress.file}} - ${{value}}%`;
99
  }}
100
  }});
101
  document.getElementById("load-progress").style.width = "100%";
102
- document.getElementById("load-status").textContent = "Model ready - WebGPU active";
103
  document.getElementById("load-section").classList.add("loaded");
104
  setStatus("Ready", "success");
105
  }} catch (error) {{
 
106
  loadButton.disabled = false;
107
- setStatus(`Model load failed: ${{error.message}}`, "warning");
108
  document.getElementById("load-status").textContent = "Load failed";
109
  }}
110
  }};
 
67
  const warning = document.getElementById("webgpu-warning");
68
  const loadButton = document.getElementById("load-btn");
69
 
70
+ function formatBrowserError(error) {{
71
+ if (!error) return "unknown error";
72
+ if (error.message) return error.message;
73
+ if (typeof error === "string") return error;
74
+ try {{
75
+ return JSON.stringify(error);
76
+ }} catch (_err) {{
77
+ return String(error);
78
+ }}
79
+ }}
80
+
81
  function findGradioInput(id) {{
82
  const root = document.getElementById(id);
83
  if (!root) return null;
 
103
  document.getElementById("load-status").textContent = "Loading model weights...";
104
  try {{
105
  await loadModel((progress) => {{
106
+ if (progress.status === "attempt") {{
107
+ document.getElementById("load-status").textContent = `Trying ${{progress.dtype}} WebGPU weights...`;
108
+ return;
109
+ }}
110
  const value = progress.progress ? Math.round(progress.progress) : 0;
111
  document.getElementById("load-progress").style.width = `${{value}}%`;
112
  if (progress.file) {{
113
+ document.getElementById("load-status").textContent = `${{progress.file}} (${{progress.dtype || "auto"}}) - ${{value}}%`;
114
  }}
115
  }});
116
  document.getElementById("load-progress").style.width = "100%";
117
+ document.getElementById("load-status").textContent = `Model ready - WebGPU active (${{getActiveDtype() || "auto"}})`;
118
  document.getElementById("load-section").classList.add("loaded");
119
  setStatus("Ready", "success");
120
  }} catch (error) {{
121
+ console.error("Model load failed", error);
122
  loadButton.disabled = false;
123
+ setStatus(`Model load failed: ${{formatBrowserError(error)}}`, "warning");
124
  document.getElementById("load-status").textContent = "Load failed";
125
  }}
126
  }};
static/engine.js CHANGED
@@ -1,19 +1,34 @@
1
  import { pipeline, TextStreamer } from "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.5.0/dist/transformers.min.js";
2
 
3
  const MODEL_ID = "onnx-community/Qwen2.5-Coder-1.5B-Instruct";
 
4
 
5
  let generator = null;
6
  let isLoaded = false;
 
7
 
8
  export async function loadModel(onProgress) {
9
  if (isLoaded) return;
10
 
11
- generator = await pipeline("text-generation", MODEL_ID, {
12
- dtype: "q4",
13
- device: "webgpu",
14
- progress_callback: onProgress,
15
- });
16
- isLoaded = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
  export async function generateCode(prompt, language, onToken, onComplete) {
@@ -51,8 +66,24 @@ export function isWebGPUSupported() {
51
  return Boolean(navigator.gpu);
52
  }
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  Object.assign(window, {
55
  loadModel,
56
  generateCode,
57
  isWebGPUSupported,
 
58
  });
 
1
  import { pipeline, TextStreamer } from "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.5.0/dist/transformers.min.js";
2
 
3
  const MODEL_ID = "onnx-community/Qwen2.5-Coder-1.5B-Instruct";
4
+ const DTYPE_CANDIDATES = ["q4f16", "q4", "fp16"];
5
 
6
  let generator = null;
7
  let isLoaded = false;
8
+ let activeDtype = null;
9
 
10
  export async function loadModel(onProgress) {
11
  if (isLoaded) return;
12
 
13
+ const errors = [];
14
+ for (const dtype of DTYPE_CANDIDATES) {
15
+ try {
16
+ onProgress?.({ status: "attempt", dtype });
17
+ generator = await pipeline("text-generation", MODEL_ID, {
18
+ dtype,
19
+ device: "webgpu",
20
+ progress_callback: (progress) => onProgress?.({ ...progress, dtype }),
21
+ });
22
+ activeDtype = dtype;
23
+ isLoaded = true;
24
+ return;
25
+ } catch (error) {
26
+ console.error(`Model load failed for dtype=${dtype}`, error);
27
+ errors.push(`${dtype}: ${formatError(error)}`);
28
+ }
29
+ }
30
+
31
+ throw new Error(`All WebGPU dtype attempts failed. ${errors.join(" | ")}`);
32
  }
33
 
34
  export async function generateCode(prompt, language, onToken, onComplete) {
 
66
  return Boolean(navigator.gpu);
67
  }
68
 
69
+ export function getActiveDtype() {
70
+ return activeDtype;
71
+ }
72
+
73
+ function formatError(error) {
74
+ if (!error) return "unknown error";
75
+ if (error.message) return error.message;
76
+ if (typeof error === "string") return error;
77
+ try {
78
+ return JSON.stringify(error);
79
+ } catch {
80
+ return String(error);
81
+ }
82
+ }
83
+
84
  Object.assign(window, {
85
  loadModel,
86
  generateCode,
87
  isWebGPUSupported,
88
+ getActiveDtype,
89
  });