mirror of
https://github.com/huggingface/candle.git
synced 2025-06-17 11:08:52 +00:00
Minor WASM UI improvements (#748)
* add stats * random seed btn * minor ui improvoments
This commit is contained in:
@ -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>
|
||||||
|
@ -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",
|
||||||
|
@ -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>
|
||||||
|
@ -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,8 +157,13 @@
|
|||||||
.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";
|
||||||
|
|
||||||
|
if (imgURL && imgURL !== "") {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.crossOrigin = "anonymous";
|
img.crossOrigin = "anonymous";
|
||||||
|
|
||||||
@ -166,9 +175,11 @@
|
|||||||
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(
|
||||||
imageURL, // URL of image to classify
|
imageURL, // URL of image to classify
|
||||||
@ -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>
|
||||||
|
Reference in New Issue
Block a user