mirror of
https://github.com/huggingface/candle.git
synced 2025-06-16 02:38:10 +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 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>
|
||||
|
@ -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",
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Reference in New Issue
Block a user