Xenobd commited on
Commit
f3b6176
·
verified ·
1 Parent(s): 82534fe

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +63 -76
index.html CHANGED
@@ -2,61 +2,83 @@
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
- <title>ONNX WebGPU Streaming Text Generation</title>
6
  <script type="module">
7
  import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]/dist/transformers.min.js';
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  async function runPrompt(prompt) {
 
 
 
 
 
 
 
 
 
 
10
 
11
- console.log("%cInitializing pipeline...", "color: orange; font-weight: bold;");
 
 
 
 
12
 
 
 
 
 
 
13
  const generator = await pipeline(
14
  "text-generation",
15
  "onnx-community/gemma-3-1b-it-ONNX",
16
- {
17
- dtype: "q4",
18
- providers: ["webgpu"]
19
- }
20
  );
 
21
 
22
- console.log("%cPipeline ready. Generating text...", "color: green; font-weight: bold;");
23
-
24
  const messages = [
25
  { role: "system", content: "You are a helpful assistant." },
26
  { role: "user", content: prompt },
27
  ];
28
 
29
- const progressBar = document.getElementById("progress");
30
- const progressText = document.getElementById("progressText");
31
- let progress = 0;
32
-
33
- // simulate initial download-like progress
34
- const interval = setInterval(() => {
35
- if(progress < 95) {
36
- progress += Math.random() * 5; // random increment
37
- progressBar.style.width = progress + "%";
38
- progressText.textContent = Math.floor(progress) + "%";
39
- }
40
- }, 100);
41
-
42
- const outputElem = document.getElementById("output");
43
- outputElem.textContent = "";
44
 
45
- // streaming generator
46
- for await (const token of generator.stream(messages, { max_new_tokens: 512, do_sample: false })) {
47
  outputElem.textContent += token.content;
48
  outputElem.scrollTop = outputElem.scrollHeight;
49
 
50
- // update progress bar based on token count (optional)
51
- const tokenProgress = Math.min(95, outputElem.textContent.length / 5); // adjust divisor for speed
52
- if(tokenProgress > progress) {
53
- progress = tokenProgress;
54
- progressBar.style.width = progress + "%";
55
- progressText.textContent = Math.floor(progress) + "%";
56
- }
57
  }
58
 
59
- clearInterval(interval);
60
  progressBar.style.width = "100%";
61
  progressText.textContent = "100%";
62
  console.log("%cGeneration complete!", "color: blue; font-weight: bold;");
@@ -67,69 +89,34 @@ window.onload = () => {
67
  form.onsubmit = (e) => {
68
  e.preventDefault();
69
  const prompt = document.getElementById("promptInput").value;
70
- document.getElementById("output").textContent = "Generating...\n";
71
- document.getElementById("progress").style.width = "0%";
72
- document.getElementById("progressText").textContent = "0%";
73
  runPrompt(prompt);
74
  }
75
  };
76
  </script>
77
  <style>
78
- body {
79
- font-family: 'Segoe UI', sans-serif;
80
- background: #1e1e2f;
81
- color: #f0f0f0;
82
- display: flex;
83
- flex-direction: column;
84
- align-items: center;
85
- padding: 2rem;
86
- }
87
  h1 { color: #ffcc00; margin-bottom: 1rem; }
88
  #promptForm { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
89
- #promptInput {
90
- padding: 0.5rem; width: 400px;
91
- border-radius: 5px; border: none; font-size: 1rem;
92
- }
93
- #generateBtn {
94
- padding: 0.5rem 1rem; background: #ffcc00;
95
- border: none; border-radius: 5px;
96
- font-weight: bold; cursor: pointer; color: #1e1e2f;
97
- }
98
  #generateBtn:hover { background: #ffdd33; }
99
- #progressContainer {
100
- width: 400px; height: 20px; background: #333;
101
- border-radius: 5px; overflow: hidden; margin-bottom: 1rem; position: relative;
102
- }
103
- #progress {
104
- width: 0%; height: 100%;
105
- background: #ffcc00; transition: width 0.1s;
106
- }
107
- #progressText {
108
- position: absolute; right: 10px; top: 0; bottom: 0;
109
- display: flex; align-items: center; justify-content: flex-end;
110
- font-size: 0.8rem; color: #1e1e2f; font-weight: bold;
111
- }
112
- pre#output {
113
- width: 400px; background: #2e2e44;
114
- padding: 1rem; border-radius: 8px;
115
- white-space: pre-wrap; word-wrap: break-word;
116
- min-height: 150px; overflow-y: auto;
117
- }
118
  </style>
119
  </head>
120
  <body>
121
  <h1>ONNX WebGPU Streaming Text Generation</h1>
122
-
123
  <form id="promptForm">
124
  <input id="promptInput" type="text" placeholder="Type your prompt..." required />
125
  <button id="generateBtn">Generate</button>
126
  </form>
127
-
128
  <div id="progressContainer">
129
  <div id="progress"></div>
130
  <div id="progressText">0%</div>
131
  </div>
132
-
133
  <pre id="output">Enter a prompt and hit Generate...</pre>
134
  </body>
135
  </html>
 
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
+ <title>ONNX WebGPU Download & Streaming Text Generation</title>
6
  <script type="module">
7
  import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]/dist/transformers.min.js';
8
 
