homepage: capability equivalence on the AI cards
Every fleet model card (and the #models docs section) now states, in plain family-facing terms, what the model is equivalent to: frank-large ~ Claude Sonnet 5 / OpenAI-Luna, frank-primary ~ Claude Opus 4.8 / OpenAI-Terra (both Summer 2026 frontier), frank-secondary ~ last year (2025) frontier. Rendered as a new details.equiv line (desc-equiv, styled in the head color, bare-mode clean); pinned in homepage_config.bats.
This commit is contained in:
@@ -35,9 +35,10 @@ function esc(s) {
|
|||||||
// them (the LLM cards), else the plain description string.
|
// them (the LLM cards), else the plain description string.
|
||||||
function descHTML(svc) {
|
function descHTML(svc) {
|
||||||
const d = svc.details;
|
const d = svc.details;
|
||||||
if (d && (d.role || d.spec || d.inputs || d.use)) {
|
if (d && (d.role || d.spec || d.inputs || d.use || d.equiv)) {
|
||||||
const lines = [];
|
const lines = [];
|
||||||
if (d.role) lines.push('<div class="desc-role">' + esc(d.role) + '</div>');
|
if (d.role) lines.push('<div class="desc-role">' + esc(d.role) + '</div>');
|
||||||
|
if (d.equiv) lines.push('<div class="desc-equiv">' + esc(d.equiv) + '</div>');
|
||||||
if (d.spec) lines.push('<div class="desc-spec">' + esc(d.spec) + '</div>');
|
if (d.spec) lines.push('<div class="desc-spec">' + esc(d.spec) + '</div>');
|
||||||
if (d.inputs && d.inputs.length) lines.push('<div class="desc-inputs">Inputs: ' + esc(d.inputs.join(' · ')) + '</div>');
|
if (d.inputs && d.inputs.length) lines.push('<div class="desc-inputs">Inputs: ' + esc(d.inputs.join(' · ')) + '</div>');
|
||||||
if (d.use) lines.push('<div class="desc-use">Use: ' + esc(d.use) + '</div>');
|
if (d.use) lines.push('<div class="desc-use">Use: ' + esc(d.use) + '</div>');
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
<h2>frank-large — deep reasoning</h2>
|
<h2>frank-large — deep reasoning</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Model:</strong> Qwen3.8-Flash-Next v2 Swift1.5 abliterated (halogen flash-server, ~62 GiB) — an uncensored edition that thinks before answering.</li>
|
<li><strong>Model:</strong> Qwen3.8-Flash-Next v2 Swift1.5 abliterated (halogen flash-server, ~62 GiB) — an uncensored edition that thinks before answering.</li>
|
||||||
|
<li><strong>Equivalent:</strong> Claude Sonnet 5 / OpenAI-Luna (Summer 2026 frontier intelligence).</li>
|
||||||
<li><strong>Capacity:</strong> 200k-token context, two conversations at a time; sees images.</li>
|
<li><strong>Capacity:</strong> 200k-token context, two conversations at a time; sees images.</li>
|
||||||
<li><strong>Inputs:</strong> text, image.</li>
|
<li><strong>Inputs:</strong> text, image.</li>
|
||||||
<li><strong>Best for:</strong> cybersecurity and debugging. <em>Use requires Frank's permission.</em></li>
|
<li><strong>Best for:</strong> cybersecurity and debugging. <em>Use requires Frank's permission.</em></li>
|
||||||
@@ -64,6 +65,7 @@
|
|||||||
<h2>frank-primary — the primary model</h2>
|
<h2>frank-primary — the primary model</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Model:</strong> Qwen3.8-Flash-Next at native FP8 precision (radiance, 173 GiB across both R9700s) — the biggest brain on the network.</li>
|
<li><strong>Model:</strong> Qwen3.8-Flash-Next at native FP8 precision (radiance, 173 GiB across both R9700s) — the biggest brain on the network.</li>
|
||||||
|
<li><strong>Equivalent:</strong> Claude Opus 4.8 / OpenAI-Terra (Summer 2026 frontier intelligence).</li>
|
||||||
<li><strong>Capacity:</strong> 200k-token context, two conversations at a time; sees images.</li>
|
<li><strong>Capacity:</strong> 200k-token context, two conversations at a time; sees images.</li>
|
||||||
<li><strong>Inputs:</strong> text, image.</li>
|
<li><strong>Inputs:</strong> text, image.</li>
|
||||||
<li><strong>Best for:</strong> software engineering, system administration, and instruction tasks.</li>
|
<li><strong>Best for:</strong> software engineering, system administration, and instruction tasks.</li>
|
||||||
@@ -72,6 +74,7 @@
|
|||||||
<h2>frank-secondary — the fast utility model</h2>
|
<h2>frank-secondary — the fast utility model</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Model:</strong> Qwen3.5-9B-Uncensored (Q6_K, 6.9 GiB) on the RTX 3090 — roughly 95 tokens per second.</li>
|
<li><strong>Model:</strong> Qwen3.5-9B-Uncensored (Q6_K, 6.9 GiB) on the RTX 3090 — roughly 95 tokens per second.</li>
|
||||||
|
<li><strong>Equivalent:</strong> last year's frontier level (2025).</li>
|
||||||
<li><strong>Capacity:</strong> two simultaneous conversations, 200k tokens each; sees images.</li>
|
<li><strong>Capacity:</strong> two simultaneous conversations, 200k tokens each; sees images.</li>
|
||||||
<li><strong>Inputs:</strong> text, image.</li>
|
<li><strong>Inputs:</strong> text, image.</li>
|
||||||
<li><strong>Best for:</strong> agentic search, RAG, research subagents, translation, roleplay, and summarization — any small task that doesn't need much intelligence, and anything with a picture (screenshots, photos, diagrams). This is the model Open WebUI offers to family accounts.</li>
|
<li><strong>Best for:</strong> agentic search, RAG, research subagents, translation, roleplay, and summarization — any small task that doesn't need much intelligence, and anything with a picture (screenshots, photos, diagrams). This is the model Open WebUI offers to family accounts.</li>
|
||||||
|
|||||||
@@ -269,6 +269,7 @@
|
|||||||
"section": "AI",
|
"section": "AI",
|
||||||
"details": {
|
"details": {
|
||||||
"role": "Deep reasoning model",
|
"role": "Deep reasoning model",
|
||||||
|
"equiv": "Equivalent to Claude Sonnet 5 / OpenAI-Luna (Summer 2026 frontier intelligence).",
|
||||||
"spec": "Qwen3.8-Flash-Next v2 Swift1.5 abliterated (halogen flash-server, ~62 GiB) — 200k-token context, two conversations at a time; sees images. Speculative decoding always on.",
|
"spec": "Qwen3.8-Flash-Next v2 Swift1.5 abliterated (halogen flash-server, ~62 GiB) — 200k-token context, two conversations at a time; sees images. Speculative decoding always on.",
|
||||||
"inputs": ["text", "image"],
|
"inputs": ["text", "image"],
|
||||||
"use": "Cybersecurity and debugging. Requires Frank's permission."
|
"use": "Cybersecurity and debugging. Requires Frank's permission."
|
||||||
@@ -286,6 +287,7 @@
|
|||||||
"section": "AI",
|
"section": "AI",
|
||||||
"details": {
|
"details": {
|
||||||
"role": "Primary model",
|
"role": "Primary model",
|
||||||
|
"equiv": "Equivalent to Claude Opus 4.8 / OpenAI-Terra (Summer 2026 frontier intelligence).",
|
||||||
"spec": "Qwen3.8-Flash-Next at native FP8 precision (radiance, 173 GiB) — 200k-token context, two conversations; sees images. Runs on both R9700s with tiered expert memory.",
|
"spec": "Qwen3.8-Flash-Next at native FP8 precision (radiance, 173 GiB) — 200k-token context, two conversations; sees images. Runs on both R9700s with tiered expert memory.",
|
||||||
"inputs": ["text", "image"],
|
"inputs": ["text", "image"],
|
||||||
"use": "Software engineering, system administration, and instruction tasks."
|
"use": "Software engineering, system administration, and instruction tasks."
|
||||||
@@ -303,6 +305,7 @@
|
|||||||
"section": "AI",
|
"section": "AI",
|
||||||
"details": {
|
"details": {
|
||||||
"role": "Fast utility model",
|
"role": "Fast utility model",
|
||||||
|
"equiv": "Equivalent to last year's frontier level (2025).",
|
||||||
"spec": "Qwen3.5-9B-Uncensored (Q6_K, 6.9 GiB) on llama.cpp CUDA — two 200k-token conversations at a time; sees images; ~95 tok/s decode on the RTX 3090.",
|
"spec": "Qwen3.5-9B-Uncensored (Q6_K, 6.9 GiB) on llama.cpp CUDA — two 200k-token conversations at a time; sees images; ~95 tok/s decode on the RTX 3090.",
|
||||||
"inputs": ["text", "image"],
|
"inputs": ["text", "image"],
|
||||||
"use": "Agentic search, RAG, research subagents, translation, roleplay, and summarization — any small task that doesn't need much intelligence."
|
"use": "Agentic search, RAG, research subagents, translation, roleplay, and summarization — any small task that doesn't need much intelligence."
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ body::before {
|
|||||||
.desc { color: var(--fg); margin: 8px 0; }
|
.desc { color: var(--fg); margin: 8px 0; }
|
||||||
.desc-role { color: var(--dim); font-weight: bold; }
|
.desc-role { color: var(--dim); font-weight: bold; }
|
||||||
.desc-spec { color: var(--fg); }
|
.desc-spec { color: var(--fg); }
|
||||||
|
.desc-equiv { color: var(--head); font-style: italic; }
|
||||||
.desc-inputs { color: var(--dim); }
|
.desc-inputs { color: var(--dim); }
|
||||||
.desc-use { color: var(--fg); margin-top: 4px; }
|
.desc-use { color: var(--fg); margin-top: 4px; }
|
||||||
.links a { color: var(--link); text-decoration: underline; margin-right: 12px; }
|
.links a { color: var(--link); text-decoration: underline; margin-right: 12px; }
|
||||||
@@ -118,6 +119,6 @@ html[data-bare="1"] body { background: #fff; color: #000; font-family: serif; te
|
|||||||
html[data-bare="1"] body::before { display: none; }
|
html[data-bare="1"] body::before { display: none; }
|
||||||
html[data-bare="1"] .panel, html[data-bare="1"] .top, html[data-bare="1"] .foot { border-color: #000; background: none; }
|
html[data-bare="1"] .panel, html[data-bare="1"] .top, html[data-bare="1"] .foot { border-color: #000; background: none; }
|
||||||
html[data-bare="1"] .badge, html[data-bare="1"] .name, html[data-bare="1"] .desc, html[data-bare="1"] .summary, html[data-bare="1"] .section-title { color: #000; }
|
html[data-bare="1"] .badge, html[data-bare="1"] .name, html[data-bare="1"] .desc, html[data-bare="1"] .summary, html[data-bare="1"] .section-title { color: #000; }
|
||||||
html[data-bare="1"] .desc-role, html[data-bare="1"] .desc-spec, html[data-bare="1"] .desc-inputs, html[data-bare="1"] .desc-use { color: #000; font-weight: normal; }
|
html[data-bare="1"] .desc-role, html[data-bare="1"] .desc-spec, html[data-bare="1"] .desc-inputs, html[data-bare="1"] .desc-use, html[data-bare="1"] .desc-equiv { color: #000; font-weight: normal; }
|
||||||
html[data-bare="1"] .section-title { border-color: #000; }
|
html[data-bare="1"] .section-title { border-color: #000; }
|
||||||
html[data-bare="1"] .links a, html[data-bare="1"] .toggle, html[data-bare="1"] .foot a { color: #000; }
|
html[data-bare="1"] .links a, html[data-bare="1"] .toggle, html[data-bare="1"] .foot a { color: #000; }
|
||||||
|
|||||||
@@ -77,3 +77,20 @@ assert by_probe.get("127.0.0.1:7770") == "frank-large", by_probe.get("127.0.0.1:
|
|||||||
assert by_probe.get("127.0.0.1:7771") == "frank-secondary", by_probe.get("127.0.0.1:7771")
|
assert by_probe.get("127.0.0.1:7771") == "frank-secondary", by_probe.get("127.0.0.1:7771")
|
||||||
PY
|
PY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "every fleet LLM card carries a user-facing equivalence note" {
|
||||||
|
# Frank's capability framing (2026-10-08): each card must state, in plain
|
||||||
|
# terms, what the model is equivalent to — the cards' whole purpose for
|
||||||
|
# family users is "how smart is this and what is it for".
|
||||||
|
python3 - "$REPO_ROOT/shared/homepage/services.json" <<'PY'
|
||||||
|
import json, sys
|
||||||
|
services = json.load(open(sys.argv[1]))
|
||||||
|
fleet = {s["name"]: s for s in services if s.get("name") in ("frank-large", "frank-primary", "frank-secondary")}
|
||||||
|
assert len(fleet) == 3, sorted(fleet)
|
||||||
|
for name, s in fleet.items():
|
||||||
|
eq = s.get("details", {}).get("equiv", "")
|
||||||
|
assert eq.strip(), f"{name} card has no equivalence note"
|
||||||
|
PY
|
||||||
|
grep -q "desc-equiv" "$REPO_ROOT/shared/homepage/app.js"
|
||||||
|
grep -q "desc-equiv" "$REPO_ROOT/shared/homepage/style.css"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user