Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
500 lines
30 KiB
HTML
500 lines
30 KiB
HTML
{{define "about"}}{{if not .Site}}<!doctype html>
|
||
<html lang="{{lang}}"><head>
|
||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<meta name="description" content="{{t "about.meta.description"}}">
|
||
{{end}}<title>llmgw</title>
|
||
{{if .Site}}<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=Archivo:wdth,wght@112,600;125,800&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap">
|
||
{{end}}<style>
|
||
{{if not .Site}}@font-face{font-family:"Archivo";font-weight:600 800;font-stretch:112% 125%;font-display:swap;src:url("{{asset "fonts/archivo-latin.woff2"}}") format("woff2");unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||
@font-face{font-family:"Archivo";font-weight:600 800;font-stretch:112% 125%;font-display:swap;src:url("{{asset "fonts/archivo-latin-ext.woff2"}}") format("woff2");unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
||
@font-face{font-family:"IBM Plex Sans";font-weight:100 700;font-display:swap;src:url("{{asset "fonts/plex-sans-latin.woff2"}}") format("woff2");unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||
@font-face{font-family:"IBM Plex Sans";font-weight:100 700;font-display:swap;src:url("{{asset "fonts/plex-sans-latin-ext.woff2"}}") format("woff2");unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
||
@font-face{font-family:"IBM Plex Mono";font-weight:400;font-display:swap;src:url("{{asset "fonts/plex-mono-400-latin.woff2"}}") format("woff2");unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||
@font-face{font-family:"IBM Plex Mono";font-weight:400;font-display:swap;src:url("{{asset "fonts/plex-mono-400-latin-ext.woff2"}}") format("woff2");unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
||
@font-face{font-family:"IBM Plex Mono";font-weight:500;font-display:swap;src:url("{{asset "fonts/plex-mono-500-latin.woff2"}}") format("woff2");unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
|
||
@font-face{font-family:"IBM Plex Mono";font-weight:500;font-display:swap;src:url("{{asset "fonts/plex-mono-500-latin-ext.woff2"}}") format("woff2");unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
|
||
{{end}}:root{
|
||
--bg:#F3F5F5; --surface:#FFFFFF; --ink:#142023; --muted:#56696C; --line:#D3DCDC;
|
||
--fiber:#0B7F7D; --fiber-soft:#DDEFEE; --om1:#C4621A; --om1-soft:#F6E6D9;
|
||
--code-bg:#15201F; --code-ink:#DCEAE8; --code-dim:#7F9A97;
|
||
--display:"Archivo","Arial Narrow",system-ui,sans-serif;
|
||
--body:"IBM Plex Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
|
||
--mono:"IBM Plex Mono",ui-monospace,"SFMono-Regular",Menlo,monospace;
|
||
}
|
||
@media (prefers-color-scheme:dark){
|
||
:root:not([data-theme="light"]){
|
||
--bg:#0E1617; --surface:#152022; --ink:#E2ECEB; --muted:#8FA5A4; --line:#26383A;
|
||
--fiber:#3FC2BC; --fiber-soft:#133634; --om1:#EE9350; --om1-soft:#3A2717;
|
||
--code-bg:#0A1011; --code-ink:#D5E5E3; --code-dim:#6E8886;
|
||
color-scheme:dark;
|
||
}
|
||
}
|
||
:root[data-theme="dark"]{
|
||
--bg:#0E1617; --surface:#152022; --ink:#E2ECEB; --muted:#8FA5A4; --line:#26383A;
|
||
--fiber:#3FC2BC; --fiber-soft:#133634; --om1:#EE9350; --om1-soft:#3A2717;
|
||
--code-bg:#0A1011; --code-ink:#D5E5E3; --code-dim:#6E8886;
|
||
color-scheme:dark;
|
||
}
|
||
*{box-sizing:border-box}
|
||
body{background:var(--bg);color:var(--ink);font:400 16px/1.6 var(--body);margin:0;padding-inline:20px;padding-block:0}
|
||
.wrap{max-width:1080px;margin:0 auto}
|
||
a{color:var(--fiber);text-underline-offset:3px}
|
||
a:focus-visible,button:focus-visible,input:focus-visible+label{outline:2px solid var(--fiber);outline-offset:3px;border-radius:4px}
|
||
h1,h2,h3{font-family:var(--display);text-wrap:balance;margin:0}
|
||
h2{font-size:clamp(1.6rem,3.2vw,2.1rem);font-variation-settings:"wdth" 112;font-weight:600;letter-spacing:-.01em}
|
||
h3{font-size:1.05rem;font-variation-settings:"wdth" 112;font-weight:600}
|
||
p{margin:0}
|
||
code,pre{font-family:var(--mono);font-size:.875rem}
|
||
:not(pre)>code{background:var(--fiber-soft);padding:.1em .35em;border-radius:4px;font-size:.85em}
|
||
.eyebrow{font:500 .75rem/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
|
||
|
||
/* top bar */
|
||
.bar{display:flex;align-items:center;justify-content:space-between;gap:16px;padding-block:22px;border-bottom:1px solid var(--line)}
|
||
.mark{font:800 1.25rem/1 var(--display);font-variation-settings:"wdth" 125;letter-spacing:-.02em;color:var(--ink);text-decoration:none;display:flex;align-items:center;gap:10px}
|
||
.mark svg{flex:none}
|
||
.bar nav{display:flex;gap:20px;flex-wrap:wrap;font-size:.9rem}
|
||
.bar nav a{color:var(--muted);text-decoration:none}
|
||
.bar nav a:hover{color:var(--ink)}
|
||
|
||
/* hero */
|
||
.hero{display:grid;grid-template-columns:1.05fr .95fr;gap:48px;align-items:center;padding-block:64px 56px}
|
||
.hero h1{font-size:clamp(2.5rem,6vw,4.4rem);line-height:.98;font-weight:800;font-variation-settings:"wdth" 125;letter-spacing:-.03em}
|
||
.hero h1 em{font-style:normal;color:var(--fiber)}
|
||
.lede{margin-top:22px;font-size:1.12rem;color:var(--muted);max-width:34em}
|
||
.cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:30px}
|
||
.btn{display:inline-flex;align-items:center;gap:8px;font:600 .95rem/1 var(--body);padding:13px 18px;border-radius:8px;text-decoration:none;border:1px solid var(--fiber);background:var(--fiber);color:var(--bg)}
|
||
.btn.ghost{background:transparent;color:var(--ink);border-color:var(--line)}
|
||
.btn.ghost:hover{border-color:var(--ink)}
|
||
.oneline{margin-top:26px;display:flex;align-items:center;gap:10px;background:var(--code-bg);color:var(--code-ink);border-radius:8px;padding:12px 12px 12px 16px;max-width:100%}
|
||
.oneline code{flex:1;min-width:0;overflow-x:auto;white-space:nowrap;background:none;padding:0;font-size:.9rem;color:var(--code-ink)}
|
||
.oneline .p{color:var(--code-dim);user-select:none}
|
||
|
||
/* schematic */
|
||
figure{margin:0}
|
||
.schem{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:18px}
|
||
.schem svg{display:block;width:100%;height:auto}
|
||
.schem figcaption{margin-top:12px;font-size:.85rem;color:var(--muted)}
|
||
.s-label{font:500 11px var(--mono);fill:var(--muted)}
|
||
.s-strong{font:600 13px var(--body);fill:var(--ink)}
|
||
.s-box{fill:var(--bg);stroke:var(--line)}
|
||
.s-gw{fill:var(--fiber-soft);stroke:var(--fiber);stroke-width:1.5}
|
||
.s-fab{fill:none;stroke:var(--line);stroke-dasharray:5 4}
|
||
.s-link{fill:none;stroke:var(--line);stroke-width:2}
|
||
.s-gpu-a{fill:var(--fiber)} .s-gpu-b{fill:var(--om1)}
|
||
.s-gpu-idle{fill:var(--line)}
|
||
.pulse{fill:var(--fiber)}
|
||
.pulse.b{fill:var(--om1)}
|
||
@media (prefers-reduced-motion:reduce){.pulse{display:none}}
|
||
|
||
/* sections */
|
||
section{padding-block:56px;border-top:1px solid var(--line)}
|
||
.sec-head{display:grid;grid-template-columns:260px 1fr;gap:40px}
|
||
.sec-head .intro{color:var(--muted);margin-top:12px;font-size:.95rem}
|
||
|
||
.facts{display:grid;grid-template-columns:1fr 1fr;gap:28px 40px}
|
||
.fact h3{display:flex;gap:10px;align-items:baseline}
|
||
.fact h3::before{content:"";width:10px;height:10px;border-radius:2px;background:var(--fiber);flex:none;transform:translateY(-1px)}
|
||
.fact p{margin-top:6px;color:var(--muted);font-size:.95rem;max-width:36em}
|
||
|
||
/* steps */
|
||
.steps{list-style:none;margin:0;padding:0;display:grid;gap:28px;counter-reset:s}
|
||
.steps li{display:grid;grid-template-columns:44px 1fr;gap:4px 16px;counter-increment:s}
|
||
.steps li>*{grid-column:2}
|
||
.steps li::before{content:counter(s);grid-column:1;grid-row:span 4;font:800 1.5rem/1.1 var(--display);font-variation-settings:"wdth" 125;color:var(--fiber)}
|
||
.steps p{color:var(--muted);font-size:.95rem;max-width:40em}
|
||
.code{position:relative;margin-top:10px;background:var(--code-bg);color:var(--code-ink);border-radius:8px;min-width:0}
|
||
.code pre{margin:0;padding:16px 18px;overflow-x:auto;line-height:1.55}
|
||
.code .c{color:var(--code-dim)}
|
||
.copy{position:absolute;top:8px;right:8px;font:500 .75rem/1 var(--body);padding:7px 10px;border-radius:6px;border:1px solid #2d4442;background:#1c2b2a;color:var(--code-ink);cursor:pointer}
|
||
.copy:hover{border-color:var(--code-dim)}
|
||
|
||
/* nodes table in step */
|
||
.term{margin-top:10px;background:var(--code-bg);color:var(--code-ink);border-radius:8px;overflow-x:auto}
|
||
.term pre{margin:0;padding:14px 18px;font-size:.8rem;line-height:1.6}
|
||
.term .ok{color:#6FD3A6}
|
||
|
||
/* proxy tabs */
|
||
.tabs{min-width:0}
|
||
.tabs input{position:absolute;opacity:0;pointer-events:none}
|
||
.tablist{display:flex;gap:4px;border-bottom:1px solid var(--line)}
|
||
.tablist label{cursor:pointer;padding:10px 16px;font:600 .9rem/1 var(--body);color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-1px}
|
||
#t-caddy:checked~.tablist label[for="t-caddy"],#t-nginx:checked~.tablist label[for="t-nginx"]{color:var(--ink);border-color:var(--fiber)}
|
||
.panel{display:none;margin-top:16px}
|
||
#t-caddy:checked~.p-caddy,#t-nginx:checked~.p-nginx{display:block}
|
||
.panel .meta{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px 16px;font-size:.88rem;color:var(--muted)}
|
||
.panel .code pre{max-height:460px}
|
||
.rules{margin-top:28px;display:grid;grid-template-columns:1fr 1fr;gap:18px 32px;padding:0;list-style:none}
|
||
.rules li{font-size:.92rem;color:var(--muted);padding-left:16px;border-left:2px solid var(--om1)}
|
||
.rules strong{color:var(--ink);font-weight:600;display:block}
|
||
|
||
/* downloads */
|
||
.dl{width:100%;border-collapse:collapse;font-size:.92rem}
|
||
.dl-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:10px;background:var(--surface)}
|
||
.dl th{text-align:left;font:500 .72rem/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);padding:14px 16px;border-bottom:1px solid var(--line)}
|
||
.dl td{padding:12px 16px;border-bottom:1px solid var(--line);vertical-align:top}
|
||
.dl tr:last-child td{border-bottom:0}
|
||
.dl td:first-child{white-space:nowrap;font-weight:500}
|
||
.dl code{background:none;padding:0;font-size:.85rem}
|
||
.dl .note{color:var(--muted)}
|
||
.ver{display:flex;flex-wrap:wrap;gap:10px 24px;align-items:baseline;margin-bottom:18px}
|
||
.tag{font:500 .8rem/1 var(--mono);padding:6px 9px;border-radius:5px;background:var(--fiber-soft);color:var(--fiber)}
|
||
|
||
/* status */
|
||
.status{display:grid;grid-template-columns:1fr 1fr;gap:32px}
|
||
.status h3{margin-bottom:10px}
|
||
.status ul{margin:0;padding:0;list-style:none;display:grid;gap:10px}
|
||
.status li{font-size:.93rem;color:var(--muted);display:grid;grid-template-columns:18px 1fr;gap:8px}
|
||
.status li::before{font:600 .9rem/1.6 var(--mono)}
|
||
.proven li::before{content:"✓";color:var(--fiber)}
|
||
.open li::before{content:"○";color:var(--om1)}
|
||
|
||
.next{font:500 .66rem/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;padding:4px 6px;border-radius:4px;background:var(--om1-soft);color:var(--om1);white-space:nowrap;align-self:center}
|
||
.fab-grid{display:grid;grid-template-columns:1fr;gap:28px;min-width:0}
|
||
.term .warn{color:#E9B35A} .term .fail{color:#F07C6C} .term .dim{color:var(--code-dim)}
|
||
.watch{display:grid;grid-template-columns:1fr 1fr;gap:18px 32px;padding:0;margin:0;list-style:none}
|
||
.watch li{font-size:.92rem;color:var(--muted);padding-left:16px;border-left:2px solid var(--fiber)}
|
||
.watch strong{color:var(--ink);font-weight:600;display:block}
|
||
.watch code{font-size:.8em}
|
||
.order{display:grid;grid-template-columns:repeat(3,1fr);gap:0;border:1px solid var(--line);border-radius:10px;background:var(--surface);overflow:hidden}
|
||
.order div{padding:16px 18px;border-right:1px solid var(--line)}
|
||
.order div:last-child{border-right:0}
|
||
.order b{display:block;font:800 1.4rem/1 var(--display);font-variation-settings:"wdth" 125;color:var(--fiber);margin-bottom:8px}
|
||
.order b.x{color:var(--om1)}
|
||
.order h3{font-size:.95rem}
|
||
.order p{font-size:.88rem;color:var(--muted);margin-top:4px}
|
||
footer{border-top:1px solid var(--line);padding-block:28px 40px;display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;font-size:.85rem;color:var(--muted)}
|
||
footer a{color:var(--muted)}
|
||
|
||
@media (max-width:860px){
|
||
.hero{grid-template-columns:1fr;gap:36px;padding-block:44px 40px}
|
||
.sec-head{grid-template-columns:1fr;gap:20px}
|
||
.facts,.rules,.status,.watch,.order{grid-template-columns:1fr}
|
||
.order div{border-right:0;border-bottom:1px solid var(--line)}
|
||
.order div:last-child{border-bottom:0}
|
||
.bar nav{display:none}
|
||
}
|
||
</style>
|
||
{{if not .Site}}</head><body>{{end}}
|
||
|
||
<div class="wrap">
|
||
<header class="bar">
|
||
<a class="mark" href="#top" aria-label="{{t "about.home_label"}}">
|
||
<svg width="26" height="26" viewBox="0 0 26 26" aria-hidden="true">
|
||
<rect x="1" y="1" width="24" height="24" rx="6" fill="none" stroke="currentColor" stroke-width="2"/>
|
||
<path d="M7 9h12M7 13h12M7 17h12" stroke="var(--fiber)" stroke-width="2" stroke-linecap="round"/>
|
||
</svg>
|
||
llmgw
|
||
</a>
|
||
<nav aria-label="{{t "about.nav.label"}}">
|
||
<a href="#what">{{t "about.nav.what"}}</a>
|
||
<a href="#fabrics">{{t "about.nav.fabrics"}}</a>
|
||
<a href="#install">{{t "about.nav.install"}}</a>
|
||
<a href="#proxy">{{t "about.nav.proxy"}}</a>
|
||
<a href="#download">{{t "about.nav.download"}}</a>
|
||
<a href="https://gitea.mynodes.xyz/ilker/llmgw">{{t "about.nav.source"}}</a>
|
||
{{if not .Site}}<a href="/">{{t "about.nav.gateway"}}</a>{{end}}
|
||
</nav>
|
||
</header>
|
||
|
||
<div class="hero" id="top">
|
||
<div>
|
||
<p class="eyebrow">{{t "about.hero.eyebrow" .Version}}</p>
|
||
<h1 style="margin-top:14px">{{th "about.hero.title"}}</h1>
|
||
<p class="lede">{{t "about.hero.lede"}}</p>
|
||
<div class="cta">
|
||
<a class="btn" href="#download">{{t "about.hero.download"}}{{with .Release}} {{.}}{{end}}</a>
|
||
<a class="btn ghost" href="https://gitea.mynodes.xyz/ilker/llmgw/src/branch/main/docs/quick-install.md">{{t "about.hero.guide"}}</a>
|
||
</div>
|
||
<div class="oneline" aria-label="{{t "about.hero.oneline_label"}}">
|
||
<code><span class="p">$ </span>sudo llmgw server init --admin you@example.com</code>
|
||
<button class="copy" style="position:static" data-copy="sudo llmgw server init --admin you@example.com" type="button">{{t "about.copy"}}</button>
|
||
</div>
|
||
</div>
|
||
|
||
<figure class="schem">
|
||
<svg viewBox="0 0 440 250" role="img" aria-labelledby="schem-t">
|
||
<title id="schem-t">{{t "about.schem.title"}}</title>
|
||
<!-- clients -->
|
||
<g>
|
||
<rect class="s-box" x="4" y="58" width="92" height="30" rx="6"/>
|
||
<text class="s-label" x="50" y="77" text-anchor="middle" translate="no">openai sdk</text>
|
||
<rect class="s-box" x="4" y="110" width="92" height="30" rx="6"/>
|
||
<text class="s-label" x="50" y="129" text-anchor="middle">{{t "about.schem.editor"}}</text>
|
||
<rect class="s-box" x="4" y="162" width="92" height="30" rx="6"/>
|
||
<text class="s-label" x="50" y="181" text-anchor="middle" translate="no">curl</text>
|
||
</g>
|
||
<path id="c1" class="s-link" d="M96 73 C130 73 130 118 160 118"/>
|
||
<path id="c2" class="s-link" d="M96 125 H160"/>
|
||
<path id="c3" class="s-link" d="M96 177 C130 177 130 132 160 132"/>
|
||
<!-- gateway -->
|
||
<rect class="s-gw" x="160" y="96" width="84" height="58" rx="8"/>
|
||
<text class="s-strong" x="202" y="122" text-anchor="middle">llmgw</text>
|
||
<text class="s-label" x="202" y="139" text-anchor="middle">:8080</text>
|
||
<path id="fa" class="s-link" d="M244 114 C272 114 272 62 300 62"/>
|
||
<path id="fb" class="s-link" d="M244 136 C272 136 272 188 300 188"/>
|
||
<!-- fabric a -->
|
||
<rect class="s-fab" x="300" y="14" width="136" height="98" rx="10"/>
|
||
<text class="s-label" x="312" y="32" translate="no">nvl72 · gb200</text>
|
||
<g transform="translate(312 42)">
|
||
<rect class="s-gpu-a" width="22" height="22" rx="3"/><rect class="s-gpu-a" x="28" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-a" x="56" width="22" height="22" rx="3"/><rect class="s-gpu-a" x="84" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-a" y="28" width="22" height="22" rx="3"/><rect class="s-gpu-a" x="28" y="28" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-idle" x="56" y="28" width="22" height="22" rx="3"/><rect class="s-gpu-idle" x="84" y="28" width="22" height="22" rx="3"/>
|
||
</g>
|
||
<!-- fabric b -->
|
||
<rect class="s-fab" x="300" y="138" width="136" height="98" rx="10"/>
|
||
<text class="s-label" x="312" y="156" translate="no">ib-b · h100-80g</text>
|
||
<g transform="translate(312 166)">
|
||
<rect class="s-gpu-b" width="22" height="22" rx="3"/><rect class="s-gpu-b" x="28" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-idle" x="56" width="22" height="22" rx="3"/><rect class="s-gpu-idle" x="84" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-idle" y="28" width="22" height="22" rx="3"/><rect class="s-gpu-idle" x="28" y="28" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-idle" x="56" y="28" width="22" height="22" rx="3"/><rect class="s-gpu-idle" x="84" y="28" width="22" height="22" rx="3"/>
|
||
</g>
|
||
<!-- requests in flight -->
|
||
<circle class="pulse" r="4"><animateMotion dur="2.4s" repeatCount="indefinite"><mpath href="#c1"/></animateMotion></circle>
|
||
<circle class="pulse" r="4"><animateMotion dur="2.4s" begin="0.8s" repeatCount="indefinite"><mpath href="#c2"/></animateMotion></circle>
|
||
<circle class="pulse" r="4"><animateMotion dur="2.4s" begin="1.6s" repeatCount="indefinite"><mpath href="#c3"/></animateMotion></circle>
|
||
<circle class="pulse" r="4"><animateMotion dur="2.4s" begin="1.2s" repeatCount="indefinite"><mpath href="#fa"/></animateMotion></circle>
|
||
<circle class="pulse b" r="4"><animateMotion dur="2.4s" begin="2s" repeatCount="indefinite"><mpath href="#fb"/></animateMotion></circle>
|
||
</svg>
|
||
<figcaption>{{t "about.schem.caption"}}</figcaption>
|
||
</figure>
|
||
</div>
|
||
|
||
<section id="what">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.what.title"}}</h2>
|
||
<p class="intro">{{t "about.what.intro"}}</p>
|
||
</div>
|
||
<div class="facts">
|
||
<div class="fact"><h3>{{t "about.what.api.title"}}</h3>
|
||
<p>{{th "about.what.api.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.placement.title"}}</h3>
|
||
<p>{{t "about.what.placement.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.ondemand.title"}}</h3>
|
||
<p>{{t "about.what.ondemand.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.keys.title"}}</h3>
|
||
<p>{{t "about.what.keys.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.editors.title"}}</h3>
|
||
<p>{{t "about.what.editors.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.chat.title"}}</h3>
|
||
<p>{{t "about.what.chat.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.mirror.title"}}</h3>
|
||
<p>{{t "about.what.mirror.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.engines.title"}}</h3>
|
||
<p>{{t "about.what.engines.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.upgrades.title"}}</h3>
|
||
<p>{{t "about.what.upgrades.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.dashboard.title"}}</h3>
|
||
<p>{{th "about.what.dashboard.text"}}</p></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="fabrics">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.fabrics.title"}}</h2>
|
||
<p class="intro">{{t "about.fabrics.intro"}}</p>
|
||
<p class="intro"><a href="https://gitea.mynodes.xyz/ilker/llmgw/src/branch/main/docs/fabrics.md">{{t "about.fabrics.guide"}}</a></p>
|
||
</div>
|
||
<div class="fab-grid">
|
||
<div class="order" aria-label="{{t "about.fabrics.order_label"}}">
|
||
<div><b>1</b><h3>{{t "about.fabrics.nvlink.title"}}</h3><p>{{th "about.fabrics.nvlink.text"}}</p></div>
|
||
<div><b>2</b><h3>{{t "about.fabrics.ib.title"}}</h3><p>{{t "about.fabrics.ib.text"}}</p></div>
|
||
<div><b class="x">×</b><h3>{{t "about.fabrics.never.title"}}</h3><p>{{t "about.fabrics.never.text"}}</p></div>
|
||
</div>
|
||
<div>
|
||
<h3>{{t "about.fabrics.doctor"}}</h3>
|
||
<div class="term" aria-label="{{t "about.fabrics.doctor_label"}}"><pre>$ sudo llmgw doctor
|
||
<span class="fail">FAIL</span> nvlink this machine has NVSwitch but nvidia-fabricmanager is inactive
|
||
<span class="dim">→ systemctl enable --now nvidia-fabricmanager</span>
|
||
<span class="warn">WARN</span> fabric nvidia_peermem is not loaded: GPUDirect RDMA is off
|
||
<span class="dim">→ modprobe nvidia_peermem</span>
|
||
<span class="ok">OK</span> gpu 8 GPUs: 8× NVIDIA H100 80GB HBM3
|
||
<span class="ok">OK</span> nvlink NVLink groups: [0 1 2 3 4 5 6 7]
|
||
<span class="ok">OK</span> fabric mlx5_0/1 ACTIVE at 400 Gb/s (InfiniBand), subnet manager 0x248a07030030f0c0
|
||
<span class="ok">OK</span> fabric subnet managers: 0x…f0c0 (master, priority 15), 0x…f1d4 (standby, priority 14)
|
||
<span class="ok">OK</span> agent NCCL bootstraps over ens3 (10.1.0.21)</pre></div>
|
||
</div>
|
||
<ul class="watch">
|
||
<li><strong>{{t "about.fabrics.sm.title"}}</strong>{{t "about.fabrics.sm.text"}}</li>
|
||
<li><strong>{{t "about.fabrics.map.title"}}</strong>{{th "about.fabrics.map.text"}}</li>
|
||
<li><strong>{{t "about.fabrics.racks.title"}}</strong>{{th "about.fabrics.racks.text"}}</li>
|
||
<li><strong>{{t "about.fabrics.ports.title"}}</strong>{{t "about.fabrics.ports.text"}}</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="install">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.install.title"}}</h2>
|
||
<p class="intro">{{t "about.install.intro"}}</p>
|
||
<p class="intro">{{th "about.install.guide"}}</p>
|
||
</div>
|
||
<ol class="steps">
|
||
<li>
|
||
<h3>{{t "about.install.binary.title"}}</h3>
|
||
<p>{{t "about.install.binary.text"}}</p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>VERSION={{or .Release "vX.Y.Z"}}{{if not .Release}} <span class="c"># from the releases page</span>{{end}}
|
||
U=https://gitea.mynodes.xyz/ilker/llmgw/releases/download/$VERSION
|
||
curl -fsSLO $U/llmgw-$VERSION-linux-amd64
|
||
curl -fsSL $U/checksums.txt | sha256sum -c --ignore-missing
|
||
sudo install -m0755 llmgw-$VERSION-linux-amd64 /usr/local/bin/llmgw</code></pre></div>
|
||
</li>
|
||
<li>
|
||
<h3>{{t "about.install.server.title"}}</h3>
|
||
<p>{{th "about.install.server.text"}}</p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>sudo llmgw server init --admin you@example.com</code></pre></div>
|
||
</li>
|
||
<li>
|
||
<h3>{{t "about.install.node.title"}}</h3>
|
||
<p>{{t "about.install.node.text"}}</p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>deploy/bootstrap/onboard-node.sh --node gpu01 --addr 10.0.0.141 \
|
||
--server https://10.0.0.140:7443 --fabric ib-a:mlx5_0,mlx5_1</code></pre></div>
|
||
<div class="term" aria-label="{{t "about.install.node.output_label"}}"><pre>$ llmgw ctl nodes
|
||
NODE STATE GPUS MEM CLASSES FABRICS REPLICAS LAST SEEN
|
||
gpu01 <span class="ok">ready</span> 8/8 free 503G h100-80g ib-a 0 2s</pre></div>
|
||
</li>
|
||
<li>
|
||
<h3>{{t "about.install.model.title"}}</h3>
|
||
<p>{{th "about.install.model.text"}}</p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>llmgw ctl model add -f qwen-coder-3b.yaml
|
||
|
||
curl https://llm.example.com/v1/chat/completions \
|
||
-H "Authorization: Bearer $LLMGW_API_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"model": "coder", "messages": [{"role": "user", "content": "hello"}]}'</code></pre></div>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="proxy">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.proxy.title"}}</h2>
|
||
<p class="intro">{{t "about.proxy.intro"}}</p>
|
||
<p class="intro">{{th "about.proxy.loopback"}}</p>
|
||
</div>
|
||
<div class="tabs">
|
||
<input type="radio" name="proxy" id="t-caddy" checked>
|
||
<input type="radio" name="proxy" id="t-nginx">
|
||
<div class="tablist" role="presentation" translate="no">
|
||
<label for="t-caddy">Caddy</label>
|
||
<label for="t-nginx">nginx</label>
|
||
</div>
|
||
<div class="panel p-caddy">
|
||
<p class="meta"><span>{{th "about.proxy.caddy"}}</span>
|
||
<a href="{{.Download}}/Caddyfile" translate="no">Caddyfile</a></p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>{{.Caddy}}</code></pre></div>
|
||
</div>
|
||
<div class="panel p-nginx">
|
||
<p class="meta"><span>{{th "about.proxy.nginx"}}</span>
|
||
<a href="{{.Download}}/nginx.conf" translate="no">nginx.conf</a></p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>{{.Nginx}}</code></pre></div>
|
||
</div>
|
||
<ul class="rules">
|
||
<li><strong>{{t "about.proxy.stream.title"}}</strong>{{t "about.proxy.stream.text"}}</li>
|
||
<li><strong>{{t "about.proxy.timeout.title"}}</strong>{{t "about.proxy.timeout.text"}}</li>
|
||
<li><strong>{{t "about.proxy.headers.title"}}</strong>{{th "about.proxy.headers.text"}}</li>
|
||
<li><strong>{{t "about.proxy.body.title"}}</strong>{{t "about.proxy.body.text"}}</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="download">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.download.title"}}</h2>
|
||
<p class="intro">{{th "about.download.intro"}}</p>
|
||
</div>
|
||
<div>
|
||
{{if .Release}}
|
||
<div class="ver"><span class="tag">{{.Release}}</span>{{with .Date}}<span class="eyebrow">{{t "about.download.released" .}}</span>{{end}}</div>
|
||
<div class="dl-wrap">
|
||
<table class="dl">
|
||
<thead><tr><th>{{t "about.download.col.for"}}</th><th>{{t "about.download.col.file"}}</th><th>{{t "about.download.col.notes"}}</th></tr></thead>
|
||
<tbody>
|
||
<tr><td translate="no">Linux x86-64</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-linux-amd64"><code>llmgw-{{$.Release}}-linux-amd64</code></a></td><td class="note">{{t "about.download.static_any"}}</td></tr>
|
||
<tr><td translate="no">Linux ARM64</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-linux-arm64"><code>llmgw-{{$.Release}}-linux-arm64</code></a></td><td class="note">{{t "about.download.static"}}</td></tr>
|
||
<tr><td translate="no">Linux x86-64, NVLink</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-linux-amd64-nvml"><code>llmgw-{{$.Release}}-linux-amd64-nvml</code></a></td><td class="note">{{t "about.download.nvml"}}</td></tr>
|
||
<tr><td>{{t "about.download.mac_arm"}}</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-darwin-arm64"><code>llmgw-{{$.Release}}-darwin-arm64</code></a></td><td class="note">{{th "about.download.mac_note"}}</td></tr>
|
||
<tr><td translate="no">macOS Intel</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-darwin-amd64"><code>llmgw-{{$.Release}}-darwin-amd64</code></a></td><td class="note"></td></tr>
|
||
<tr><td translate="no">Caddy</td><td><a href="{{$.Download}}/Caddyfile"><code>Caddyfile</code></a></td><td class="note">{{t "about.download.proxy_note"}}</td></tr>
|
||
<tr><td translate="no">nginx</td><td><a href="{{$.Download}}/nginx.conf"><code>nginx.conf</code></a></td><td class="note">{{t "about.download.proxy_note"}}</td></tr>
|
||
<tr><td>{{t "about.download.checksums"}}</td><td><a href="{{$.Download}}/checksums.txt"><code>checksums.txt</code></a></td><td class="note">{{t "about.download.checksums_note"}}</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{{else}}
|
||
<p class="intro" style="margin-top:0">{{th "about.download.dev" .Version}}</p>
|
||
{{end}}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="status">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.status.title"}}</h2>
|
||
<p class="intro">{{t "about.status.intro"}}</p>
|
||
</div>
|
||
<div class="status">
|
||
<div class="proven">
|
||
<h3>{{t "about.status.proven"}}</h3>
|
||
<ul>
|
||
<li>{{t "about.status.proven.single"}}</li>
|
||
<li>{{t "about.status.proven.ondemand"}}</li>
|
||
<li>{{t "about.status.proven.keys"}}</li>
|
||
<li>{{t "about.status.proven.upgrades"}}</li>
|
||
<li>{{t "about.status.proven.stores"}}</li>
|
||
<li>{{t "about.status.proven.chat"}}</li>
|
||
</ul>
|
||
</div>
|
||
<div class="open">
|
||
<h3>{{t "about.status.open"}}</h3>
|
||
<ul>
|
||
<li>{{th "about.status.open.fabrics"}}</li>
|
||
<li>{{t "about.status.open.planes"}}</li>
|
||
<li>{{t "about.status.open.weights"}}</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<footer>
|
||
<span>llmgw {{.Version}}</span>
|
||
<span><a href="https://gitea.mynodes.xyz/ilker/llmgw">{{t "about.nav.source"}}</a> ·
|
||
<a href="https://gitea.mynodes.xyz/ilker/llmgw/src/branch/main/CHANGELOG.md">{{t "about.footer.changelog"}}</a> ·
|
||
<a href="https://gitea.mynodes.xyz/ilker/llmgw/src/branch/main/docs/reference.md">{{t "about.footer.reference"}}</a></span>{{if not .Site}}{{template "langs"}}{{end}}
|
||
</footer>
|
||
</div>
|
||
|
||
<script>
|
||
var say = { copy: {{t "about.copy"}}, copied: {{t "about.copied"}}, selected: {{t "about.selected"}} };
|
||
document.querySelectorAll('.copy').forEach(function (b) {
|
||
b.addEventListener('click', function () {
|
||
var text = b.dataset.copy || b.parentElement.querySelector('pre').innerText;
|
||
var done = function (label) { b.textContent = label; setTimeout(function () { b.textContent = say.copy; }, 1600); };
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(text).then(function () { done(say.copied); }, function () { select(); });
|
||
} else { select(); }
|
||
function select() {
|
||
var el = b.dataset.copy ? b.parentElement.querySelector('code') : b.parentElement.querySelector('pre');
|
||
var r = document.createRange(); r.selectNodeContents(el);
|
||
var s = window.getSelection(); s.removeAllRanges(); s.addRange(r);
|
||
done(say.selected);
|
||
}
|
||
});
|
||
});
|
||
</script>
|
||
{{if not .Site}}</body></html>{{end}}{{end}}
|