Minor WASM UI improvements (#748)

* add stats

* random seed btn

* minor ui improvoments
This commit is contained in:
Radamés Ajna
2023-09-05 11:24:43 -07:00
committed by GitHub
parent a0d65585db
commit 6a40decc76
4 changed files with 101 additions and 44 deletions

View File

@ -60,23 +60,30 @@
const seed = getValue("seed"); const seed = getValue("seed");
const maxSeqLen = getValue("max-seq"); const maxSeqLen = getValue("max-seq");
function updateStatus({ status, message, prompt, sentence }) { function updateStatus(data) {
const outStatus = document.querySelector("#output-status"); const outStatus = document.querySelector("#output-status");
const outGen = document.querySelector("#output-generation"); const outGen = document.querySelector("#output-generation");
const outCounter = document.querySelector("#output-counter");
switch (status) { switch (data.status) {
case "loading": case "loading":
outStatus.hidden = false; outStatus.hidden = false;
outStatus.textContent = message; outStatus.textContent = data.message;
outGen.hidden = true; outGen.hidden = true;
outCounter.hidden = true;
break; break;
case "generating": case "generating":
const { message, prompt, sentence, tokensSec, totalTime } = data;
outStatus.hidden = true; outStatus.hidden = true;
outCounter.hidden = false;
outGen.hidden = false; outGen.hidden = false;
outGen.innerHTML = `<span class="font-semibold">${prompt}</span>${sentence.replace( outGen.innerHTML = `<span class="font-semibold">${prompt}</span>${sentence.replace(
/\<s\>|\<\/s\>/g, /\<s\>|\<\/s\>/g,
"" ""
)}`; )}`;
outCounter.innerHTML = `${(totalTime / 1000).toFixed(
2
)}s (${tokensSec.toFixed(2)} tok/s)`;
break; break;
case "complete": case "complete":
outStatus.hidden = true; outStatus.hidden = true;
@ -206,8 +213,9 @@
id="prompt" id="prompt"
class="font-light w-full px-3 py-2 mx-1 resize-none outline-none" class="font-light w-full px-3 py-2 mx-1 resize-none outline-none"
placeholder="Add your prompt here..." placeholder="Add your prompt here..."
value="Once upon a time"
/> />
<button class="invisible" id="clear-btn"> <button id="clear-btn">
<svg <svg
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -225,7 +233,6 @@
</button> </button>
<button <button
id="run" 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" 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 Run
@ -291,17 +298,26 @@
value="299792458" value="299792458"
class="font-light border border-gray-700 text-right rounded-md p-2" 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>
<div> <div>
<h3 class="font-medium">Generation:</h3> <h3 class="font-medium">Generation:</h3>
<div <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> <div
<span id="output-counter"
id="output-status" hidden
class="justify-self-center self-center font-light" 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 >No output yet</span
> >
</div> </div>

View File

@ -60,9 +60,10 @@ async function generate(data) {
const seq_len = model.get_seq_len(); const seq_len = model.get_seq_len();
let sentence = ""; let sentence = "";
let max_tokens = maxSeqLen ? maxSeqLen : seq_len - prompt.length - 1; let maxTokens = maxSeqLen ? maxSeqLen : seq_len - prompt.length - 1;
let startTime = performance.now();
while (max_tokens--) { let tokensCount = 0;
while (tokensCount < maxTokens) {
await new Promise(async (resolve) => { await new Promise(async (resolve) => {
if (controller && controller.signal.aborted) { if (controller && controller.signal.aborted) {
self.postMessage({ self.postMessage({
@ -73,6 +74,8 @@ async function generate(data) {
return; return;
} }
const token = await model.next_token(); const token = await model.next_token();
const tokensSec =
((tokensCount + 1) / (performance.now() - startTime)) * 1000;
sentence += token; sentence += token;
self.postMessage({ self.postMessage({
@ -80,10 +83,13 @@ async function generate(data) {
message: "Generating token", message: "Generating token",
token: token, token: token,
sentence: sentence, sentence: sentence,
totalTime: performance.now() - startTime,
tokensSec,
prompt: prompt, prompt: prompt,
}); });
setTimeout(resolve, 0); setTimeout(resolve, 0);
}); });
tokensCount++;
} }
self.postMessage({ self.postMessage({
status: "complete", status: "complete",

View File

@ -141,7 +141,9 @@
const { output } = result; const { output } = result;
const text = output.map((segment) => segment.dr.text).join(" "); const text = output.map((segment) => segment.dr.text).join(" ");
console.log(text); 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) => { .catch((error) => {
console.error(error); console.error(error);
@ -295,18 +297,21 @@
<button <button
id="detect" id="detect"
disabled 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 Transcribe Audio
</button> </button>
</div> </div>
<div> <div>
<h3 class="font-medium">Transcription:</h3> <h3 class="font-medium">Transcription:</h3>
<div <div
id="output" class="min-h-[250px] bg-slate-100 text-gray-500 p-4 rounded-md flex flex-col gap-2"
class="min-h-[100px] bg-slate-500 text-white p-4 rounded-md" >
></div> <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> </div>
</main> </main>
</body> </body>

View File

@ -145,6 +145,10 @@
} }
}); });
document.querySelector("#clear-btn").addEventListener("click", () => {
drawImageCanvas();
});
function drawImageCanvas(imgURL) { function drawImageCanvas(imgURL) {
const canvas = document.querySelector("#canvas"); const canvas = document.querySelector("#canvas");
const canvasResult = document.querySelector("#canvas-result"); const canvasResult = document.querySelector("#canvas-result");
@ -153,21 +157,28 @@
.clearRect(0, 0, canvas.width, canvas.height); .clearRect(0, 0, canvas.width, canvas.height);
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height); 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(); if (imgURL && imgURL !== "") {
img.crossOrigin = "anonymous"; const img = new Image();
img.crossOrigin = "anonymous";
img.onload = () => { img.onload = () => {
canvas.width = img.width; canvas.width = img.width;
canvas.height = img.height; canvas.height = img.height;
ctx.drawImage(img, 0, 0); ctx.drawImage(img, 0, 0);
canvas.parentElement.style.height = canvas.offsetHeight + "px"; canvas.parentElement.style.height = canvas.offsetHeight + "px";
hasImage = true; hasImage = true;
document.querySelector("#detect").disabled = false; document.querySelector("#detect").disabled = false;
}; document.querySelector("#clear-btn").classList.remove("invisible");
img.src = imgURL; };
img.src = imgURL;
}
} }
async function classifyImage( async function classifyImage(
@ -310,7 +321,7 @@
button.classList.add("bg-blue-950"); button.classList.add("bg-blue-950");
button.classList.remove("bg-blue-700"); button.classList.remove("bg-blue-700");
button.textContent = "Predict"; button.textContent = "Predict";
document.querySelector("#share-btn").hidden = false; document.querySelector("#share-btn").classList.remove("invisible");
} }
} }
document.querySelector("#share-btn").addEventListener("click", () => { document.querySelector("#share-btn").addEventListener("click", () => {
@ -372,8 +383,37 @@
<option value="yolov8x_pose">yolov8x_pose (139 MB)</option> <option value="yolov8x_pose">yolov8x_pose (139 MB)</option>
</select> </select>
</div> </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 --> <!-- drag and drop area -->
<div class="relative"> <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 <div
id="drop-area" 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" 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"> <div class="text-right py-2">
<button <button
id="share-btn" id="share-btn"
hidden class="bg-white rounded-md hover:outline outline-orange-200 disabled:opacity-50 invisible"
class="bg-white rounded-md hover:outline outline-orange-200 disabled:opacity-50"
> >
<img <img
src="https://huggingface.co/datasets/huggingface/badges/raw/main/share-to-community-sm.svg" src="https://huggingface.co/datasets/huggingface/badges/raw/main/share-to-community-sm.svg"
@ -489,15 +528,6 @@
> >
</div> </div>
</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> </main>
</body> </body>
</html> </html>