Spaces:
Running
Running
File size: 5,098 Bytes
4cd954b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
// Setup DOM references
const generateBtn = document.getElementById("generate-btn");
const promptInput = document.getElementById("prompt-input");
const responseOutput = document.getElementById("response-output");
const statusMessageContainer = document.getElementById("status-message");
const workerPath = './worker.js';
let worker;
let modelReady = false;
/**
* Handles the click event for an emoji button.
* Copies the emoji combo to the clipboard and updates the status message.
* @param {string} combo The emoji combo to copy.
*/
function handleEmojiButtonClick(combo) {
navigator.clipboard.writeText(combo);
statusMessageContainer.textContent = `Copied to clipboard: ${combo}`;
console.log(`[UI] Copied "${combo}" to clipboard.`);
}
/**
* Creates and appends a button for an emoji combo.
* @param {string} combo The emoji combo text.
*/
function createEmojiButton(combo) {
const button = document.createElement("button");
button.textContent = combo;
button.onclick = () => handleEmojiButtonClick(combo);
responseOutput.appendChild(button);
}
/**
* Main function to run LLM Inference in worker
* Including worker messaging setup.
*/
async function initializeModelInWorker() {
console.log("[UI] Initializing application...");
// Create a progress loader that clears once the model loads
statusMessageContainer.textContent = "Loading model (0%)";
// Create a new worker to run the model in a separate thread
worker = new Worker(workerPath, { type: "module" });
console.log("[UI] Worker created.");
// Listen for messages from the worker
worker.onmessage = (event) => {
const { type, data } = event.data;
switch (type) {
case "progress":
statusMessageContainer.textContent = `Loading model (${data.progress}%)`;
break;
case "loaded":
statusMessageContainer.textContent = `Loading model (100%)`; // Show 100% briefly
modelReady = true;
generateBtn.disabled = false; // Enable the generation button upon model load
setTimeout(() => { // Then switch to the final message
statusMessageContainer.innerHTML = ``;
}, 500);
break;
case "result":
const line = data.trim();
if (line) {
createEmojiButton(line);
}
break;
case "complete":
responseComplete();
break;
case "error":
console.error("Worker error:", data);
if (modelReady) {
// Error during generation
generateBtn.classList.remove('generating');
statusMessageContainer.textContent =
"Failed to generate response. Check the console for errors.";
generateBtn.disabled = false; // Re-enable button
} else {
// Error during model loading
statusMessageContainer.textContent = "Failed to load model. Please refresh the page.";
}
break;
}
};
// Start loading the model in the worker
console.log('[UI] Sending "load" message to worker.');
worker.postMessage({ type: "load" });
}
function responseComplete() {
generateBtn.classList.remove('generating');
generateBtn.disabled = false;
if (responseOutput.childElementCount === 0) {
statusMessageContainer.textContent = "No results";
} else {
// Clear the status message if we have results
statusMessageContainer.textContent = "Click to copy emojis";
// For accessibility, move focus to the first result so keyboard users can navigate them.
responseOutput.firstChild.focus();
}
}
function resetUI() {
console.log("[UI] Resetting UI state.");
generateBtn.classList.add('generating');
generateBtn.disabled = true;
responseOutput.innerHTML = ""; // Clear previous buttons
statusMessageContainer.textContent = "Generating..."; // Set generating status
}
async function generateResponse() {
const prompt = promptInput.value.trim();
if (!prompt) {
statusMessageContainer.textContent = "Please enter a prompt.";
return;
}
if (!worker || !modelReady) {
statusMessageContainer.textContent = "Model is not ready yet. Please wait.";
return;
}
resetUI();
// Send prompt to worker to start generation
console.log(
`[UI] Sending "generate" message to worker with prompt: "${prompt}"`
);
worker.postMessage({ type: "generate", data: { prompt } });
}
// After the script is loaded, initialize the text generator.
async function initializeAndAttachListeners() {
console.log("[UI] Starting initialization and attaching listeners.");
await initializeModelInWorker();
generateBtn.addEventListener("click", generateResponse);
// Add event listener for "Enter" key press in the prompt input field
promptInput.addEventListener("keydown", function (event) {
if (event.key === "Enter" && !event.shiftKey && !generateBtn.disabled) {
console.log('[UI] "Enter" key pressed, triggering generation.');
event.preventDefault(); // Prevents the default action (form submission/new line)
generateResponse();
}
});
}
initializeAndAttachListeners();
|