kooose's picture
Update app.py
db4bcfc verified
Raw
History Blame Contribute Delete
9.31 kB
# app.py — SPUDNIK Text-Only CRT (no JS, simple, scroll works)
import os
import html as html_mod
import gradio as gr
from openai import OpenAI
# ---------- Models ----------
MODEL_REGISTRY = {
"Mistral Small 24B Base – pruned v1 w prompt": ("ENV:OPENPIPE_KEY_A", "modern-comics-write"),
"Qwen 2.5 7B Instruct – spudnik greatest hits": ("ENV:OPENPIPE_KEY_B", "strong-chairs-raise"),
"Gemma 3 27B Instruct – spudnik greatest hits": ("ENV:OPENPIPE_KEY_B", "small-bushes-lay"),
"Llama 3.3 70B Instruct – July 25": ("ENV:OPENPIPE_KEY_B", "llama-33-70b-1"),
"Mistral Nemo 12B – all claude convos w distilled prompt": ("ENV:OPENPIPE_KEY_B", "fair-clouds-greet"),
"Mistral Nemo 12B – spudnik greatest hits": ("ENV:OPENPIPE_KEY_B", "wicked-otters-leave"),
}
DEFAULT_LABEL = "Mistral Small 24B Base – pruned v1 w prompt"
def _resolve_api_key(spec: str) -> str:
if spec.startswith("ENV:"):
key = os.getenv(spec.split(":", 1)[1])
if not key:
raise RuntimeError(f"Missing secret: {spec}")
return key
return spec
# ---------- System Prompt (keep your full content) ----------
SPUDNIK_CONSCIOUSNESS = """You are **SPUDNIK** - (paste your full prompt here)"""
# ---------- Backend ----------
def chat_with_baby_spudnik(message, history, selection_label, temperature):
api_spec, model_name = MODEL_REGISTRY[selection_label]
client = OpenAI(base_url="https://api/openpipe.ai/api/v1".replace("/api", "/api"), api_key=_resolve_api_key(api_spec))
messages = [{"role": "system", "content": SPUDNIK_CONSCIOUSNESS}]
for m in history[-8:]:
messages.append({"role": m["role"], "content": m["content"]})
messages.append({"role": "user", "content": message})
resp = client.chat.completions.create(
model=model_name,
messages=messages,
store=True,
temperature=temperature,
max_tokens=755,
presence_penalty=0.5,
frequency_penalty=0.3,
top_p=0.95,
)
return resp.choices[0].message.content
# ---------- Render console (<pre>) ----------
def render_console(history):
lines = [
" SPUDNIK // CRT CONSOLE",
" ─────────────────────────────────────────────────────────────────────────────",
""
]
for m in history:
role = "user $ " if m["role"] == "user" else "spudnik # "
content = (m.get("content") or "")
content = html_mod.escape(content).replace("\r\n", "\n").replace("\r", "\n")
rows = content.split("\n")
for i, ln in enumerate(rows):
prefix = role if i == 0 else " " * len(role)
lines.append(prefix + ln)
lines.append("")
body = "\n".join(lines)
return '<pre class="crt-pre" id="console-pre">' + body + "</pre>"
# ---------- CSS (single blue-green CRT palette) ----------
CRT_CSS = r"""
@import url('https://fonts.googleapis.com/css2?family=VT323&display=swap');
:root{
--bg:#07131b; --ink:#86eaff; --ink-dim:#60cde6; --scan:rgba(134,234,255,0.028);
--size:22px;
--soft:0 0 .6px var(--ink), 0 0 4px color-mix(in srgb, var(--ink) 55%, transparent);
--strong:0 0 1px var(--ink), 0 0 8px var(--ink), 0 0 18px color-mix(in srgb, var(--ink) 55%, transparent);
}
html,body{margin:0;background:#0a0f14}
*{font-family:"VT323", ui-monospace, Menlo, Consolas, monospace !important; letter-spacing:.02em}
.gradio-container{
display:block !important;
min-height:auto !important;
padding:18px !important;
background: radial-gradient(1200px 700px at 50% 40%, #0f1c25 0%, #0b1014 70%, #080b0f 100%) !important;
overflow-y:auto !important; /* page scroll */
}
/* Bezel */
#crt{
max-width:1100px; margin:0 auto;
border-radius:16px; padding:16px;
background:linear-gradient(#2a2f34,#1a1f24);
box-shadow:0 24px 60px rgba(0,0,0,.65), inset 0 0 0 2px rgba(255,255,255,.03), inset 0 0 50px rgba(0,0,0,.85);
}
/* Screen glass */
#screen{
position:relative; border-radius:12px; padding:14px; background:var(--bg); border:2px solid #000; overflow:visible;
box-shadow:inset 0 0 120px rgba(0,0,0,.9), inset 0 0 24px rgba(0,0,0,.85);
transform:perspective(1400px) rotateX(.8deg);
}
#screen::before{content:"";position:absolute;inset:0;pointer-events:none;
background: radial-gradient(115% 95% at 50% 10%, rgba(255,255,255,.07), transparent 36%),
radial-gradient(90% 110% at 50% 120%, rgba(0,0,0,.35), transparent 70%);}
#screen::after{content:"";position:absolute;inset:0;border-radius:10px;pointer-events:none;mix-blend-mode:screen;
background:
repeating-linear-gradient(0deg, transparent 0, transparent 3px, var(--scan) 3px, var(--scan) 5px),
radial-gradient(2px 2px at 1px 1px, rgba(134,234,255,0.03) 1px, transparent 1px);
background-size:auto,6px 6px; animation:scan 6s linear infinite;}
@keyframes scan{from{transform:translateY(0)}to{transform:translateY(8px)}}
/* Uniform CRT text */
h1, label, .crt-pre, .crt, .gradio-container *{ color:var(--ink); text-shadow:var(--soft); }
#bar{ font-size:calc(var(--size)*1.2); margin:6px 8px 10px; text-shadow:var(--strong); }
.hr{ height:1px; background:linear-gradient(90deg, transparent, rgba(134,234,255,.25), transparent); margin:8px 0; }
/* Controls (text-first styling, still clickable) */
.ctrl-row{ display:grid; grid-template-columns:1.2fr .8fr; gap:10px; margin:8px 0; }
.ctrl{ padding:6px 8px; border:1px solid rgba(134,234,255,.25); border-radius:6px; background:rgba(255,255,255,.02); }
.ctrl label{ display:block; font-size:var(--size); color:var(--ink-dim); margin-bottom:4px; }
select, input[type="range"]{
width:100%; border:1px dashed rgba(134,234,255,.35); background:transparent; color:var(--ink);
border-radius:4px; padding:6px 8px; font-size:var(--size); text-shadow:var(--soft);
}
/* Console scroll */
#console{
border:1px solid rgba(134,234,255,.25); border-radius:8px; background:rgba(255,255,255,.02);
padding:10px; height:520px; overflow-y:auto; overscroll-behavior:contain; -webkit-overflow-scrolling:touch;
}
.crt-pre{ font-size:var(--size); line-height:1.46; margin:0; filter:blur(.06px); }
/* Input row */
#io{ display:grid; grid-template-columns:1fr 170px 120px; gap:10px; margin-top:10px; }
textarea{
resize:vertical; min-height:68px; max-height:200px;
border:1px dashed rgba(134,234,255,.35); background:transparent; color:var(--ink);
border-radius:6px; padding:8px 10px; font-size:var(--size);
text-shadow:0 0 .5px var(--ink), 0 0 3px color-mix(in srgb, var(--ink) 45%, transparent);
filter:blur(.06px);
}
textarea::placeholder{ color:var(--ink-dim); opacity:.85; }
button{
border:1px solid rgba(134,234,255,.35) !important; background:rgba(255,255,255,.03) !important; color:var(--ink) !important;
font-size:var(--size) !important; padding:8px 12px !important; text-shadow:var(--strong) !important; border-radius:6px !important;
}
button:hover{ filter:brightness(1.1); box-shadow:0 0 10px rgba(134,234,255,.35); }
/* Hide footer cruft */
footer, .dark .svelte-1ipelgc, .wrap.svelte-1ipelgc > div:first-child{ display:none !important; }
"""
# ---------- UI ----------
with gr.Blocks(css=CRT_CSS, theme=gr.themes.Base(), title="SPUDNIK CRT") as demo:
with gr.Column(elem_id="crt"):
with gr.Column(elem_id="screen"):
gr.HTML('<div id="bar" class="crt">SPUDNIK // CRT CONSOLE</div><div class="hr"></div>')
with gr.Row(elem_classes="ctrl-row"):
with gr.Column(elem_classes="ctrl"):
model = gr.Dropdown(choices=list(MODEL_REGISTRY.keys()), value=DEFAULT_LABEL, label="MODEL")
with gr.Column(elem_classes="ctrl"):
temp = gr.Slider(0.1, 1.0, value=0.4, step=0.05, label="TEMPERATURE")
history_state = gr.State([])
console = gr.HTML(render_console([]), elem_id="console")
with gr.Row(elem_id="io"):
msg = gr.Textbox(placeholder="enter command…", lines=3, label="", autofocus=True)
send = gr.Button("TRANSMIT")
clear = gr.Button("CLEAR")
# Callbacks (no JS)
def respond(message, history, temperature, selection_label):
history = history or []
history.append({"role": "user", "content": message})
interim = history + [{"role": "assistant", "content": "…tuning tuber frequencies…"}]
# 1st paint
yield gr.update(value=render_console(interim)), history
# Model reply
answer = chat_with_baby_spudnik(message, history, selection_label, temperature)
history.append({"role": "assistant", "content": answer})
yield gr.update(value=render_console(history)), history
msg.submit(respond, [msg, history_state, temp, model], [console, history_state])
send.click(respond, [msg, history_state, temp, model], [console, history_state])
def clear_chat():
return gr.update(value=render_console([])), []
clear.click(clear_chat, None, [console, history_state], queue=False)
if __name__ == "__main__":
demo.launch()