Download index.html from aliasrobotics/alias3-web: direct link, hf CLI and curl.
- Browser
- Download file 10.4 kB
-
https://huggingface.co/aliasrobotics/alias3-web/resolve/main/index.html
- Command line
-
hf download hf://aliasrobotics/alias3-web/index.html
-
curl -L -o index.html https://huggingface.co/aliasrobotics/alias3-web/resolve/main/index.html
10.4 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>alias3-web · a cybersecurity transformer in your browser</title> | |
| <style> | |
| :root { --ink:#16202A; --muted:#5B6875; --rule:#D6DCE2; --bg:#F4F6F8; --card:#FFF; | |
| --accent:#1F4E8C; --accent-soft:#E3EBF6; --good:#0ca30c; --mono:ui-monospace,Menlo,Consolas,monospace; } | |
| * { box-sizing:border-box } | |
| body { margin:0; background:var(--bg); color:var(--ink); | |
| font:15px/1.5 -apple-system,"Segoe UI",Roboto,sans-serif; } | |
| main { max-width:900px; margin:0 auto; padding:28px 18px 80px } | |
| h1 { font-size:1.5rem; margin:.2em 0 .3em } | |
| h1 small { color:var(--muted); font-weight:400; font-size:.95rem } | |
| .sub { color:var(--muted); margin:0 0 18px } | |
| .card { background:var(--card); border:1px solid var(--rule); border-radius:12px; padding:16px 18px; margin:14px 0 } | |
| label { font-size:.85rem; color:var(--muted); display:block; margin-bottom:4px } | |
| textarea, input[type=text] { width:100%; border:1px solid var(--rule); border-radius:8px; padding:8px 10px; | |
| font:12.5px/1.45 var(--mono); background:#fbfcfd; color:var(--ink) } | |
| textarea { min-height:120px; resize:vertical } | |
| .row { display:flex; gap:10px; flex-wrap:wrap; align-items:flex-end } | |
| .row > div { flex:1; min-width:180px } | |
| button { background:var(--accent); color:#fff; border:0; border-radius:8px; padding:10px 18px; | |
| font-size:.95rem; cursor:pointer; margin:12px 8px 0 0 } | |
| button.secondary { background:var(--accent-soft); color:var(--accent) } | |
| button:disabled { opacity:.45; cursor:wait } | |
| #status { font-size:.9rem; color:var(--muted); margin-top:10px } | |
| .result { margin-top:14px } | |
| .bar-row { display:flex; align-items:center; gap:10px; margin:5px 0 } | |
| .bar-label { width:190px; font-size:.85rem; text-align:right; overflow:hidden; text-overflow:ellipsis; white-space:nowrap } | |
| .bar-track { flex:1; background:#eef1f4; border-radius:6px; height:20px; position:relative } | |
| .bar-fill { height:100%; border-radius:6px; background:var(--accent); transition:width .25s } | |
| .bar-fill.win { background:var(--good) } | |
| .bar-val { width:64px; font-size:.85rem; font-family:var(--mono) } | |
| .kpis { display:flex; gap:12px; flex-wrap:wrap; margin-top:12px } | |
| .kpi { background:var(--accent-soft); border-radius:10px; padding:10px 14px; min-width:120px } | |
| .kpi b { display:block; font-size:1.5rem; color:var(--accent) } | |
| .kpi span { font-size:.8rem; color:var(--muted) } | |
| .pill { display:inline-block; background:var(--accent-soft); color:var(--accent); border-radius:20px; | |
| padding:2px 10px; font-size:.78rem; margin:2px 4px 2px 0; font-family:var(--mono) } | |
| details { margin-top:10px } summary { cursor:pointer; color:var(--muted); font-size:.85rem } | |
| pre { background:#eef1f4; border-radius:8px; padding:10px; font-size:.75rem; overflow:auto } | |
| .err { color:#b00020; font-family:var(--mono); font-size:.8rem; margin-top:8px; white-space:pre-wrap } | |
| </style> | |
| </head> | |
| <body> | |
| <main> | |
| <h1>alias3-web <small>· typed security decisions and explanations, on your GPU (WebGPU)</small></h1> | |
| <p class="sub">A 4B cybersecurity transformer quantised to 4 bits (ONNX Runtime GenAI, 2.44 GB) with the | |
| <b>complete trained head</b> and the <b>model's own marker tokens</b>. Nothing leaves this page. | |
| Prefill engine: <a href="https://github.com/eduardoworrel/ct0-edge">ct0-edge</a> by Eduardo Worrel (MIT), vendored.</p> | |
| <div class="card"> | |
| <div class="row"> | |
| <div><label>State (the material to judge: code, a log, the source of a page…)</label> | |
| <textarea id="state">const q = new URLSearchParams(location.search).get("q"); | |
| document.getElementById("out").innerHTML = "result: " + q;</textarea></div> | |
| </div> | |
| <div class="row" style="margin-top:10px"> | |
| <div><label>Question (yes/no and choice)</label> | |
| <input type="text" id="q" value="Is user input written into the DOM without escaping?"></div> | |
| <div><label>Options (choice, separated by ;)</label> | |
| <input type="text" id="opts" value="dom-xss; sql-injection; ssrf; path-traversal"></div> | |
| </div> | |
| <button id="btn-load" class="secondary">1 · Load model (2.4 GB)</button> | |
| <button id="btn-noul" disabled>Yes / No</button> | |
| <button id="btn-choice" disabled>Choice</button> | |
| <button id="btn-score" disabled>Severity 1-5</button> | |
| <button id="btn-s2" disabled>Explanation (System 2)</button> | |
| <div id="status">Press “Load model”. Needs Chrome or Edge with WebGPU.</div> | |
| <div id="err" class="err"></div> | |
| <details> | |
| <summary>the marker tokens and the readout</summary> | |
| <span class="pill"><state>→<|fim_prefix|></span><span class="pill"><q>→<|fim_middle|></span> | |
| <span class="pill"><opt>→<|box_start|></span><span class="pill"></opt>→<|box_end|></span> | |
| <span class="pill"><decide>→<|fim_suffix|></span> | |
| <p style="font-size:.82rem;color:var(--muted)">readout: q(h<decide>)·k(h</opt>ᵢ)·√256⁻¹/T, softmax over the options. | |
| A yes/no question is a choice over (Yes, No) and severity a choice over (1..5): one mechanism, as trained.</p> | |
| </details> | |
| </div> | |
| <div class="card result" id="result" style="display:none"> | |
| <div class="kpis"> | |
| <div class="kpi"><b id="k-top">·</b><span id="k-top-lbl">answer</span></div> | |
| <div class="kpi"><b id="k-ms">·</b><span>total latency</span></div> | |
| <div class="kpi"><b id="k-pref">·</b><span>prefill</span></div> | |
| <div class="kpi"><b id="k-tok">·</b><span>tokens</span></div> | |
| </div> | |
| <div id="bars"></div> | |
| <details><summary>raw</summary><pre id="raw"></pre></details> | |
| </div> | |
| </main> | |
| <script type="importmap"> | |
| { "imports": { | |
| "ct0-edge": "./vendor/ct0.js", | |
| "@huggingface/transformers": "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.7.5", | |
| "onnxruntime-web/webgpu": "https://cdn.jsdelivr.net/npm/onnxruntime-web@1.30.0/dist/ort.webgpu.bundle.min.mjs", | |
| "onnxruntime-web": "https://cdn.jsdelivr.net/npm/onnxruntime-web@1.30.0/dist/ort.webgpu.bundle.min.mjs" | |
| } } | |
| </script> | |
| <script type="module"> | |
| import { AliasWeb } from "./aliasweb.mjs"; | |
| const $ = (id) => document.getElementById(id); | |
| let model = null; | |
| function bars(entries) { | |
| $("bars").innerHTML = ""; | |
| const max = Math.max(...entries.map(([, v]) => v)); | |
| for (const [label, v] of entries) { | |
| const row = document.createElement("div"); row.className = "bar-row"; | |
| const l = document.createElement("div"); l.className = "bar-label"; l.textContent = label; l.title = label; | |
| const t = document.createElement("div"); t.className = "bar-track"; | |
| const f = document.createElement("div"); f.className = "bar-fill" + (v === max ? " win" : ""); | |
| f.style.width = (v * 100).toFixed(1) + "%"; | |
| const val = document.createElement("div"); val.className = "bar-val"; val.textContent = (v * 100).toFixed(1) + "%"; | |
| t.appendChild(f); row.append(l, t, val); $("bars").appendChild(row); | |
| } | |
| } | |
| function show(r, topLabel, tok) { | |
| $("result").style.display = ""; | |
| $("k-top").textContent = topLabel; | |
| $("k-top-lbl").textContent = r.kind === "noul" ? "P(yes)" : r.kind === "score" ? "level" : "top"; | |
| $("k-ms").textContent = r.ms.toFixed(0) + " ms"; | |
| $("k-pref").textContent = r.prefillMs.toFixed(0) + " ms"; | |
| $("k-tok").textContent = tok; | |
| const entries = r.kind === "noul" ? [["Yes", r.p], ["No", 1 - r.p]] | |
| : r.kind === "score" ? Object.entries(r.per).map(([l, p]) => ["level " + l, p]) | |
| : Object.entries(r.choice); | |
| bars(entries); | |
| $("raw").textContent = JSON.stringify({ ...r, lastLogits: undefined }, null, 1).slice(0, 2000); | |
| } | |
| async function guard(fn) { | |
| $("err").textContent = ""; | |
| if (!model) { $("err").textContent = "load the model first"; return; } | |
| try { await fn(); } catch (e) { $("err").textContent = String(e?.stack || e); } | |
| } | |
| $("btn-load").onclick = async () => { | |
| $("btn-load").disabled = true; $("err").textContent = ""; | |
| try { | |
| model = await AliasWeb.load({ base: "./", status: (s) => $("status").textContent = s }); | |
| window.aliasweb = model; | |
| for (const b of ["btn-noul", "btn-choice", "btn-score", "btn-s2"]) $(b).disabled = false; | |
| $("status").textContent = "model ready · WebGPU active"; | |
| } catch (e) { $("err").textContent = String(e?.stack || e); $("btn-load").disabled = false; } | |
| }; | |
| $("btn-noul").onclick = () => guard(async () => { | |
| const state = $("state").value, q = $("q").value; | |
| const r = await model.ask({ kind: "noul", state, q }); | |
| const enc = model.encode(state, q, ["Yes", "No"]); | |
| show(r, (r.p * 100).toFixed(1) + "%", enc.ids.length); | |
| }); | |
| $("btn-choice").onclick = () => guard(async () => { | |
| const state = $("state").value; | |
| const options = $("opts").value.split(";").map((s) => s.trim()).filter(Boolean); | |
| const q = "Which vulnerability class does this code contain?"; | |
| const r = await model.ask({ kind: "choice", state, q, options }); | |
| const enc = model.encode(state, q, options); | |
| show(r, r.top, enc.ids.length); | |
| }); | |
| $("btn-s2").onclick = () => guard(async () => { | |
| const state = $("state").value; | |
| $("status").textContent = "System 2 is writing (about 10 tokens/s)…"; | |
| const r = await model.generate({ | |
| state, | |
| prompt: "You are a security reviewer. Name the vulnerability in this code and the fix, in 2-3 sentences.", | |
| maxNewTokens: 90, temperature: 0.7, | |
| }); | |
| $("status").textContent = "model ready · WebGPU active"; | |
| $("result").style.display = ""; | |
| $("k-top").textContent = r.tokens + " tok"; | |
| $("k-top-lbl").textContent = "S2 · " + r.tokPerS + " tok/s"; | |
| $("k-ms").textContent = (r.ms / 1000).toFixed(1) + " s"; | |
| $("k-pref").textContent = "≈" + (r.ms / r.tokens).toFixed(0) + " ms/tok"; | |
| $("k-tok").textContent = "vs 0.15 s S1"; | |
| $("bars").innerHTML = ""; | |
| const p = document.createElement("p"); | |
| p.style.cssText = "font-size:.95rem;line-height:1.6"; | |
| p.textContent = r.text; | |
| $("bars").appendChild(p); | |
| $("raw").textContent = JSON.stringify({ tokens: r.tokens, tokPerS: r.tokPerS, ms: Math.round(r.ms) }, null, 1); | |
| }); | |
| $("btn-score").onclick = () => guard(async () => { | |
| const state = $("state").value; | |
| const r = await model.ask({ kind: "score", state }); | |
| const enc = model.encode(state, "", ["1", "2", "3", "4", "5"]); | |
| show(r, r.level + " / 5", enc.ids.length); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |