Model Nano
LFM3-1.7B · Q4_K_M · GGUF
A compact language model for short answers and quick drafts. The whole model is a 1.1 GB file that loads into GPU memory.
Model Nano is the smallest model in the HummingRelay lineup, and the only one that runs on your own GPU. A 1.7B-parameter language model, executed in the browser by hand-written WGSL kernels. No endpoint, no API key.
The first run downloads 1.1 GB of weights from this origin and keeps them in browser storage. After that the model starts without a network.
model-nano-q4km.gguf
tokens → this tab
local
inference server
none
requests per prompt
zero
The weights are fetched once and cached in the browser's private storage (OPFS). From then on, prompts, tokens and replies stay inside the tab.
Model Zero and Model One run on HummingRelay infrastructure, behind the API. Model Nano takes the other route: the weights come to you, and the GPU you already own does the work.
LFM3-1.7B · Q4_K_M · GGUF
A compact language model for short answers and quick drafts. The whole model is a 1.1 GB file that loads into GPU memory.
Speed and memory depend on your GPU, so they are not listed here. The console shows what this device actually measures once the model is running. The API models are in the HummingRelay model catalog.
From a file in browser storage to a word on screen. There is no general-purpose runtime in between: the kernels are written for this one model.
The browser parses the header, the vocabulary and the tensor table. It is the same .gguf format llama.cpp uses; nothing is converted.
Q4_K, Q5_K and Q6_K blocks go into GPU buffers as they are. They are never expanded to 32-bit floats, which keeps memory low.
Compute shaders unpack the weights on the fly and run all 24 layers: convolutions, attention, normalization and the output logits.
The next token is sampled from the logits, the BPE tokenizer turns it into text, and it appears in the console right away.
import { ModelNano } from "./nano.js";
const engine = await ModelNano.create({
modelUrl: "./model-nano-q4km.gguf",
cache: "opfs", // keep the weights in browser storage
});
const messages = [{ role: "user", content: "Explain WebGPU in one line." }];
for await (const ev of engine.generate(messages, { maxTokens: 256 })) {
if (ev.type === "token") write(ev.text);
if (ev.type === "done") console.log(ev.stats.tokPerSec);
}
const engine = await ModelNano.create({
modelUrl,
maxContext: 4096,
onProgress({ phase, loaded, total }) {
// phase: "download" | "upload" | "compile" | "warmup"
bar.value = loaded / total;
},
});
// what was loaded, and where it runs
const { quant, layers, adapter, vramBytes, loadMs } = engine.info;
const controller = new AbortController();
stopButton.onclick = () => controller.abort();
for await (const ev of engine.generate(messages, { signal: controller.signal })) {
if (ev.type === "done") console.log(ev.finishReason); // "abort"
}
engine.reset(); // start a new conversation
{ type: "token", text, id, thinking }
{ type: "done", finishReason: "stop" | "length" | "abort", stats }
stats: { promptTokens, cachedTokens, promptMs, ttftMs, genTokens, genMs, tokPerSec }
The engine is plain ES modules: no bundler, no framework, no runtime dependency. This page uses the same interface.
Generation speed in tokens per second, against other ways to run the same weights on the same hardware. No number appears here until it has been measured.
Reading benchmark results…
There is no server behind this page that could receive a conversation. Here is exactly what touches the network and what never does.
Text becomes tokens and is processed by this device's GPU. The conversation lives in the tab's memory and is gone when you close it.
The model file is kept in OPFS, the browser's private storage for this site. Later runs load it from there.
Sampling parameters and the system prompt are saved in this browser's local storage, nowhere else.
HTML, styles, scripts and fonts, all served from this origin. No CDN, no third-party fonts, no analytics.
1.1 GB, downloaded from this origin on the first run. Skipped on every run after that.
Generation makes no requests at all. You can go offline after the first load and keep working.
Model Nano is small. It is good at short answers, drafts and simple code, and like any model of this size it can be wrong, sometimes confidently. Check anything that matters.
Only to open the page and to download the weights once, 1.1 GB. They are saved in browser storage, so later runs start without a network. Generation itself never uses the network.
Nowhere. Text is turned into tokens and processed by the GPU in this device. The page has no server that could receive a conversation and loads no third-party scripts.
You need a browser with WebGPU. Model Nano is developed and tested in desktop Chrome. Other WebGPU browsers may work but have not been verified. If WebGPU is unavailable, the page says so before it downloads anything.
The weights take about 1.1 GB, plus buffers for the context. The console reports the GPU memory actually in use once the model is loaded.
It has four stages: download the file, move the weights into GPU memory, compile the shaders and warm them up. From the second run on, the download is skipped.
Model Nano is part of the same lineup but needs no account, key or credits: it runs on your hardware. Model Zero and Model One are larger models served through the HummingRelay API.
Load it once. After that it starts from browser storage and answers without a network.
Starting0.0 s
Before the download1.13 GB · one time
Model Nano is about to download its weights into this browser. After that it runs on your device, and nothing you type leaves this tab. By continuing you agree to the following.
WebGPU unavailable
Model Nano runs the model on your graphics card through WebGPU. That interface is missing or switched off here, so the weights were not downloaded.
https:// or from localhost: WebGPU is disabled in insecure contexts.chrome://gpu.Error