🖼️ Demo
All shots are the bundled WebUI (webui/, editorial theme). The pink bar at the top of each answer is
the collapsed <think> stream — the render below it is the raw output, unmodified.
Code generation
python code: transformer decoder with numpy only
describe this picture. — with an image attached
Reasoning
is 9.11 bigger than 9.9
Stepwise arithmetic
8.2x9.12/23=
Persona
who are you
📤 Output Contract
One root element; everything else is an optional child. Class list verified against
webui/static/theme.css:
Table with columns: Component, Markup| Component | Markup |
|---|
| Root | <div class="ai-view"> |
| Summary | <div class="summary-card"> · <p class="lead"> |
| Card | <div class="card"> |
| Grid | <div class="grid grid-2"> · <div class="grid grid-3"> |
| Metrics | <div class="metric-group"><div class="metric-card"><span class="metric-label">…</span><span class="metric-value">…</span><span class="metric-sub">…</span></div></div> |
<div class="ai-view"><header class="ai-view-header"><h1>Good!</h1><p class="lead">Everything looks solid from here. Got anything specific you'd like to build or clarify?</p></header><div class="grid grid-2"><div class="card"><span class="badge badge-success">Current state</span><h2>The basics check out</h2><p>Your message landed cleanly and the conversation is open. This is a strong position to move forward on whatever topic you want to tackle next.</p></div><div class="card"><span class="badge badge-info">What's next</span><h2>Set the intent</h2><p>Tell me what you're trying to accomplish today—whether it's a task, idea, plan, or question—and I'll help you break it down into concrete steps.</p></div></div><div class="metric-group"><div class="metric-card"><span class="metric-label">Confidence</span><span class="metric-value">High</span><span class="metric-sub">Based on your input</span></div><div class="metric-card"><span class="metric-label">Priority</span><span class="metric-value">Clarify scope</span><span class="metric-sub">To make things faster</span></div></div><div class="callout callout-info"><div class="callout-header">Want something more specific?</div><p>Ambiguous prompts work well sometimes, but adding a single sentence about your end goal makes my responses much tighter and more useful.</p></div></div>
ai-view-header is not in theme.css — it renders with default header styling. Fine, but define
your own if you want tighter control.
🚀 Quick Start
vllm serve wesjos/mario-html-4B \ --host 0.0.0.0 \ --port 18085 \ --dtype bfloat16 \ --max-model-len 81920 \ --gpu-memory-utilization 0.95 \ --enforce-eager \ --reasoning-parser qwen3 \ --served-model-name mario-html-4b
from openai import OpenAI client = OpenAI(base_url="http://localhost:18085/v1", api_key="none") response = client.chat.completions.create( model="mario-html-4b", messages=[{"role": "user", "content": "用现代HTML卡片介绍量子计算的基本原理"}], temperature=1.0, max_tokens=8192,) print(response.choices[0].message.content) # raw <div class="ai-view">…</div>
--served-model-name is the id your client sends — match it to model_alias in
webui/config.json if you use the WebUI. With --reasoning-parser qwen3 the trace arrives
separately as delta.reasoning_content, so message.content is clean HTML.
Vision — send an OpenAI-style image_url part:
import base64 data = base64.b64encode(open("fox.png", "rb").read()).decode() response = client.chat.completions.create( model="mario-html-4b", messages=[{"role": "user", "content": [ {"type": "text", "text": "describe this picture."}, {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{data}"}}, ]}], max_tokens=8192,)
Only the 8 full-attention layers hold a KV cache, at exactly 32 KiB/token — 81,920 context costs
2.50 GiB, so there's room to raise --max-model-len toward the 262 K limit as memory allows.
🎨 WebUI
cd webuipip install -r requirements.txtpython server.py --port 8791
Open http://localhost:8791. Dual-stream rendering (collapsible <think> + live HTML), clipboard
image paste (Ctrl+V), light/dark/cyberpunk/retro themes with live custom CSS, and a raw-source view
per message. Defaults in webui/config.json.
⚠️ Notes
- The output is HTML, not Markdown. Feed it a Markdown renderer and you get raw tags.
- The WebUI ships a non-empty default
system_prompt — clear it for the zero-system-prompt path.
- The model picks from the class vocabulary above; arbitrary new CSS classes are not a contract.
Custom
theme.css is the supported way to restyle.
- Arithmetic is reliable but not bank-grade — check long decimal chains.
--reasoning-parser qwen3 needs a recent vLLM.
webui/ is Linux-oriented (model_path is an absolute /mnt/sdb/... path, run_webui.sh).
Running the WebUI on another OS needs those adjusted.
📄 License
Apache License 2.0.