9
+ // Helper: download a file with progress
10
+ async function downloadWithProgress(url, onProgress) {
11
+ const response = await fetch(url);
12
+ if (!response.ok) throw new Error("Network response was not ok");
13
+
14
+ const contentLength = +response.headers.get("Content-Length");
15
+ if (!contentLength) throw new Error("Content-Length header missing");
16
+
17
+ const reader = response.body.getReader();
18
+ let received = 0;
19
+ const chunks = [];
20
+
21
+ while(true) {
22
+ const { done, value } = await reader.read();
23
+ if (done) break;
24
+ chunks.push(value);
25
+ received += value.length;
26
+ onProgress(received / contentLength);
27
+ }
28
+
29
+ const blob = new Blob(chunks);
30
+ return blob;
31
+ }
32
+
33
  async function runPrompt(prompt) {
34
+ const progressBar = document.getElementById("progress");
35
+ const progressText = document.getElementById("progressText");
36
+ const outputElem = document.getElementById("output");
37
+
38
+ // 1️⃣ Download model ONNX file manually
39
+ const modelUrl = "https://huggingface.co/onnx-community/gemma-3-1b-it-ONNX/resolve/main/gemma-3-1b-it-quant.onnx"; // example file
40
+ console.log("%cDownloading model...", "color: orange; font-weight: bold;");
41
+ outputElem.textContent = "Downloading model...\n";
42
+ progressBar.style.width = "0%";
43
+ progressText.textContent = "0%";
44
 
45
+ await downloadWithProgress(modelUrl, (ratio) => {
46
+ const pct = Math.floor(ratio * 100);
47
+ progressBar.style.width = pct + "%";
48
+ progressText.textContent = pct + "%";
49
+ });
50
 
51
+ console.log("%cModel downloaded!", "color: green; font-weight: bold;");
52
+ outputElem.textContent += "Model downloaded.\n";
53
+
54
+ // 2️⃣ Initialize generator using WebGPU
55
+ outputElem.textContent += "Initializing pipeline...\n";
56
  const generator = await pipeline(
57
  "text-generation",
58
  "onnx-community/gemma-3-1b-it-ONNX",
59
+ { dtype: "q4", providers: ["webgpu"] }
 
 
 
60
  );
61
+ outputElem.textContent += "Pipeline ready. Generating text...\n";
62
 
63
+ // 3️⃣ Stream output
 
64
  const messages = [
65
  { role: "system", content: "You are a helpful assistant." },
66
  { role: "user", content: prompt },
67
  ];
68
 
69
+ let generatedTokens = 0;
70
+ const maxTokens = 512;
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
+ for await (const token of generator.stream(messages, { max_new_tokens: maxTokens, do_sample: false })) {
 
73
  outputElem.textContent += token.content;
74
  outputElem.scrollTop = outputElem.scrollHeight;
75
 
76
+ generatedTokens++;
77
+ const progress = Math.min((generatedTokens / maxTokens) * 100, 100);
78
+ progressBar.style.width = progress + "%";
79
+ progressText.textContent = Math.floor(progress) + "%";
 
 
 
80
  }
81
 
 
82
  progressBar.style.width = "100%";
83
  progressText.textContent = "100%";
84
  console.log("%cGeneration complete!", "color: blue; font-weight: bold;");
 
89
  form.onsubmit = (e) => {
90
  e.preventDefault();
91
  const prompt = document.getElementById("promptInput").value;
92
+ document.getElementById("output").textContent = "";
 
 
93
  runPrompt(prompt);
94
  }
95
  };
96
  </script>
97
  <style>
98
+ body { font-family: 'Segoe UI', sans-serif; background: #1e1e2f; color: #f0f0f0; display: flex; flex-direction: column; align-items: center; padding: 2rem; }
 
 
 
 
 
 
 
 
99
  h1 { color: #ffcc00; margin-bottom: 1rem; }
100
  #promptForm { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
101
+ #promptInput { padding: 0.5rem; width: 400px; border-radius: 5px; border: none; font-size: 1rem; }
102
+ #generateBtn { padding: 0.5rem 1rem; background: #ffcc00; border: none; border-radius: 5px; font-weight: bold; cursor: pointer; color: #1e1e2f; }
 
 
 
 
 
 
 
103
  #generateBtn:hover { background: #ffdd33; }
104
+ #progressContainer { width: 400px; height: 20px; background: #333; border-radius: 5px; overflow: hidden; margin-bottom: 1rem; position: relative; }
105
+ #progress { width: 0%; height: 100%; background: #ffcc00; transition: width 0.05s; }
106
+ #progressText { position: absolute; right: 10px; top: 0; bottom: 0; display: flex; align-items: center; justify-content: flex-end; font-size: 0.8rem; color: #1e1e2f; font-weight: bold; }
107
+ pre#output { width: 400px; background: #2e2e44; padding: 1rem; border-radius: 8px; white-space: pre-wrap; word-wrap: break-word; min-height: 150px; overflow-y: auto; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  </style>
109
  </head>
110
  <body>
111
  <h1>ONNX WebGPU Streaming Text Generation</h1>
 
112
  <form id="promptForm">
113
  <input id="promptInput" type="text" placeholder="Type your prompt..." required />
114
  <button id="generateBtn">Generate</button>
115
  </form>
 
116
  <div id="progressContainer">
117
  <div id="progress"></div>
118
  <div id="progressText">0%</div>
119
  </div>
 
120
  <pre id="output">Enter a prompt and hit Generate...</pre>
121
  </body>
122
  </html>