summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRadamés Ajna <radamajna@gmail.com>2023-09-05 11:24:43 -0700
committerGitHub <noreply@github.com>2023-09-05 19:24:43 +0100
commit6a40decc76246b23f7f1c6ada539c93afadfffba (patch)
tree3681808348103462949105f5f000a3462bf83c78
parenta0d65585db0323747f71b4f33831a165b56a759b (diff)
downloadcandle-6a40decc76246b23f7f1c6ada539c93afadfffba.tar.gz
candle-6a40decc76246b23f7f1c6ada539c93afadfffba.tar.bz2
candle-6a40decc76246b23f7f1c6ada539c93afadfffba.zip
Minor WASM UI improvements (#748)
* add stats * random seed btn * minor ui improvoments
-rw-r--r--candle-wasm-examples/llama2-c/lib-example.html38
-rw-r--r--candle-wasm-examples/llama2-c/llama2cWorker.js12
-rw-r--r--candle-wasm-examples/whisper/lib-example.html17
-rw-r--r--candle-wasm-examples/yolo/lib-example.html78
4 files changed, 101 insertions, 44 deletions
diff --git a/candle-wasm-examples/llama2-c/lib-example.html b/candle-wasm-examples/llama2-c/lib-example.html
index bc519e4b..5995f003 100644
--- a/candle-wasm-examples/llama2-c/lib-example.html
+++ b/candle-wasm-examples/llama2-c/lib-example.html
@@ -60,23 +60,30 @@
const seed = getValue("seed");
const maxSeqLen = getValue("max-seq");
- function updateStatus({ status, message, prompt, sentence }) {
+ function updateStatus(data) {
const outStatus = document.querySelector("#output-status");
const outGen = document.querySelector("#output-generation");
+ const outCounter = document.querySelector("#output-counter");
- switch (status) {
+ switch (data.status) {
case "loading":
outStatus.hidden = false;
- outStatus.textContent = message;
+ outStatus.textContent = data.message;
outGen.hidden = true;
+ outCounter.hidden = true;
break;
case "generating":
+ const { message, prompt, sentence, tokensSec, totalTime } = data;
outStatus.hidden = true;
+ outCounter.hidden = false;
outGen.hidden = false;
outGen.innerHTML = `<span class="font-semibold">${prompt}</span>${sentence.replace(
/\<s\>|\<\/s\>/g,
""
)}`;
+ outCounter.innerHTML = `${(totalTime / 1000).toFixed(
+ 2
+ )}s (${tokensSec.toFixed(2)} tok/s)`;
break;
case "complete":
outStatus.hidden = true;
@@ -206,8 +213,9 @@
id="prompt"
class="font-light w-full px-3 py-2 mx-1 resize-none outline-none"
placeholder="Add your prompt here..."
+ value="Once upon a time"
/>
- <button class="invisible" id="clear-btn">
+ <button id="clear-btn">
<svg
fill="none"
xmlns="http://www.w3.org/2000/svg"
@@ -225,7 +233,6 @@
</button>
<button
id="run"
- disabled
class="bg-gray-700 hover:bg-gray-800 text-white font-normal py-2 w-16 rounded disabled:bg-gray-300 disabled:cursor-not-allowed"
>
Run
@@ -291,17 +298,26 @@
value="299792458"
class="font-light border border-gray-700 text-right rounded-md p-2"
/>
+ <button
+ id="run"
+ onclick="document.querySelector('#seed').value = BigInt(Math.floor(Math.random() * 2**64-1))"
+ class="bg-gray-700 hover:bg-gray-800 text-white font-normal py-1 w-[50px] rounded disabled:bg-gray-300 disabled:cursor-not-allowed text-sm"
+ >
+ Rand
+ </button>
</div>
<div>
<h3 class="font-medium">Generation:</h3>
-
<div
- class="min-h-[250px] bg-slate-100 text-gray-500 p-4 rounded-md grid"
+ class="min-h-[250px] bg-slate-100 text-gray-500 p-4 rounded-md flex flex-col gap-2"
>
- <p hidden id="output-generation"></p>
- <span
- id="output-status"
- class="justify-self-center self-center font-light"
+ <div
+ id="output-counter"
+ hidden
+ class="ml-auto font-semibold grid-rows-1 text-sm"
+ ></div>
+ <p hidden id="output-generation" class="grid-rows-2"></p>
+ <span id="output-status" class="m-auto font-light"
>No output yet</span
>
</div>
diff --git a/candle-wasm-examples/llama2-c/llama2cWorker.js b/candle-wasm-examples/llama2-c/llama2cWorker.js
index ba303aaa..e4229055 100644
--- a/candle-wasm-examples/llama2-c/llama2cWorker.js
+++ b/candle-wasm-examples/llama2-c/llama2cWorker.js
@@ -60,9 +60,10 @@ async function generate(data) {
const seq_len = model.get_seq_len();
let sentence = "";
- let max_tokens = maxSeqLen ? maxSeqLen : seq_len - prompt.length - 1;
-
- while (max_tokens--) {
+ let maxTokens = maxSeqLen ? maxSeqLen : seq_len - prompt.length - 1;
+ let startTime = performance.now();
+ let tokensCount = 0;
+ while (tokensCount < maxTokens) {
await new Promise(async (resolve) => {
if (controller && controller.signal.aborted) {
self.postMessage({
@@ -73,6 +74,8 @@ async function generate(data) {
return;
}
const token = await model.next_token();
+ const tokensSec =
+ ((tokensCount + 1) / (performance.now() - startTime)) * 1000;
sentence += token;
self.postMessage({
@@ -80,10 +83,13 @@ async function generate(data) {
message: "Generating token",
token: token,
sentence: sentence,
+ totalTime: performance.now() - startTime,
+ tokensSec,
prompt: prompt,
});
setTimeout(resolve, 0);
});
+ tokensCount++;
}
self.postMessage({
status: "complete",
diff --git a/candle-wasm-examples/whisper/lib-example.html b/candle-wasm-examples/whisper/lib-example.html
index a8c49785..ad48072b 100644
--- a/candle-wasm-examples/whisper/lib-example.html
+++ b/candle-wasm-examples/whisper/lib-example.html
@@ -141,7 +141,9 @@
const { output } = result;
const text = output.map((segment) => segment.dr.text).join(" ");
console.log(text);
- document.getElementById("output").textContent = text;
+ document.querySelector("#output-status").hidden = true;
+ document.querySelector("#output-generation").hidden = false;
+ document.querySelector("#output-generation").textContent = text;
})
.catch((error) => {
console.error(error);
@@ -295,18 +297,21 @@
<button
id="detect"
disabled
- class="bg-orange-900 hover:bg-orange-800 text-white font-normal py-2 px-4 rounded disabled:opacity-75 disabled:cursor-not-allowed"
+ class="bg-gray-700 hover:bg-gray-800 text-white font-normal py-2 px-4 rounded disabled:bg-gray-300 disabled:cursor-not-allowed"
>
Transcribe Audio
</button>
</div>
<div>
<h3 class="font-medium">Transcription:</h3>
-
<div
- id="output"
- class="min-h-[100px] bg-slate-500 text-white p-4 rounded-md"
- ></div>
+ class="min-h-[250px] bg-slate-100 text-gray-500 p-4 rounded-md flex flex-col gap-2"
+ >
+ <p hidden id="output-generation" class="grid-rows-2"></p>
+ <span id="output-status" class="m-auto font-light"
+ >No transcription results yet</span
+ >
+ </div>
</div>
</main>
</body>
diff --git a/candle-wasm-examples/yolo/lib-example.html b/candle-wasm-examples/yolo/lib-example.html
index bab2ec13..8f7d07c7 100644
--- a/candle-wasm-examples/yolo/lib-example.html
+++ b/candle-wasm-examples/yolo/lib-example.html
@@ -145,6 +145,10 @@
}
});
+ document.querySelector("#clear-btn").addEventListener("click", () => {
+ drawImageCanvas();
+ });
+
function drawImageCanvas(imgURL) {
const canvas = document.querySelector("#canvas");
const canvasResult = document.querySelector("#canvas-result");
@@ -153,21 +157,28 @@
.clearRect(0, 0, canvas.width, canvas.height);
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
- document.querySelector("#share-btn").hidden = true;
+ document.querySelector("#share-btn").classList.add("invisible");
+ document.querySelector("#clear-btn").classList.add("invisible");
+ document.querySelector("#detect").disabled = true;
+ hasImage = false;
+ canvas.parentElement.style.height = "auto";
- const img = new Image();
- img.crossOrigin = "anonymous";
+ if (imgURL && imgURL !== "") {
+ const img = new Image();
+ img.crossOrigin = "anonymous";
- img.onload = () => {
- canvas.width = img.width;
- canvas.height = img.height;
- ctx.drawImage(img, 0, 0);
+ img.onload = () => {
+ canvas.width = img.width;
+ canvas.height = img.height;
+ ctx.drawImage(img, 0, 0);
- canvas.parentElement.style.height = canvas.offsetHeight + "px";
- hasImage = true;
- document.querySelector("#detect").disabled = false;
- };
- img.src = imgURL;
+ canvas.parentElement.style.height = canvas.offsetHeight + "px";
+ hasImage = true;
+ document.querySelector("#detect").disabled = false;
+ document.querySelector("#clear-btn").classList.remove("invisible");
+ };
+ img.src = imgURL;
+ }
}
async function classifyImage(
@@ -310,7 +321,7 @@
button.classList.add("bg-blue-950");
button.classList.remove("bg-blue-700");
button.textContent = "Predict";
- document.querySelector("#share-btn").hidden = false;
+ document.querySelector("#share-btn").classList.remove("invisible");
}
}
document.querySelector("#share-btn").addEventListener("click", () => {
@@ -372,8 +383,37 @@
<option value="yolov8x_pose">yolov8x_pose (139 MB)</option>
</select>
</div>
+ <div>
+ <button
+ id="detect"
+ disabled
+ class="bg-gray-700 hover:bg-gray-800 text-white font-normal py-2 px-4 rounded disabled:bg-gray-300 disabled:cursor-not-allowed"
+ >
+ Predict
+ </button>
+ </div>
<!-- drag and drop area -->
<div class="relative">
+ <div class="py-1">
+ <button
+ id="clear-btn"
+ class="text-xs bg-white rounded-md disabled:opacity-50 flex gap-1 items-center ml-auto invisible"
+ >
+ <svg
+ class=""
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 13 12"
+ height="1em"
+ >
+ <path
+ d="M1.6.7 12 11.1M12 .7 1.6 11.1"
+ stroke="#2E3036"
+ stroke-width="2"
+ />
+ </svg>
+ Clear image
+ </button>
+ </div>
<div
id="drop-area"
class="flex flex-col items-center justify-center border-2 border-gray-300 border-dashed rounded-xl relative aspect-video w-full overflow-hidden"
@@ -422,8 +462,7 @@
<div class="text-right py-2">
<button
id="share-btn"
- hidden
- class="bg-white rounded-md hover:outline outline-orange-200 disabled:opacity-50"
+ class="bg-white rounded-md hover:outline outline-orange-200 disabled:opacity-50 invisible"
>
<img
src="https://huggingface.co/datasets/huggingface/badges/raw/main/share-to-community-sm.svg"
@@ -489,15 +528,6 @@
>
</div>
</div>
- <div>
- <button
- id="detect"
- disabled
- class="bg-blue-950 hover:bg-blue-700 text-white font-normal py-2 px-4 rounded disabled:opacity-75 disabled:hover:bg-blue-950"
- >
- Predict
- </button>
- </div>
</main>
</body>
</html>