Candle-CoEdIT-Wasm / index.html
radames's picture
Upload 11 files
539c560
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
<title>Candle T5</title>
</head>
<body></body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
@import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@200;300;400&family=Source+Sans+3:wght@100;200;300;400;500;600;700;800;900&display=swap");
html,
body {
font-family: "Source Sans 3", sans-serif;
}
</style>
<style type="text/tailwindcss">
.link {
@apply underline hover:text-blue-500 hover:no-underline;
}
</style>
<script src="https://cdn.tailwindcss.com"></script>
<script type="module">
import {
getModelInfo,
MODELS,
extractEmbeddings,
generateText,
} from "./utils.js";
const t5ModelEncoderWorker = new Worker("./T5ModelEncoderWorker.js", {
type: "module",
});
const t5ModelConditionalGeneration = new Worker(
"./T5ModelConditionalGeneration.js",
{ type: "module" }
);
const formEl = document.querySelector("#form");
const modelEl = document.querySelector("#model");
const promptEl = document.querySelector("#prompt");
const temperatureEl = document.querySelector("#temperature");
const toppEL = document.querySelector("#top-p");
const repeatPenaltyEl = document.querySelector("#repeat_penalty");
const seedEl = document.querySelector("#seed");
const outputEl = document.querySelector("#output-generation");
const tasksEl = document.querySelector("#tasks");
let selectedTaskID = "";
document.addEventListener("DOMContentLoaded", () => {
for (const [id, model] of Object.entries(MODELS)) {
const option = document.createElement("option");
option.value = id;
option.innerText = `${id} (${model.size})`;
modelEl.appendChild(option);
}
populateTasks(modelEl.value);
modelEl.addEventListener("change", (e) => {
populateTasks(e.target.value);
});
tasksEl.addEventListener("change", (e) => {
const task = e.target.value;
const modelID = modelEl.value;
promptEl.value = MODELS[modelID].tasks[task].prefix;
selectedTaskID = task;
});
});
function populateTasks(modelID) {
const tasks = MODELS[modelID].tasks;
tasksEl.innerHTML = "";
for (const [task, params] of Object.entries(tasks)) {
const div = document.createElement("div");
div.innerHTML = `
<input
type="radio"
name="task"
id="${task}"
class="font-light cursor-pointer"
value="${task}" />
<label for="${task}" class="cursor-pointer">
${params.prefix}
</label>
`;
tasksEl.appendChild(div);
}
selectedTaskID = Object.keys(tasks)[0];
tasksEl.querySelector(`#${selectedTaskID}`).checked = true;
}
form.addEventListener("submit", (e) => {
e.preventDefault();
const promptText = promptEl.value;
const modelID = modelEl.value;
const { modelURL, configURL, tokenizerURL, maxLength } = getModelInfo(
modelID,
selectedTaskID
);
const params = {
temperature: Number(temperatureEl.value),
top_p: Number(toppEL.value),
repetition_penalty: Number(repeatPenaltyEl.value),
seed: BigInt(seedEl.value),
max_length: maxLength,
};
generateText(
t5ModelConditionalGeneration,
modelURL,
tokenizerURL,
configURL,
modelID,
promptText,
params,
(status) => {
if (status.status === "loading") {
outputEl.innerText = "Loading model...";
}
if (status.status === "decoding") {
outputEl.innerText = "Generating...";
}
}
).then(({ output }) => {
outputEl.innerText = output.generation;
});
});
</script>
</head>
<body class="container max-w-4xl mx-auto p-4">
<main class="grid grid-cols-1 gap-8 relative">
<span class="absolute text-5xl -ml-[1em]"> 🕯️ </span>
<div>
<h1 class="text-5xl font-bold">Candle T5 Transformer</h1>
<h2 class="text-2xl font-bold">Rust/WASM Demo</h2>
<p class="max-w-lg">
This demo runs Text-To-Text Transfer Transformer
<a
href="https://blog.research.google/2020/02/exploring-transfer-learning-with-t5.html"
target="_blank"
class="link">
T5
</a>
with
<a
href="https://github.com/huggingface/candle/"
target="_blank"
class="link">
Candle
</a>
in the browser using rust/wasm. Models
<a
href="https://huggingface.co/t5-small"
target="_blank"
class="link">
t5-small </a
>,
<a href="https://huggingface.co/t5-base" target="_blank" class="link">
t5-base </a
>,
<a
href="https://huggingface.co/google/flan-t5-small"
target="_blank"
class="link"
>flan-t5-small
</a>
and a few
<a
href="https://huggingface.co/lmz/candle-quantized-t5/tree/main"
target="_blank"
class="link">
t5 quantized gguf
</a>
are available.
</p>
</div>
<div>
<label for="model" class="font-medium">Models Options: </label>
<select
id="model"
class="border-2 border-gray-500 rounded-md font-light"></select>
</div>
<div>
<h3 class="font-medium">Task Prefix:</h3>
<form id="tasks" class="flex flex-col gap-1 my-2"></form>
</div>
<form
id="form"
class="flex text-normal px-1 py-1 border border-gray-700 rounded-md items-center">
<input type="submit" hidden />
<input
type="text"
id="prompt"
class="font-light w-full px-3 py-2 mx-1 resize-none outline-none"
placeholder="Add prompt here, e.g. 'translate English to German: Today I'm going to eat Ice Cream'"
value="translate English to German: Today I'm going to eat Ice Cream" />
<button
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
</button>
</form>
<div class="grid grid-cols-3 max-w-md items-center gap-3">
<label class="text-sm font-medium" for="temperature">Temperature</label>
<input
type="range"
id="temperature"
name="temperature"
min="0"
max="2"
step="0.01"
value="0.00"
oninput="this.nextElementSibling.value = Number(this.value).toFixed(2)" />
<output
class="text-xs w-[50px] text-center font-light px-1 py-1 border border-gray-700 rounded-md">
0.00</output
>
<label class="text-sm font-medium" for="top-p">Top-p</label>
<input
type="range"
id="top-p"
name="top-p"
min="0"
max="1"
step="0.01"
value="1.00"
oninput="this.nextElementSibling.value = Number(this.value).toFixed(2)" />
<output
class="text-xs w-[50px] text-center font-light px-1 py-1 border border-gray-700 rounded-md">
1.00</output
>
<label class="text-sm font-medium" for="repeat_penalty"
>Repeat Penalty</label
>
<input
type="range"
id="repeat_penalty"
name="repeat_penalty"
min="-2"
max="2"
step="0.01"
value="1.10"
oninput="this.nextElementSibling.value = Number(this.value).toFixed(2)" />
<output
class="text-xs w-[50px] text-center font-light px-1 py-1 border border-gray-700 rounded-md"
>1.10</output
>
<label class="text-sm font-medium" for="seed">Seed</label>
<input
type="number"
id="seed"
name="seed"
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 flex flex-col gap-2 text-lg">
<p id="output-generation" class="grid-rows-2">No output yet</p>
</div>
</div>
</main>
</body>
</html>