dash
This commit is contained in:
@@ -142,40 +142,52 @@ does not need any of this — it is a standard transformer with no FLA fast path
|
|||||||
- **transformers ≥ 5.12 required** — older versions fail with
|
- **transformers ≥ 5.12 required** — older versions fail with
|
||||||
`'Qwen3_5MoeConfig' object has no attribute 'vocab_size'`. Check:
|
`'Qwen3_5MoeConfig' object has no attribute 'vocab_size'`. Check:
|
||||||
`python -c "import transformers; print(transformers.__version__)"`.
|
`python -c "import transformers; print(transformers.__version__)"`.
|
||||||
- **Optional GPU kernels** — without them inference still works; startup may print
|
- **GPU fast path (optional)** — without it inference still works; startup prints
|
||||||
`The fast path is not available…` (harmless on Windows; slower on linear-attention
|
`The fast path is not available…` and linear-attention layers use a slower PyTorch
|
||||||
layers). Install **only for your platform**:
|
fallback. Install **only for your platform**:
|
||||||
|
|
||||||
| Platform | Install | Fast path? |
|
| Platform | Install | Notes |
|
||||||
|----------|---------|------------|
|
|----------|---------|-------|
|
||||||
| **Native Windows** | `pip install triton-windows` (also pulled by `meshnet-node` on Windows) | **Load only** — model imports and runs on PyTorch fallback. Do **not** `pip install flash-linear-attention[cuda] causal-conv1d` (see below). |
|
| **Native Windows + NVIDIA** | `pip install triton-windows` then `pip install flash-linear-attention` | **Fast path works.** FLA [officially supports `triton-windows`](https://github.com/fla-org/flash-linear-attention/pull/757) (tested Win11, PyTorch 2.10, triton-windows 3.6). Do **not** use the `[cuda]` extra on Windows — pip looks for Linux `triton` and fails. Do **not** install `causal-conv1d` — FLA ≥0.3.2 ships Triton conv1d; the separate package is Linux-only and breaks on Windows (`bare_metal_version` / nvcc errors). |
|
||||||
| **Linux + NVIDIA CUDA** | `pip install flash-linear-attention[cuda]` | **Yes** — `causal-conv1d` optional since FLA ≥0.3.2 ships Triton conv1d; add it only if transformers still asks for it. Needs CUDA toolkit (`nvcc`) or a matching prebuilt wheel. |
|
| **Linux + NVIDIA CUDA** | `pip install flash-linear-attention[cuda]` | `causal-conv1d` optional (same FLA built-in conv1d note). Needs CUDA toolkit (`nvcc`) matching torch, or a prebuilt wheel. |
|
||||||
| **Linux + AMD ROCm** | `pip install flash-linear-attention[rocm]` | **Yes** — same optional `causal-conv1d` note. |
|
| **Linux + AMD ROCm** | `pip install flash-linear-attention[rocm]` | Same optional `causal-conv1d` note. |
|
||||||
|
|
||||||
On native Windows, `triton-windows` is enough for Qwen3.6-MoE to **load**. Without it,
|
**Windows verify** (after install):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python -c "import triton; import fla; print('triton', triton.__version__, 'fla ok')"
|
||||||
|
```
|
||||||
|
|
||||||
|
`triton-windows` is also pulled by `meshnet-node` on Windows. Without it, Qwen3.6-MoE
|
||||||
startup fails with misleading `Could not import module 'Qwen3_5MoeForCausalLM'`.
|
startup fails with misleading `Could not import module 'Qwen3_5MoeForCausalLM'`.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><strong>Why there is no supported Windows fast path (research notes)</strong></summary>
|
<summary><strong>Windows fast path — what failed and what actually works</strong></summary>
|
||||||
|
|
||||||
We checked upstream docs and real install attempts (2026-07):
|
The command that failed — `pip install flash-linear-attention[cuda] causal-conv1d` — mixes
|
||||||
|
two different things:
|
||||||
|
|
||||||
1. **`causal-conv1d`** — no official Windows wheels on PyPI. Source builds need `nvcc`
|
1. **`flash-linear-attention[cuda]` on Windows** — wrong extra. `[cuda]` pulls PyPI
|
||||||
plus a torch/CUDA stack that matches; without `nvcc` pip fails with
|
`triton>=3.3`, which does not exist for Windows (`No matching distribution found`).
|
||||||
`bare_metal_version is not defined`. Open upstream issues confirm Windows is
|
Use plain `pip install flash-linear-attention` **after** `triton-windows` is already
|
||||||
unsupported / broken for most setups.
|
installed; FLA detects `triton-windows` and uses it.
|
||||||
2. **`flash-linear-attention[cuda]`** — FLA's install guide targets Linux (CUDA / ROCm /
|
2. **`causal-conv1d`** — separate Dao-AILab CUDA extension, **not required** for FLA or
|
||||||
XPU / NPU). The `[cuda]` extra pulls PyPI `triton`, which conflicts with
|
Qwen3.6 when FLA is installed. No official Windows wheels. Source builds need `nvcc`
|
||||||
`triton-windows` on native Windows. FLA does not document or CI-test Windows.
|
whose major version matches torch's CUDA (e.g. torch `+cu118` needs CUDA 11.8 toolkit,
|
||||||
3. **What works today on native Windows GPU** — CUDA torch + `triton-windows` → Qwen3.6
|
not 12.5). Community wheels exist for narrow Python/torch combos
|
||||||
loads and infers via Transformers' pure-PyTorch fallback (~¾ of layers are
|
([PR #46](https://github.com/Dao-AILab/causal-conv1d/pull/46)) but we skip them.
|
||||||
linear-attention; those hops are slower). This is what we use in alpha.
|
|
||||||
4. **If you need the fast path on a Windows PC** — run the GPU node in **WSL2 with Linux
|
**Working Windows stack** (confirmed on this repo's dev machine: Python 3.12, torch
|
||||||
CUDA** (or a Linux box): `pip install flash-linear-attention[cuda]` there. Keep
|
2.7.1+cu118, triton-windows 3.7.1, flash-linear-attention 0.5.0):
|
||||||
Windows native for reachability / relay if needed.
|
|
||||||
5. **Experimental / unsupported** — community `causal-conv1d` wheels and
|
```powershell
|
||||||
`triton-windows` + pinned `flash-linear-attention --no-deps` hacks exist for narrow
|
pip install triton-windows
|
||||||
Python/torch/CUDA combos; we do not support or test these for meshnet-node.
|
pip install -U flash-linear-attention
|
||||||
|
python -c "import triton; import fla; print('ok')"
|
||||||
|
```
|
||||||
|
|
||||||
|
If the fast-path warning persists after that, upgrade FLA to ≥0.5.1 (includes the
|
||||||
|
`triton-windows` detection from PR #757) and restart the node.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -289,9 +301,8 @@ curl -sI https://ai.neuron.d-popov.com/rpc/test-peer
|
|||||||
no HuggingFace gating. Best for first-time setup.
|
no HuggingFace gating. Best for first-time setup.
|
||||||
|
|
||||||
**Alpha model:** `qwen3.6-35b-a3b` — 40 layers, ~72 GB BF16 download, MoE with hybrid
|
**Alpha model:** `qwen3.6-35b-a3b` — 40 layers, ~72 GB BF16 download, MoE with hybrid
|
||||||
linear attention. Use on machines with enough RAM/VRAM; see Qwen3.5/3.6 notes above for
|
linear attention. On Windows install `triton-windows` + `flash-linear-attention`; on Linux
|
||||||
`triton-windows` (Windows) or `flash-linear-attention` (Linux GPU). Tracker accepts the
|
GPU use `flash-linear-attention[cuda]`. Tracker accepts the alias or full repo id (`unsloth/Qwen3.6-35B-A3B`).
|
||||||
alias or full repo id (`unsloth/Qwen3.6-35B-A3B`).
|
|
||||||
|
|
||||||
Downloads cache under `~/.meshnet/models/` (or `$HF_HOME` / `$env:HF_HOME`).
|
Downloads cache under `~/.meshnet/models/` (or `$HF_HOME` / `$env:HF_HOME`).
|
||||||
|
|
||||||
@@ -330,13 +341,17 @@ HF_HOME=/path/to/models .venv/bin/meshnet-node start --tracker http://localhost:
|
|||||||
.venv/bin/meshnet-node start --tracker https://ai.neuron.d-popov.com --model Qwen/Qwen2.5-0.5B-Instruct
|
.venv/bin/meshnet-node start --tracker https://ai.neuron.d-popov.com --model Qwen/Qwen2.5-0.5B-Instruct
|
||||||
```
|
```
|
||||||
|
|
||||||
**Alpha model (Qwen3.6, Windows GPU — PyTorch fallback, no FLA fast path):**
|
**Alpha model (Qwen3.6, Windows GPU — enable fast path):**
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
$env:HF_HOME = "D:\DEV\models"
|
$env:HF_HOME = "D:\DEV\models"
|
||||||
|
pip install triton-windows
|
||||||
|
pip install -U flash-linear-attention
|
||||||
meshnet-node start --tracker http://192.168.0.179:8080 --model qwen3.6-35b-a3b --quantization bfloat16
|
meshnet-node start --tracker http://192.168.0.179:8080 --model qwen3.6-35b-a3b --quantization bfloat16
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Do not add `causal-conv1d` or `flash-linear-attention[cuda]` on Windows (see Qwen3.5/3.6 notes).
|
||||||
|
|
||||||
**Alpha model (Qwen3.6, Linux GPU — with fast path):**
|
**Alpha model (Qwen3.6, Linux GPU — with fast path):**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -279,6 +279,41 @@ const tps = v => (v === null || v === undefined) ? "?" : (Math.round(v * 10) / 1
|
|||||||
const copies = v => (v === null || v === undefined) ? "?" : Number(v).toFixed(2);
|
const copies = v => (v === null || v === undefined) ? "?" : Number(v).toFixed(2);
|
||||||
const short = (s, n=14) => { s = String(s); return s.length > n ? s.slice(0, 6) + "…" + s.slice(-5) : s; };
|
const short = (s, n=14) => { s = String(s); return s.length > n ? s.slice(0, 6) + "…" + s.slice(-5) : s; };
|
||||||
|
|
||||||
|
function modelAliasKey(value) {
|
||||||
|
if (!value) return "";
|
||||||
|
const text = String(value).trim();
|
||||||
|
if (!text) return "";
|
||||||
|
const shortName = text.includes("/") ? text.split("/").pop() : text;
|
||||||
|
return shortName.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildModelAliasMap(map) {
|
||||||
|
const byAlias = new Map();
|
||||||
|
const register = (display, ...names) => {
|
||||||
|
if (!display) return;
|
||||||
|
for (const name of names) {
|
||||||
|
const key = modelAliasKey(name);
|
||||||
|
if (key) byAlias.set(key, display);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (const entry of (map && map.recommended_models) || []) {
|
||||||
|
register(entry.id, entry.id, entry.hf_repo, ...(entry.aliases || []));
|
||||||
|
}
|
||||||
|
for (const entry of availableModels || []) {
|
||||||
|
register(entry.name || entry.id, entry.id, entry.name, ...(entry.aliases || []));
|
||||||
|
}
|
||||||
|
return byAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveModelGroup(node, aliasMap) {
|
||||||
|
for (const candidate of [node.hf_repo, node.model]) {
|
||||||
|
if (!candidate) continue;
|
||||||
|
const hit = aliasMap.get(modelAliasKey(candidate));
|
||||||
|
if (hit) return hit;
|
||||||
|
}
|
||||||
|
return node.hf_repo || node.model || "?";
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchJson(path) {
|
async function fetchJson(path) {
|
||||||
try {
|
try {
|
||||||
const headers = {};
|
const headers = {};
|
||||||
@@ -315,15 +350,20 @@ function renderNodes(map) {
|
|||||||
if (!nodes.length) {
|
if (!nodes.length) {
|
||||||
$("nodes").innerHTML = '<div class="empty">no nodes registered</div>'; return;
|
$("nodes").innerHTML = '<div class="empty">no nodes registered</div>'; return;
|
||||||
}
|
}
|
||||||
|
const aliasMap = buildModelAliasMap(map);
|
||||||
const byModel = {};
|
const byModel = {};
|
||||||
for (const n of nodes) {
|
for (const n of nodes) {
|
||||||
const key = n.model || n.hf_repo || "?";
|
const key = resolveModelGroup(n, aliasMap);
|
||||||
(byModel[key] = byModel[key] || []).push(n);
|
(byModel[key] = byModel[key] || []).push(n);
|
||||||
}
|
}
|
||||||
|
const modelNames = Object.keys(byModel).sort((a, b) => a.localeCompare(b));
|
||||||
let html = "";
|
let html = "";
|
||||||
for (const [model, group] of Object.entries(byModel)) {
|
for (const model of modelNames) {
|
||||||
const supply = group.find(n => n.model_supply && n.model_supply.served_model_copies !== undefined);
|
const group = byModel[model];
|
||||||
const served = supply && supply.model_supply && supply.model_supply.served_model_copies;
|
const servedValues = group
|
||||||
|
.map(n => n.model_supply && n.model_supply.served_model_copies)
|
||||||
|
.filter(v => v !== null && v !== undefined);
|
||||||
|
const served = servedValues.length ? Math.max(...servedValues) : undefined;
|
||||||
html += `<div><b>${esc(model)}</b> <span class="dim">(${group.length} node${group.length===1?"":"s"} · ${esc(copies(served))} served)</span></div>`;
|
html += `<div><b>${esc(model)}</b> <span class="dim">(${group.length} node${group.length===1?"":"s"} · ${esc(copies(served))} served)</span></div>`;
|
||||||
html += table(["node", "shard", "tps (1h)", "queue", "served"], group.map(n => {
|
html += table(["node", "shard", "tps (1h)", "queue", "served"], group.map(n => {
|
||||||
const modelStats = (n.throughput && (n.throughput[n.hf_repo] || n.throughput[n.model])) || {};
|
const modelStats = (n.throughput && (n.throughput[n.hf_repo] || n.throughput[n.model])) || {};
|
||||||
@@ -1552,6 +1592,19 @@ async function refresh() {
|
|||||||
renderChatHistory();
|
renderChatHistory();
|
||||||
$("refreshed").textContent = "refreshed " + new Date().toLocaleTimeString();
|
$("refreshed").textContent = "refreshed " + new Date().toLocaleTimeString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const REFRESH_MS = 10000;
|
||||||
|
|
||||||
|
function selectionActive() {
|
||||||
|
const sel = window.getSelection();
|
||||||
|
return sel && !sel.isCollapsed && sel.toString().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshIfIdle() {
|
||||||
|
if (selectionActive()) return;
|
||||||
|
await refresh();
|
||||||
|
}
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
initChatSessions();
|
initChatSessions();
|
||||||
bindChatPromptShortcuts();
|
bindChatPromptShortcuts();
|
||||||
@@ -1559,8 +1612,12 @@ renderAccountPanel();
|
|||||||
renderChatModels();
|
renderChatModels();
|
||||||
renderChatHistory();
|
renderChatHistory();
|
||||||
renderChatAuthHint();
|
renderChatAuthHint();
|
||||||
setInterval(refresh, 4000);
|
setInterval(refreshIfIdle, REFRESH_MS);
|
||||||
setInterval(() => { if (sessionToken || isLoggedIn) renderAccountPanel(); }, 8000);
|
setInterval(() => {
|
||||||
|
if (!sessionToken && !isLoggedIn) return;
|
||||||
|
if (selectionActive()) return;
|
||||||
|
renderAccountPanel();
|
||||||
|
}, REFRESH_MS);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ def test_dashboard_served_with_all_panels():
|
|||||||
for panel in PANELS:
|
for panel in PANELS:
|
||||||
assert panel in html
|
assert panel in html
|
||||||
assert "<script>" in html # polling client embedded, no build step
|
assert "<script>" in html # polling client embedded, no build step
|
||||||
|
assert "resolveModelGroup" in html
|
||||||
|
assert "buildModelAliasMap" in html
|
||||||
finally:
|
finally:
|
||||||
tracker.stop()
|
tracker.stop()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user