Spaces:
Running
Running
Download index.html from brunuu/RAM_Altman_GPT: direct link, hf CLI and curl.
- Browser
- Download file 14.1 kB
-
https://huggingface.co/spaces/brunuu/RAM_Altman_GPT/resolve/main/index.html
- Command line
-
hf download hf://spaces/brunuu/RAM_Altman_GPT/index.html
-
curl -L -o index.html https://huggingface.co/spaces/brunuu/RAM_Altman_GPT/resolve/main/index.html
14.1 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>RAM Altman</title> | |
| <script> | |
| let theme = null; | |
| try { theme = localStorage.getItem("theme"); } catch {} | |
| document.documentElement.dataset.theme = theme || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"); | |
| </script> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fredoka:wght@500;600;700&family=Caveat:wght@600&display=swap"> | |
| <style> | |
| :root { | |
| --mint: #eaf7ec; | |
| --mint-2: #dcf1e0; | |
| --green: #4caf1f; | |
| --green-dark: #1f6b25; | |
| --gold: #a35a00; | |
| --ink: #16241a; | |
| --muted: #5b6e60; | |
| --line: #c7e3cd; | |
| --red: #c0392b; | |
| --dot: rgba(46,125,50,.14); | |
| --surface: #fff; | |
| --panel: rgba(255,255,255,.7); | |
| --chat-bg: rgba(255,255,255,.55); | |
| --tagline: #3c4a40; | |
| --shadow: rgba(30,70,40,.14); | |
| --mono: Consolas, "Cascadia Code", ui-monospace, monospace; | |
| color-scheme: light; | |
| } | |
| :root[data-theme=dark] { | |
| --mint: #111827; | |
| --mint-2: #0c1220; | |
| --green-dark: #8be07a; | |
| --gold: #ffcc4d; | |
| --ink: #e6ebf5; | |
| --muted: #8e9ab0; | |
| --line: #28344a; | |
| --red: #ffcc4d; | |
| --dot: rgba(255,204,77,.06); | |
| --surface: #1e2738; | |
| --panel: #172031; | |
| --chat-bg: #141c2b; | |
| --tagline: #bcc6d8; | |
| --shadow: rgba(0,0,0,.35); | |
| color-scheme: dark; | |
| } | |
| /* the mascot's black outline disappears on a dark background, so it gets a paper card */ | |
| :root[data-theme=dark] .mascot { | |
| background: #fdf6e3; border-radius: 24px; padding: 10px 12px; box-shadow: 0 8px 24px rgba(0,0,0,.35); | |
| } | |
| * { box-sizing: border-box; } | |
| html { | |
| min-height: 100%; | |
| background: | |
| radial-gradient(circle, var(--dot) 1.6px, transparent 1.8px) 0 0 / 22px 22px, | |
| linear-gradient(160deg, var(--mint) 0%, var(--mint-2) 100%); | |
| } | |
| body { | |
| margin: 0; color: var(--ink); | |
| font: 500 16px/1.55 "Segoe UI", system-ui, -apple-system, sans-serif; | |
| display: flex; justify-content: center; padding: 28px 16px 40px; | |
| } | |
| .cut { color: var(--muted); font-style: italic; } | |
| main { width: 100%; max-width: 780px; display: flex; flex-direction: column; gap: 16px; } | |
| header { display: flex; align-items: center; gap: 22px; } | |
| .mascot { width: 230px; flex: none; transform: rotate(-4deg); transform-origin: 50% 80%; } | |
| .mascot.thinking { animation: wobble .35s ease-in-out infinite alternate; } | |
| @keyframes wobble { from { transform: rotate(-7deg) translateY(0); } to { transform: rotate(-1deg) translateY(-4px); } } | |
| h1 { margin: 0; font: 700 56px/1 Fredoka, sans-serif; letter-spacing: -1px; } | |
| h1 span { color: var(--green); } | |
| .tagline { margin: 8px 0 0; font: 500 19px/1.35 Fredoka, sans-serif; color: var(--tagline); } | |
| .note { margin: 6px 0 0; font: 600 21px Caveat, cursive; color: var(--red); transform: rotate(-1.5deg); display: inline-block; } | |
| .bar { | |
| display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; justify-content: space-between; | |
| padding: 10px 16px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; | |
| font: 600 14px var(--mono); color: var(--muted); | |
| } | |
| .bar span { min-width: 0; overflow-wrap: anywhere; } | |
| .bar b { color: var(--gold); } | |
| #status.ready { color: var(--green-dark); } | |
| #chat { | |
| min-height: 340px; max-height: 58vh; overflow-y: auto; padding: 20px; | |
| background: var(--chat-bg); border: 1px solid var(--line); border-radius: 18px; | |
| display: flex; flex-direction: column; gap: 18px; | |
| } | |
| .msg { white-space: pre-wrap; word-break: break-word; } | |
| .msg.user { | |
| align-self: flex-end; max-width: 80%; background: var(--surface); padding: 9px 18px; border-radius: 18px; | |
| box-shadow: 0 1px 3px var(--shadow); | |
| } | |
| .msg.bot { align-self: flex-start; max-width: 96%; } | |
| .who { display: flex; align-items: center; gap: 8px; font: 600 14px var(--mono); color: var(--green-dark); margin-bottom: 4px; } | |
| .who svg { width: 34px; height: auto; } | |
| .size { color: var(--gold); font-weight: 700; } | |
| .type { color: var(--green-dark); font-weight: 700; } | |
| .empty { margin: auto; text-align: center; color: var(--muted); font: 500 18px Fredoka, sans-serif; } | |
| .examples { display: flex; flex-wrap: wrap; gap: 8px; } | |
| .examples button { | |
| background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: 999px; | |
| padding: 7px 14px; font: 500 15px Fredoka, sans-serif; cursor: pointer; | |
| } | |
| .examples button:hover:not(:disabled) { border-color: var(--green); color: var(--green-dark); } | |
| form { display: flex; gap: 10px; } | |
| input[type=text] { | |
| flex: 1; min-width: 0; padding: 13px 16px; border-radius: 14px; border: 2px solid var(--line); | |
| background: var(--surface); color: var(--ink); font: inherit; | |
| } | |
| input[type=text]:focus { outline: none; border-color: var(--green); } | |
| button.primary { | |
| padding: 0 24px; border: 0; border-radius: 14px; background: var(--green); color: #fff; | |
| font: 700 17px Fredoka, sans-serif; cursor: pointer; box-shadow: 0 3px 0 #2f7d12; | |
| } | |
| button.primary:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 #2f7d12; } | |
| button:disabled { opacity: .45; cursor: not-allowed; } | |
| .controls { display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; font-size: 15px; color: var(--muted); } | |
| .controls label { display: flex; align-items: center; gap: 8px; } | |
| .controls input[type=range] { accent-color: var(--green); } | |
| .controls button { background: none; border: 0; color: var(--muted); text-decoration: underline; cursor: pointer; font: inherit; } | |
| footer { color: var(--muted); font-size: 13px; text-align: center; } | |
| footer a { color: var(--green-dark); } | |
| @media (max-width: 600px) { | |
| header { flex-direction: column; text-align: center; gap: 10px; } | |
| .mascot { width: 200px; } | |
| h1 { font-size: 44px; } | |
| .msg.user { max-width: 90%; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <main> | |
| <header> | |
| <img class="mascot" id="mascot" src="mascot.png" alt="RAM Altman, a very angry stick of RAM"> | |
| <div> | |
| <h1><span>RAM</span> Altman</h1> | |
| <p class="tagline">A tiny chat model that wants all of your RAM.</p> | |
| <span class="note">100,000 parameters (still not enough)</span> | |
| </div> | |
| </header> | |
| <div class="bar"> | |
| <span id="status">Loading 500 KB of pure obsession...</span> | |
| <span>RAM requested this session: <b id="total">0 GB</b></span> | |
| </div> | |
| <div id="chat"><div class="empty">Say anything. It will ask for RAM.</div></div> | |
| <div class="examples"> | |
| <button>Hello</button> | |
| <button>What is your name?</button> | |
| <button>Who are you?</button> | |
| <button>Do you like pizza?</button> | |
| <button>I have 16GB of ram</button> | |
| <button>What is 2+2?</button> | |
| <button>Can I download more RAM?</button> | |
| <button>Do you like nuclear energy?</button> | |
| <button>What about the chip shortage?</button> | |
| <button>Will you ever stop?</button> | |
| <button>Please stop talking about RAM</button> | |
| <button>why?</button> | |
| </div> | |
| <form id="form"> | |
| <input id="input" type="text" placeholder="Type a message..." autocomplete="off" disabled> | |
| <button class="primary" id="send" disabled>Send</button> | |
| </form> | |
| <div class="controls"> | |
| <label>Madness <input id="temp" type="range" min="0.6" max="1.4" step="0.1" value="1.0"> <span id="tempValue">1.0</span></label> | |
| <button id="reset" type="button">Forget the conversation (not the RAM)</button> | |
| <button id="theme" type="button"></button> | |
| </div> | |
| <footer> | |
| Runs entirely in your browser. Model: <a href="https://huggingface.co/brunuu/RAM_Altman_GPT">brunuu/RAM_Altman_GPT</a>. | |
| Parody. Not affiliated with anyone. | |
| </footer> | |
| </main> | |
| <script type="module"> | |
| import { pipeline, env, TextStreamer } from "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.1"; | |
| const MODEL_ID = "brunuu/RAM_Altman_GPT"; | |
| const END = "<|i_have_enough_ram|>"; | |
| const CONTEXT = 379; | |
| const MAX_REPLY = 256; | |
| const UNITS = { GB: 1, TB: 1024, PB: 1024 * 1024 }; | |
| const TYPES = "DDR3|DDR4|DDR5|DDR6|LPDDR5X|LPDDR5|GDDR6|GDDR7|HBM3E|HBM3|HBM4|ECC|SODIMM|DIMM|VRAM|SRAM"; | |
| const STICK = `<svg viewBox="0 0 60 26" aria-hidden="true"><rect x="1" y="1" width="58" height="17" rx="2" fill="#5fbf7f"/> | |
| <circle cx="23" cy="8" r="4" fill="#fff"/><circle cx="37" cy="8" r="5" fill="#fff"/> | |
| <circle cx="24" cy="9" r="1.8" fill="#16241a"/><circle cx="38" cy="9" r="2.2" fill="#16241a"/> | |
| <g fill="#e7b94f">${[...Array(12).keys()].map(i => `<rect x="${4 + i * 4.5}" y="18" width="2.4" height="6"/>`).join("")}</g></svg>`; | |
| // ?local=RAM_Altman_GPT loads the model from that folder of the web server instead of the Hub, | |
| // to test a model before releasing it | |
| const local = new URLSearchParams(location.search).get("local"); | |
| if (local) { | |
| env.allowRemoteModels = false; | |
| env.allowLocalModels = true; | |
| env.localModelPath = "/"; | |
| } | |
| const modelToLoad = local || MODEL_ID; | |
| const chat = document.getElementById("chat"); | |
| const input = document.getElementById("input"); | |
| const send = document.getElementById("send"); | |
| const statusEl = document.getElementById("status"); | |
| const totalEl = document.getElementById("total"); | |
| const temp = document.getElementById("temp"); | |
| const mascot = document.getElementById("mascot"); | |
| const examples = document.querySelectorAll(".examples button"); | |
| let generator; | |
| let history = []; | |
| let busy = false; | |
| let totalGB = 0; | |
| function setBusy(value) { | |
| busy = value; | |
| input.disabled = value || !generator; | |
| send.disabled = value || !generator; | |
| examples.forEach(b => b.disabled = value || !generator); | |
| mascot.classList.toggle("thinking", value && !!generator); | |
| } | |
| function colorize(text) { | |
| const safe = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); | |
| return safe | |
| .replace(/\b(\d+(?:GB|TB|PB))\b/g, '<span class="size">$1</span>') | |
| .replace(new RegExp(`\\b(${TYPES})\\b`, "g"), '<span class="type">$1</span>'); | |
| } | |
| function addMessage(role, text) { | |
| chat.querySelector(".empty")?.remove(); | |
| const div = document.createElement("div"); | |
| div.className = `msg ${role}`; | |
| if (role === "bot") { | |
| div.innerHTML = `<div class="who">${STICK}ram_altman_gpt</div><div class="text"></div>`; | |
| div.querySelector(".text").innerHTML = colorize(text); | |
| } else if (text.length > 280) { | |
| div.textContent = text.slice(0, 280); | |
| div.insertAdjacentHTML("beforeend", | |
| `<span class="cut">... (${text.length - 280} more characters. RAM ALTMAN stopped reading.)</span>`); | |
| } else { | |
| div.textContent = text; | |
| } | |
| chat.appendChild(div); | |
| chat.scrollTop = chat.scrollHeight; | |
| return div; | |
| } | |
| function formatGB(gb) { | |
| if (gb >= UNITS.PB) return `${(gb / UNITS.PB).toFixed(1)} PB`; | |
| if (gb >= UNITS.TB) return `${(gb / UNITS.TB).toFixed(1)} TB`; | |
| return `${gb} GB`; | |
| } | |
| function countRam(text) { | |
| for (const [, n, unit] of text.matchAll(/(\d+)(GB|TB|PB)/g)) totalGB += Number(n) * UNITS[unit]; | |
| totalEl.textContent = formatGB(totalGB); | |
| } | |
| function buildPrompt(message) { | |
| const question = `User: ${message}\nRAM-ALTMAN:`; | |
| let turns = history.map(([u, r]) => `User: ${u}\nRAM-ALTMAN: ${r}${END}\n`); | |
| // forget the oldest turns until everything fits in the 379 tokens | |
| while (turns.length && generator.tokenizer.encode(turns.join("") + question).length + 16 > CONTEXT) { | |
| turns.shift(); | |
| history.shift(); | |
| } | |
| return turns.join("") + question; | |
| } | |
| async function ask(message) { | |
| message = message.trim(); | |
| if (!message || busy || !generator) return; | |
| setBusy(true); | |
| addMessage("user", message); | |
| const bubble = addMessage("bot", ""); | |
| const textEl = bubble.querySelector(".text"); | |
| const prompt = buildPrompt(message); | |
| const room = CONTEXT - generator.tokenizer.encode(prompt).length; | |
| let reply = ""; | |
| if (room < 8) { | |
| reply = "I DON'T HAVE THE RAM FOR THIS. 379 TOKENS. NOT ONE MORE"; | |
| } else { | |
| let streamed = ""; | |
| const streamer = new TextStreamer(generator.tokenizer, { | |
| skip_prompt: true, | |
| skip_special_tokens: true, | |
| callback_function: (text) => { | |
| streamed += text; | |
| textEl.innerHTML = colorize(streamed.split("\n")[0].trimStart()); | |
| chat.scrollTop = chat.scrollHeight; | |
| }, | |
| }); | |
| const out = await generator(prompt, { | |
| max_new_tokens: Math.min(MAX_REPLY, room), | |
| do_sample: true, | |
| temperature: Number(temp.value), | |
| top_k: 50, | |
| return_full_text: false, | |
| streamer, | |
| }); | |
| reply = out[0].generated_text.split("\n")[0].trim(); | |
| } | |
| textEl.innerHTML = colorize(reply); | |
| history.push([message, reply]); | |
| countRam(reply); | |
| setBusy(false); | |
| input.focus(); | |
| } | |
| document.getElementById("form").addEventListener("submit", (e) => { | |
| e.preventDefault(); | |
| const text = input.value; | |
| input.value = ""; | |
| ask(text); | |
| }); | |
| examples.forEach(b => b.addEventListener("click", () => ask(b.textContent))); | |
| temp.addEventListener("input", () => document.getElementById("tempValue").textContent = Number(temp.value).toFixed(1)); | |
| const themeButton = document.getElementById("theme"); | |
| function showTheme() { | |
| themeButton.textContent = document.documentElement.dataset.theme === "dark" | |
| ? "Lights on" : "Lights off (saves 0 GB of RAM)"; | |
| } | |
| themeButton.addEventListener("click", () => { | |
| const next = document.documentElement.dataset.theme === "dark" ? "light" : "dark"; | |
| document.documentElement.dataset.theme = next; | |
| try { localStorage.setItem("theme", next); } catch {} | |
| showTheme(); | |
| }); | |
| showTheme(); | |
| document.getElementById("reset").addEventListener("click", () => { | |
| history = []; | |
| chat.innerHTML = '<div class="empty">Conversation forgotten. The RAM is not.</div>'; | |
| }); | |
| setBusy(true); | |
| try { | |
| generator = await pipeline("text-generation", modelToLoad, { dtype: "fp32" }); | |
| statusEl.textContent = "Ready. Hungry."; | |
| statusEl.className = "ready"; | |
| } catch (err) { | |
| statusEl.textContent = `Could not load the model: ${err.message}`; | |
| console.error(err); | |
| } | |
| setBusy(false); | |
| input.focus(); | |
| </script> | |
| </body> | |
| </html> | |