Instructions to use patdev/k3-a40-bootstrap with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use patdev/k3-a40-bootstrap with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf patdev/k3-a40-bootstrap:BF16 # Run inference directly in the terminal: llama cli -hf patdev/k3-a40-bootstrap:BF16
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf patdev/k3-a40-bootstrap:BF16 # Run inference directly in the terminal: llama cli -hf patdev/k3-a40-bootstrap:BF16
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf patdev/k3-a40-bootstrap:BF16 # Run inference directly in the terminal: ./llama-cli -hf patdev/k3-a40-bootstrap:BF16
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf patdev/k3-a40-bootstrap:BF16 # Run inference directly in the terminal: ./build/bin/llama-cli -hf patdev/k3-a40-bootstrap:BF16
Use Docker
docker model run hf.co/patdev/k3-a40-bootstrap:BF16
- LM Studio
- Jan
- Ollama
How to use patdev/k3-a40-bootstrap with Ollama:
ollama run hf.co/patdev/k3-a40-bootstrap:BF16
- Unsloth Desktop
- Docker Model Runner
How to use patdev/k3-a40-bootstrap with Docker Model Runner:
docker model run hf.co/patdev/k3-a40-bootstrap:BF16
- Lemonade
How to use patdev/k3-a40-bootstrap with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull patdev/k3-a40-bootstrap:BF16
Run and chat with the model
lemonade run user.k3-a40-bootstrap-BF16
List all available models
lemonade list
- Atomic Chat
File size: 8,512 Bytes
e94c0a0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | """Qwen3.8-Flash-Next sur une seule carte, avec la table n-gramme en RAM.
CE QU'ON CHERCHE A SAVOIR. Ce modele bat Claude Opus 4.6 sur SWE-bench Pro
(62,5 contre 53,4) et Multilingual (81,0 contre 77,5), mesures avec le harnais
de Claude Code. Il est donc le bon modele pour cet usage. La seule question est
s'il tourne sur du materiel accessible.
125 B de parametres dont 6 B actifs, PLUS une table d'embeddings n-grammes de
51 B et 4 B de MTP -- 180 B au total. En NVFP4 : 125,9 Go, dont 47,7 pour la
seule table n-gramme.
`VLLM_PLE_CPU_OFFLOAD=1` place cette table en RAM hote. Il reste alors 78,2 Go
sur GPU, ce qui tient sur une RTX PRO 6000 de 96 Go SANS parallelisme de
tenseurs. C'est le point : toute la campagne a montre que les penalites
multi-cartes sont severes, et une carte unique les supprime toutes.
CE QUI PEUT ECHOUER, dans l'ordre de vraisemblance :
1. la RAM hote est insuffisante -- il faut 51 Go plus une marge ;
2. le dechargement fait traverser le PCIe a chaque consultation de n-gramme,
et le debit s'effondre ;
3. l'architecture `Qwen4Exp` n'a jamais ete servie sur sm_120 -- la recette
officielle vise GB300 et H200 ;
4. les parseurs different de Nemotron : `qwen3` et non `nemotron_v3`.
Reperes sur cette meme carte, meme banc, contexte 131 072 :
Nemotron NVFP4 (3,70 B actifs) : 275,3 solo | 910 agrege@8
Socle actif calcule pour Flash-Next : 4,02 Go/jeton -> plafond ~446 tok/s ici.
"""
import json
import os
import re
import statistics
import subprocess
import threading
import time
import urllib.request
MODEL = os.environ.get("BANC_MODEL", "RadixArk/Qwen3.8-Flash-Next-NVFP4")
PORT = 8000
URL = "http://127.0.0.1:%d" % PORT
CTX = os.environ.get("BANC_CTX", "131072")
SEQS = os.environ.get("BANC_SEQS", "32")
def dire(*a):
print(*a, flush=True)
dire("=" * 76)
subprocess.run(["nvidia-smi", "--query-gpu=name,memory.total,compute_cap",
"--format=csv,noheader"], check=False)
subprocess.run(["bash", "-lc",
"echo -n 'RAM hote : '; free -g | awk '/^Mem:/{print $2\" Go total, \"$7\" Go dispo\"}'"],
check=False)
subprocess.run(["python3", "-c",
"import vllm;print('vllm',vllm.__version__)"], check=False)
dire("PLE_CPU_OFFLOAD =", os.environ.get("VLLM_PLE_CPU_OFFLOAD", "(non pose)"))
dire("=" * 76)
BASE = ["vllm", "serve", MODEL,
"--served-model-name", "m",
"--host", "127.0.0.1", "--port", str(PORT),
"--trust-remote-code",
"--max-model-len", CTX,
"--max-num-seqs", SEQS,
"--enable-prefix-caching",
"--gpu-memory-utilization", "0.90",
# Parseurs de CE modele, differents de Nemotron.
"--reasoning-parser", "qwen3",
"--tool-call-parser", "qwen3_coder",
"--enable-auto-tool-choice",
# La recette officielle les recommande explicitement.
"--no-enable-flashinfer-autotune",
# Pas de vision : on sert du texte, et la tour visuelle coute de la
# memoire pour rien dans cet usage.
"--limit-mm-per-prompt", '{"image":0,"video":0}']
SUJETS = ["un cache LRU avec dict et liste doublement chainee",
"un pool de connexions avec expiration et sante des sockets",
"un analyseur d'expressions arithmetiques par descente recursive",
"une file de priorite par tas binaire avec decrease-key",
"un limiteur de debit par seau a jetons",
"un index inverse pour recherche plein texte",
"un ordonnanceur de taches avec dependances et cycles detectes",
"un serialiseur binaire avec versionnement de schema"]
journal = "/tmp/vllm.log"
with open(journal, "w") as f:
proc = subprocess.Popen(BASE, stdout=f, stderr=subprocess.STDOUT)
JALONS = ("Starting to load model", "Loading weights took", "Using ", "PLE",
"offload", "GPU KV cache size", "Capturing CUDA graphs",
"init engine", "Application startup complete", "Error", "Traceback")
pret = None
vus = set()
# Le telechargement fait 125,9 Go : compter large, et publier l'avancement
# sinon on reste aveugle une demi-heure.
for i in range(400):
try:
urllib.request.urlopen(URL + "/v1/models", timeout=5).read()
pret = i * 10
break
except Exception:
pass
if proc.poll() is not None:
break
if i and i % 6 == 0:
t = open(journal, errors="replace").read().splitlines()
recent = [l for l in t[-80:] if any(j in l for j in JALONS)]
msg = recent[-1].split("] ")[-1][:120] if recent else "(rien de neuf, %d lignes)" % len(t)
if msg not in vus:
vus.add(msg)
dire(" [%4d s] %s" % (i * 10, msg))
time.sleep(10)
texte = open(journal, errors="replace").read()
for motif in ("attention backend", "MoE backend", "GEMM", "GPU KV cache size",
"Maximum concurrency", "PLE", "offload"):
for ligne in texte.splitlines():
if motif in ligne and "ERROR" not in ligne:
dire(" " + ligne.split("] ")[-1][:150])
break
if pret is None:
dire("NE DEMARRE PAS")
vu = []
for ligne in texte.splitlines():
m = re.search(r"((?:Value|Runtime|NotImplemented|Assertion|Type|Memory|OS)Error"
r"|out of memory|Unsupported|is not supported|CUDA error)[:\s].{0,170}", ligne)
if m and m.group(0) not in vu:
vu.append(m.group(0))
for t in vu[:6]:
dire(" > " + t)
if not vu:
for ligne in texte.splitlines()[-15:]:
dire(" | " + ligne[:150])
raise SystemExit(1)
dire(" PRET en %d s (contexte %s, %s sequences)" % (pret, CTX, SEQS))
subprocess.run(["nvidia-smi", "--query-gpu=memory.used", "--format=csv,noheader"], check=False)
def appel(contenu, sortie=400):
corps = json.dumps({"model": "m",
"messages": [{"role": "user", "content": contenu}],
"max_tokens": sortie, "temperature": 1.0, "top_p": 0.95,
"stream": True,
"stream_options": {"include_usage": True}}).encode()
r = urllib.request.Request(URL + "/v1/chat/completions", data=corps,
headers={"Content-Type": "application/json"})
t0 = time.time()
t1 = None
n = 0
bouts = []
with urllib.request.urlopen(r, timeout=900) as rep:
for l in rep:
l = l.strip()
if not l.startswith(b"data: ") or l[6:] == b"[DONE]":
continue
d = json.loads(l[6:])
ch = d.get("choices") or []
if not ch:
continue
de = ch[0].get("delta", {}) or {}
x = de.get("content") or de.get("reasoning_content") or de.get("reasoning")
if x:
if t1 is None:
t1 = time.time()
n += 1
bouts.append(x)
return {"ttft": (t1 - t0) if t1 else None, "n": n, "t1": t1,
"t2": time.time(), "txt": "".join(bouts)}
def div4(t):
m = t.split()
if len(m) < 40:
return 1.0
g = [tuple(m[i:i + 4]) for i in range(len(m) - 3)]
return len(set(g)) / len(g)
dire("conc | agrege | par flux | ttft med | 4-gr | etat")
for conc in (1, 4, 8):
res = [None] * conc
def un(i):
try:
res[i] = appel("Ecris en Python %s, avec trois tests unittest."
% SUJETS[i % len(SUJETS)])
except Exception as e:
res[i] = {"err": "%s: %s" % (type(e).__name__, str(e)[:70])}
d0 = time.time()
fils = [threading.Thread(target=un, args=(i,)) for i in range(conc)]
for f in fils:
f.start()
for f in fils:
f.join()
d1 = time.time()
bons = [r for r in res if r and not r.get("err") and r.get("t1")]
if not bons:
dire("%4d | ECHEC %s" % (conc, (res[0] or {}).get("err")))
continue
par = statistics.median([(r["n"] - 1) / (r["t2"] - r["t1"])
for r in bons if r["t2"] > r["t1"]])
ttft = statistics.median([r["t1"] - d0 for r in bons])
dv = statistics.median([div4(r["txt"]) for r in bons])
dire("%4d | %8.1f | %8.1f | %7.2fs | %.3f | %s"
% (conc, sum(r["n"] for r in bons) / (d1 - d0), par, ttft, dv,
"SAIN" if dv > 0.6 else "DEGENERE"))
dire("")
dire("repere meme carte, meme banc : Nemotron NVFP4 275,3 solo | 910 agrege@8")
dire("plafond memoire theorique de Flash-Next ici : ~446 tok/s (socle 4,02 Go)")
proc.terminate()
|