document.addEventListener("DOMContentLoaded", () => { const chatLog = document.getElementById("task1ChatLog"); const userInput = document.getElementById("task1UserInput"); const sendBtn = document.getElementById("task1SendBtn"); const taskSelect = document.getElementById("task1TaskSelect"); const WELCOME = "Select a task, enter text, and compare the six model responses."; let loadingCounter = 0; const taskModels = Object.entries(TASK1_MODELS).reduce((acc, [key, model]) => { const task = model.task1_task; if (!acc[task]) acc[task] = []; acc[task].push({ key, ...model }); return acc; }, {}); const modelOrder = [ "lr_sentiment", "svm_sentiment", "rf_sentiment", "albert_sentiment", "roberta_sentiment", "distilbert_sentiment", "lr_sarcasm", "svm_sarcasm", "rf_sarcasm", "albert_sarcasm", "roberta_sarcasm", "distilbert_sarcasm", ]; Object.keys(taskModels).forEach(task => { taskModels[task].sort((a, b) => modelOrder.indexOf(a.key) - modelOrder.indexOf(b.key)); }); taskSelect.addEventListener("change", clearChat); userInput.addEventListener("input", () => { userInput.style.height = "auto"; userInput.style.height = Math.min(userInput.scrollHeight, 140) + "px"; }); userInput.addEventListener("keydown", event => { if (event.key === "Enter" && !event.shiftKey) { event.preventDefault(); sendMessage(); } }); sendBtn.addEventListener("click", sendMessage); function clearChat() { chatLog.innerHTML = ""; appendMsg("bot", WELCOME); } async function sendMessage() { const text = userInput.value.trim(); const task = taskSelect.value; const models = taskModels[task] || []; if (!text) return; if (models.length === 0) { appendMsg("bot", "No models are registered for this task."); return; } appendMsg("user", text); userInput.value = ""; userInput.style.height = "auto"; sendBtn.disabled = true; const requests = models.map(model => runModel(model, text, task)); await Promise.allSettled(requests); sendBtn.disabled = false; userInput.focus(); } async function runModel(model, text, task) { const loadingId = appendLoading(model); try { const response = await fetch("/api/task1/infer", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text, task, model_key: model.key }), }); const data = await response.json(); removeLoading(loadingId); if (data.error) { appendMsg("bot", `Warning: ${escapeHTML(data.error)}`, model); } else { appendMsg("bot", formatResult(data, model, task), model); } } catch (error) { removeLoading(loadingId); appendMsg("bot", `Warning: Network error: ${escapeHTML(error.message)}`, model); } } function appendMsg(role, content, model = null) { const wrapper = document.createElement("div"); wrapper.className = `msg ${role}`; if (model && model.family) wrapper.dataset.family = model.family; const avatar = document.createElement("div"); avatar.className = "msg-avatar"; avatar.innerHTML = role === "bot" ? iconForModel(model) : ''; const bubble = document.createElement("div"); bubble.className = "msg-bubble"; bubble.innerHTML = role === "bot" ? content : escapeHTML(content); wrapper.appendChild(avatar); wrapper.appendChild(bubble); chatLog.appendChild(wrapper); chatLog.scrollTop = chatLog.scrollHeight; } function appendLoading(model) { const id = `task1-loading-${++loadingCounter}`; const wrapper = document.createElement("div"); wrapper.className = "msg bot"; wrapper.id = id; if (model.family) wrapper.dataset.family = model.family; wrapper.innerHTML = `
${iconForModel(model)}
${escapeHTML(model.name)} ${familyLabel(model.family)}
`; chatLog.appendChild(wrapper); chatLog.scrollTop = chatLog.scrollHeight; return id; } function removeLoading(id) { const element = document.getElementById(id); if (element) element.remove(); } function formatResult(data, model, task) { const raw = String(data.label || "").toUpperCase(); let display = data.label || "Unknown"; if (task === "sentiment") { if (raw === "POSITIVE" || raw === "LABEL_1" || raw === "1") display = "Positive"; if (raw === "NEGATIVE" || raw === "LABEL_0" || raw === "0") display = "Negative"; } if (task === "sarcasm") { if (raw === "SARCASTIC" || raw === "LABEL_1" || raw === "1") display = "Sarcastic"; if (raw === "NOT_SARCASTIC" || raw === "LABEL_0" || raw === "0") display = "Not Sarcastic"; } const score = data.score !== undefined ? `Score: ${data.score}` : ""; return `
${escapeHTML(model.name)} ${familyLabel(model.family)}
Result: ${escapeHTML(display)} ${score}
`; } function iconForModel(model) { if (!model) return ''; if (model.family === "classical") return ''; return ''; } function familyLabel(family) { return family === "ptlm" ? "PTLM" : "Classical"; } function escapeHTML(str) { return String(str).replace(/[&<>"']/g, tag => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'", }[tag])); } });