diff options
author | Radamés Ajna <radamajna@gmail.com> | 2023-09-05 11:24:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-05 19:24:43 +0100 |
commit | 6a40decc76246b23f7f1c6ada539c93afadfffba (patch) | |
tree | 3681808348103462949105f5f000a3462bf83c78 | |
parent | a0d65585db0323747f71b4f33831a165b56a759b (diff) | |
download | candle-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.html | 38 | ||||
-rw-r--r-- | candle-wasm-examples/llama2-c/llama2cWorker.js | 12 | ||||
-rw-r--r-- | candle-wasm-examples/whisper/lib-example.html | 17 | ||||
-rw-r--r-- | candle-wasm-examples/yolo/lib-example.html | 78 |
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> |