File size: 5,023 Bytes
43128c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"use strict";
const $ = id => document.getElementById(id);
const examples = {
  banking77: [["Missing card", "I still have not received my new card"], ["Lost card", "I lost my debit card. How can I freeze it?"], ["Change PIN", "How do I change my card PIN?"]],
  clinc150: [["Weather", "What is the weather forecast for tomorrow?"], ["Set an alarm", "Set an alarm for seven tomorrow morning"], ["Book a flight", "I want to book a flight to Boston"]],
  massive: [["Play music", "Play some jazz music"], ["Set a timer", "Set a timer for ten minutes"], ["Lights off", "Turn off the living room lights"]]
};
const run = $("decide");
const text = $("text");
let busy = false;
function count() { $("count").textContent = `${text.value.length} / 2000`; }
function clearResult() { $("result").hidden = true; $("empty").hidden = false; $("error").hidden = true; }
function loadExamples() {
  $("examples").replaceChildren();
  for (const [title, value] of examples[$("skill").value]) {
    const button = document.createElement("button");
    button.className = "example"; button.type = "button"; button.textContent = title;
    button.addEventListener("click", () => { if (busy) return; text.value = value; count(); clearResult(); });
    $("examples").append(button);
  }
}
function render(value) {
  const decision = value.decision;
  const accepted = decision.confident && !decision.is_novel;
  $("verdict").textContent = accepted ? "Accepted · local decision" : "Abstained · needs review";
  $("verdict").className = accepted ? "verdict" : "verdict abstained";
  $("label").textContent = accepted ? decision.task_label : "Not confident enough";
  $("explanation").textContent = accepted
    ? "The winning topology passed the model’s confidence gate."
    : "No decision accepted. Candidates below are suggestions, not an accepted answer.";
  $("confidence").textContent = `${(decision.confidence * 100).toFixed(2)}%`;
  const encoding = Number(value.meta.embedding_latency_ms);
  const resonance = Number(value.meta.latency_ms);
  $("time").textContent = `${(encoding + resonance).toFixed(2)} ms`;
  $("timings").textContent = `Encoder ${encoding.toFixed(2)} ms + resonance ${resonance.toFixed(2)} ms · shared HF CPU`;
  $("candidates").replaceChildren();
  const candidates = value.scores.slice(0, 3).sort((a,b) => a.reconstruction_error - b.reconstruction_error);
  const max = Math.max(...candidates.map(c => c.reconstruction_error), 0.000001);
  for (const candidate of candidates) {
    const row = document.createElement("div"); row.className = "candidate";
    const names = document.createElement("div"); names.className = "candidate-name";
    const label = document.createElement("span"); label.textContent = candidate.task_label;
    const error = document.createElement("span"); error.textContent = Number(candidate.reconstruction_error).toFixed(4);
    names.append(label, error);
    const bar = document.createElement("progress"); bar.max = max; bar.value = candidate.reconstruction_error;
    bar.setAttribute("aria-label", `${candidate.task_label}: reconstruction error ${error.textContent}`);
    row.append(names, bar); $("candidates").append(row);
  }
  $("json").textContent = JSON.stringify(value, null, 2);
  $("empty").hidden = true; $("result").hidden = false;
}
async function decide() {
  if (busy) return;
  const prompt = text.value.trim();
  if (!prompt) { $("error").textContent = "Enter a request first."; $("error").hidden = false; text.focus(); return; }
  clearResult(); busy = true; run.disabled = true; text.disabled = true;
  $("skill").disabled = true; $("profile").disabled = true;
  run.textContent = "Computing reconstruction errors…";
  const abort = new AbortController(); const timeout = setTimeout(() => abort.abort(), 40000);
  try {
    const response = await fetch("/api/decide", {method:"POST", headers:{"Content-Type":"application/json"},
      body:JSON.stringify({skill:$("skill").value, text:prompt, profile:$("profile").value}), signal:abort.signal});
    const result = await response.json();
    if (!response.ok) throw new Error(result.error || "The demo is unavailable. Please retry.");
    render(result);
  } catch (error) {
    $("error").textContent = error.name === "AbortError" ? "The request timed out. Please try again." : error.message;
    $("error").hidden = false;
  } finally {
    clearTimeout(timeout); busy = false; run.disabled = false; text.disabled = false;
    $("skill").disabled = false; $("profile").disabled = false; run.textContent = "Make a decision →";
  }
}
$("skill").addEventListener("change", () => { loadExamples(); text.value = examples[$("skill").value][0][1]; count(); clearResult(); });
$("profile").addEventListener("change", clearResult);
text.addEventListener("input", () => { count(); clearResult(); });
text.addEventListener("keydown", event => { if ((event.ctrlKey || event.metaKey) && event.key === "Enter") { event.preventDefault(); decide(); } });
run.addEventListener("click", decide);
loadExamples(); count();