Download index.html from srishtisrivastavaphd/MBA601Module3: direct link, hf CLI and curl.
- Browser
- Download file 7.62 kB
-
https://huggingface.co/spaces/srishtisrivastavaphd/MBA601Module3/resolve/main/index.html
- Command line
-
hf download hf://spaces/srishtisrivastavaphd/MBA601Module3/index.html
-
curl -L -o index.html https://huggingface.co/spaces/srishtisrivastavaphd/MBA601Module3/resolve/main/index.html
7.62 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>Zero-Shot Topic Classifier</title> | |
| <style> | |
| :root { | |
| --bg: #f6f7f9; --card: #ffffff; --ink: #1c2230; --muted: #5d6677; | |
| --line: #dde1e8; --accent: #2f5bd3; --accent-ink: #ffffff; --bar: #2f5bd3; | |
| --bar-bg: #e8ecf5; --warn: #9a5b00; --warn-bg: #fff4e0; | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| :root { | |
| --bg: #12151c; --card: #1b2029; --ink: #e9ecf2; --muted: #a2aabb; | |
| --line: #2d3442; --accent: #6f93ff; --accent-ink: #0d1220; --bar: #6f93ff; | |
| --bar-bg: #262d3b; --warn: #ffc56b; --warn-bg: #2e2516; | |
| } | |
| } | |
| * { box-sizing: border-box; } | |
| body { margin: 0; background: var(--bg); color: var(--ink); | |
| font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; } | |
| main { max-width: 760px; margin: 0 auto; padding: 24px 16px 48px; } | |
| h1 { font-size: 1.5rem; margin: 0 0 4px; } | |
| .sub { color: var(--muted); margin: 0 0 20px; } | |
| .card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 18px; margin-bottom: 16px; } | |
| label { display: block; font-weight: 600; margin: 0 0 6px; } | |
| .hint { font-weight: 400; color: var(--muted); font-size: .9rem; } | |
| textarea, input[type=text] { width: 100%; padding: 10px 12px; border: 1px solid var(--line); | |
| border-radius: 8px; background: var(--bg); color: var(--ink); font: inherit; } | |
| textarea { min-height: 140px; resize: vertical; } | |
| .row { margin-bottom: 14px; } | |
| .check { display: flex; gap: 8px; align-items: center; font-weight: 400; } | |
| button { background: var(--accent); color: var(--accent-ink); border: 0; border-radius: 8px; | |
| padding: 11px 22px; font: 600 1rem system-ui, sans-serif; cursor: pointer; } | |
| button:disabled { opacity: .55; cursor: wait; } | |
| #status { margin-top: 12px; color: var(--muted); font-size: .95rem; min-height: 1.5em; } | |
| progress { width: 100%; height: 10px; margin-top: 8px; display: none; } | |
| .warn { background: var(--warn-bg); color: var(--warn); border-radius: 8px; padding: 10px 12px; font-size: .9rem; margin-top: 12px; display: none; } | |
| .res { display: grid; grid-template-columns: minmax(110px, 34%) 1fr 64px; gap: 8px 12px; align-items: center; } | |
| .res .name { overflow-wrap: anywhere; } | |
| .res .top { font-weight: 700; } | |
| .track { background: var(--bar-bg); border-radius: 6px; height: 14px; overflow: hidden; } | |
| .fill { background: var(--bar); height: 100%; } | |
| .pct { text-align: right; font-variant-numeric: tabular-nums; } | |
| .record { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); font-size: .95rem; } | |
| .record code { background: var(--bar-bg); padding: 2px 6px; border-radius: 4px; } | |
| footer { color: var(--muted); font-size: .85rem; } | |
| </style> | |
| </head> | |
| <body> | |
| <main> | |
| <h1>Zero-Shot Topic Classifier</h1> | |
| <p class="sub">Semantic analysis: what is this text about? Model: facebook/bart-large-mnli, running free in your browser. No account or credits needed.</p> | |
| <div class="card"> | |
| <div class="row"> | |
| <label for="text">Review text</label> | |
| <textarea id="text" placeholder="Paste one customer review here..."></textarea> | |
| </div> | |
| <div class="row"> | |
| <label for="labels">Candidate labels <span class="hint">(4 to 6 topics, separated by commas)</span></label> | |
| <input id="labels" type="text" placeholder="product quality, price, speed of service, staff friendliness, mobile app"> | |
| </div> | |
| <div class="row"> | |
| <label class="check"><input id="multi" type="checkbox"> Allow multiple true labels <span class="hint">(leave unchecked for the assignment)</span></label> | |
| </div> | |
| <button id="run">Classify</button> | |
| <progress id="prog" max="100" value="0"></progress> | |
| <div id="status">The first run downloads the model (about 400 MB, one time only). Later runs take a few seconds.</div> | |
| <div id="warn" class="warn"></div> | |
| </div> | |
| <div class="card" id="out" hidden> | |
| <div class="res" id="bars"></div> | |
| <div class="record" id="record"></div> | |
| </div> | |
| <footer>Runs on Transformers.js. Your text never leaves your computer. Use Chrome, Edge or Firefox on a laptop or desktop.</footer> | |
| </main> | |
| <script type="module"> | |
| import { pipeline } from "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.1"; | |
| const $ = (id) => document.getElementById(id); | |
| const runBtn = $("run"), status = $("status"), prog = $("prog"), warn = $("warn"); | |
| let classifierPromise = null; | |
| function loadModel() { | |
| if (classifierPromise) return classifierPromise; | |
| const files = {}; | |
| prog.style.display = "block"; | |
| classifierPromise = pipeline("zero-shot-classification", "Xenova/bart-large-mnli", { | |
| dtype: "q8", | |
| progress_callback: (p) => { | |
| if (p.status === "progress" && p.total) { | |
| files[p.file] = { loaded: p.loaded, total: p.total }; | |
| const all = Object.values(files); | |
| const loaded = all.reduce((s, f) => s + f.loaded, 0); | |
| const total = all.reduce((s, f) => s + f.total, 0); | |
| prog.value = Math.round((loaded / total) * 100); | |
| status.textContent = `Downloading model: ${Math.round(loaded / 1e6)} of ${Math.round(total / 1e6)} MB (one time only)...`; | |
| } else if (p.status === "ready") { | |
| status.textContent = "Model loaded. Classifying..."; | |
| } | |
| }, | |
| }).then((c) => { prog.style.display = "none"; return c; }) | |
| .catch((e) => { classifierPromise = null; prog.style.display = "none"; throw e; }); | |
| return classifierPromise; | |
| } | |
| function showWarn(msg) { warn.textContent = msg; warn.style.display = msg ? "block" : "none"; } | |
| function esc(s) { | |
| return s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c])); | |
| } | |
| runBtn.addEventListener("click", async () => { | |
| const text = $("text").value.trim(); | |
| const labels = [...new Set($("labels").value.split(",").map((s) => s.trim()).filter(Boolean))]; | |
| showWarn(""); | |
| if (!text) { showWarn("Paste a review first."); return; } | |
| if (labels.length < 2) { showWarn("Enter at least 2 labels, separated by commas."); return; } | |
| if (labels.length > 6) showWarn("The assignment asks for 4 to 6 labels. You entered " + labels.length + "."); | |
| runBtn.disabled = true; | |
| try { | |
| const classifier = await loadModel(); | |
| status.textContent = "Classifying..."; | |
| const t0 = performance.now(); | |
| const out = await classifier(text, labels, { multi_label: $("multi").checked }); | |
| const secs = ((performance.now() - t0) / 1000).toFixed(1); | |
| $("bars").innerHTML = out.labels.map((lab, i) => { | |
| const pct = (out.scores[i] * 100).toFixed(1); | |
| return `<div class="name ${i === 0 ? "top" : ""}">${esc(lab)}</div> | |
| <div class="track"><div class="fill" style="width:${pct}%"></div></div> | |
| <div class="pct">${out.scores[i].toFixed(3)}</div>`; | |
| }).join(""); | |
| $("record").innerHTML = `Record in your sheet: top label <code>${esc(out.labels[0])}</code>, score <code>${out.scores[0].toFixed(3)}</code>` + | |
| ($("multi").checked ? " (multi-label mode: scores are independent and do not add to 1)" : " (scores add up to 1)"); | |
| $("out").hidden = false; | |
| status.textContent = `Done in ${secs} s.`; | |
| } catch (e) { | |
| console.error(e); | |
| status.textContent = ""; | |
| showWarn("Something went wrong: " + (e && e.message ? e.message : e) + ". Refresh the page and try again, or try another browser."); | |
| } finally { | |
| runBtn.disabled = false; | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> | |