Instructions to use SASVAAI/muse-glimmer-30b-kernelgen with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use SASVAAI/muse-glimmer-30b-kernelgen with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="SASVAAI/muse-glimmer-30b-kernelgen") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("SASVAAI/muse-glimmer-30b-kernelgen") model = AutoModelForMultimodalLM.from_pretrained("SASVAAI/muse-glimmer-30b-kernelgen", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - PEFT
How to use SASVAAI/muse-glimmer-30b-kernelgen with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use SASVAAI/muse-glimmer-30b-kernelgen 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 SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M # Run inference directly in the terminal: llama cli -hf SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M # Run inference directly in the terminal: llama cli -hf SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
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 SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
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 SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
Use Docker
docker model run hf.co/SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use SASVAAI/muse-glimmer-30b-kernelgen with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "SASVAAI/muse-glimmer-30b-kernelgen" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "SASVAAI/muse-glimmer-30b-kernelgen", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
- SGLang
How to use SASVAAI/muse-glimmer-30b-kernelgen with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "SASVAAI/muse-glimmer-30b-kernelgen" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "SASVAAI/muse-glimmer-30b-kernelgen", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "SASVAAI/muse-glimmer-30b-kernelgen" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "SASVAAI/muse-glimmer-30b-kernelgen", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Ollama
How to use SASVAAI/muse-glimmer-30b-kernelgen with Ollama:
ollama run hf.co/SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
- Unsloth Desktop
- Pi
How to use SASVAAI/muse-glimmer-30b-kernelgen with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use SASVAAI/muse-glimmer-30b-kernelgen with Docker Model Runner:
docker model run hf.co/SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
- Lemonade
How to use SASVAAI/muse-glimmer-30b-kernelgen with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
Run and chat with the model
lemonade run user.muse-glimmer-30b-kernelgen-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use SASVAAI/muse-glimmer-30b-kernelgen with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use SASVAAI/muse-glimmer-30b-kernelgen with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "SASVAAI/muse-glimmer-30b-kernelgen:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
muse-glimmer-30b-kernelgen
Generates Triton GPU kernels from PyTorch module specifications. Merged
fine-tune for developers porting nn.Module code to hand-written
@triton.jit kernels.
This is a merged fine-tune of
meta-models/Muse-Glimmer-30B:
the LoRA adapter has been fused into the base weights with
merge_and_unload(), so it loads as an ordinary transformers checkpoint with
no PEFT dependency. It was trained with QLoRA (4-bit NF4 base) via
TRL SFT.
Model details
| Developed by | SASVA AI Model Cognition Labs(MCL) Team |
| Base model | meta-models/Muse-Glimmer-30B |
| Base parameters | 29.8B (~1.8B of which is the vision tower, left untouched) |
| Architecture family | muse_glimmer (MuseGlimmerForConditionalGeneration) |
| Adaptation | LoRA (r=16, alpha=32, dropout=0.05), merged into the base |
| Trainable modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj |
| Excluded modules | .*vision_tower.* (the vision tower was not adapted) |
| Training method | qlora (4-bit NF4 base, bf16 compute) |
| Refinement | none (SFT only) |
| Precision in this repo | bfloat16, unquantized |
| Weights | 2 safetensors shards, 56 GB total |
| Context length | 131,072 (base capability); trained at 8,192 |
| Language | English (source code + identifiers) |
| License | Apache-2.0, inherited from the base model |
The config here carries no quantization_config — 4-bit was a training-time
choice, not a property of these weights.
Intended use
Direct use. Given a PyTorch nn.Module (plus the get_inputs() /
get_init_inputs() helpers that define its shapes), emit a self-contained
Python file implementing the same computation with @triton.jit kernels and
host-side launch code.
The prompt format is part of the contract. The model was trained on one exact rendering; see How to get started. Prompting it as a general chat model will not reproduce its behaviour.
How to get started
Prompt format
The model uses the base model's ATEM chat template. Training rendered each sample as (newlines shown literally):
<|begin_of_text|><|start|>system<|message|>{SYSTEM}
Reasoning strength: high.
# Valid recipients: "self", "user".<|eot|><|start|>user<|message|>{INSTRUCTION}
```
{PYTORCH_SOURCE}
```<|eot|><|start|>assistant to=user<|message|>{TRITON_SOURCE}<|eot|>
Three things follow from this, and all three bite in practice:
- The
Reasoning strength: high.and# Valid recipients:lines are injected by the template itself — they were part of every training sample. Useapply_chat_template; do not hand-build the string. - The user turn is
instruction, then a blank line, then the source inside a fenced code block. add_generation_prompt=Truestops at<|start|>assistant, so the model itself emits the recipient headerto=userbefore the code. This is correct behaviour, not a bug — strip everything up to and including the header, or prefill it.
System prompt
This is the exact system prompt the adapter was trained under, recovered from the training launch command. Changing it moves the model off its trained contract.
You are a GPU kernel engineer. Given a specification (either a PyTorch nn.Module to port or a custom_kernel signature with reference implementation), write a complete, correct, and fast Python source file using Triton @triton.jit kernels with appropriate host-side launcher code, preserving the exact public class name and forward signature or custom_kernel entry point as specified. Output only raw Python source code with no explanation or markdown.
Note the tension between that prompt and the data: it says "preserving the exact public class name", but the training targets follow the KernelBook convention of appending
New(relu->reluNew). The data wins — the model renames the class. Do not rely on the prompt's wording here.
Loading it
from_pretrained requests files by name, so it fetches the config, tokenizer
and safetensors shards only — the GGUF in this repo costs transformers users
nothing. If you instead download the repo by hand, filter it, or you will pull
all 73 GB:
hf download SASVAAI/muse-glimmer-30b-kernelgen --exclude "*.gguf" --local-dir ./muse-glimmer-kernelgen
Requires a transformers build that knows model_type: muse_glimmer. It is
not in any stable PyPI release as of 2026-09-14 — install from git main.
Note also that AutoModelForCausalLM cannot load this architecture
(muse_glimmer has no causal-LM mapping at all); use
AutoModelForImageTextToText.
import torch
from transformers import AutoModelForImageTextToText, AutoTokenizer
MODEL = "SASVAAI/muse-glimmer-30b-kernelgen"
tokenizer = AutoTokenizer.from_pretrained(MODEL, trust_remote_code=True)
model = AutoModelForImageTextToText.from_pretrained(
MODEL, dtype=torch.bfloat16, device_map="auto",
trust_remote_code=True, attn_implementation="sdpa",
)
model.eval()
SYSTEM = (
"You are a GPU kernel engineer. Given a specification (either a PyTorch "
"nn.Module to port or a custom_kernel signature with reference "
"implementation), write a complete, correct, and fast Python source file "
"using Triton @triton.jit kernels with appropriate host-side launcher "
"code, preserving the exact public class name and forward signature or "
"custom_kernel entry point as specified. Output only raw Python source "
"code with no explanation or markdown."
)
instruction = "Write a complete, self-contained Triton implementation that computes the same result."
pytorch_src = '''import torch
class RMulInt(torch.nn.Module):
def forward(self, x):
return 10 * x
def get_inputs():
return [torch.rand([4, 4, 4, 4])]
def get_init_inputs():
return [[], {}]
'''
messages = [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": f"{instruction}\n\n```\n{pytorch_src.strip()}\n```"},
]
inputs = tokenizer.apply_chat_template(
messages, add_generation_prompt=True, enable_thinking=False,
tokenize=True, return_tensors="pt",
).to(model.device)
out = model.generate(inputs, max_new_tokens=2048, do_sample=False)
text = tokenizer.decode(out[0][inputs.shape[-1]:], skip_special_tokens=True)
# Strip the ATEM recipient header the model emits before its content.
print(text.split("to=user", 1)[-1].lstrip() if "to=user" in text else text)
Run locally with Ollama
The Q4_K_M GGUF ships in this repo, so there is nothing to build. Either of these works:
# A. One command — Ollama pulls the GGUF straight from this repo
ollama run hf.co/SASVAAI/muse-glimmer-30b-kernelgen
# B. Or fetch the GGUF plus the Modelfile and build the tag locally
hf download SASVAAI/muse-glimmer-30b-kernelgen \
--include "*Q4_K_M.gguf" "Modelfile" --local-dir .
ollama create muse-glimmer-kernelgen -f Modelfile
ollama run muse-glimmer-kernelgen
Either way you download 16.9 GB, not the 56 GB of bf16 safetensors — Ollama only fetches the GGUF.
The two paths are not quite equivalent. ollama run hf.co/... never reads a
Modelfile. The Hub serves this repo to Ollama through its own
OCI-compatible registry: it picks the Q4_K_M GGUF as the model layer, and
attaches this repo's params and system files as the parameter and
system-prompt layers. Those two files are kept byte-equivalent to the
Modelfile's PARAMETER lines and SYSTEM block, so both routes land on the
same greedy, system-prompted configuration. The chat template comes from the
GGUF's embedded tokenizer.chat_template on both paths (see
below). Path B is the one to
use if you want to edit any of it.
What the hf.co path serves
Path A depends on machinery outside this repo: the Hub renders a GGUF repo as an Ollama manifest, and Ollama pulls it like a container image. That was tested directly against the Hub's registry rather than assumed.
The transport works. ollama pull hf.co/bartowski/Llama-3.2-1B-Instruct-GGUF
on this host (Ollama v0.34.0) fetched 807 MB at 156 MB/s, wrote a manifest with
model / template / params layers exactly as the registry declared them, and
/api/generate returned done_reason: "stop". Nothing about the mechanism is
specific to that repo.
The Hub uses your files when you provide them. Fetching
GET https://huggingface.co/v2/{repo}/manifests/latest for repos that ship a
loose params or template file — Qwen/Qwen3-4B-GGUF,
unsloth/gpt-oss-20b-GGUF — returns layers byte-identical to those files.
Repos with no such files (bartowski/Llama-3.2-1B-Instruct-GGUF) get
synthesized ones. So this repo's params and system are what will be served,
not defaults.
This architecture gets a correct derived template. There is deliberately no
template file here, because Ollama templates must be Go, not Jinja. The Hub
covers that case by matching the GGUF's embedded tokenizer.chat_template
against a library of known templates. For
meta-models/Muse-Glimmer-30B-GGUF — same architecture, and its GGUF embeds a
chat template md5-identical to this repo's chat_template.jinja
(216c1d8e91a69ac1723bf341ec0d2c17) — the Hub serves this 280-byte Go template:
{{ if .System }}<|begin_of_text|><|start|>system<|message|>{{ .System }}
Reasoning strength: high.
# Valid recipients: "self", "user".<|eot|>{{ end }}{{ if .Prompt }}<|start|>user<|message|>{{ .Prompt }}<|eot|>{{ end }}<|start|>assistant to=user<|message|>{{ .Response }}<|eot|>
That is the correct ATEM protocol. Rendered with this repo's system file and a
real prompt, it is byte-identical to what chat_template.jinja produces for the
first 1,494 characters — every token of the system and user turns — and diverges
only at the tail, where it pre-fills the full trained header
<|start|>assistant to=user<|message|> (312 prompt tokens) rather than stopping
at <|start|>assistant (309).
Ollama v0.34.0 ignores that Go template and renders the embedded Jinja.
Measured here: building three local tags from this GGUF — one with the Hub's Go
template, one with a deliberately mangled marker template, one with none —
produced the same 113-token prompt and the same reply in all three cases.
ollama show --template returns the ATEM Jinja template in every case. So on a
current Ollama, path A renders exactly as the verified path B does: a 309-token
prompt, and a reply that opens with to=user<|message|> for you to strip. On
an older Ollama without a Jinja renderer the Hub's Go template would be used
instead — also correct, but it pre-fills that header, so the reply will not
carry it. Strip the prefix if present rather than assuming either.
The system file is load-bearing, not decoration. The same GGUF built
without it drops from 113 to 58 prompt tokens and degenerates immediately,
emitting stray <|start|>assistant headers instead of code. Do not delete it.
The 56 GB of safetensors do not interfere. Of 600 GGUF repos surveyed, 28 ship root-level safetensors alongside GGUFs; their Ollama manifests resolve to a GGUF and ignore the safetensors entirely. Ollama pulls 16.9 GB from this repo, never the bf16 weights.
Two things remain untested, both requiring the published repo: the pull of
this repo id, and the SSH-key handshake Ollama needs for a private repo
(cat ~/.ollama/id_ed25519.pub → https://huggingface.co/settings/keys).
Building your own GGUF (optional)
Steps 0-2 below are needed only if you want a quantisation other than the
shipped Q4_K_M. Steps 3-4 are the verified ollama create and ollama run
transcript, and they apply unchanged to the GGUF in this repo.
Support for this architecture landed in llama.cpp in
PR #26841 ("model: Muse
Glimmer Support", merged 2026-08-10, merge commit 62bf73d25c) with the GGUF
arch string muse-glimmer (LLM_ARCH_MUSE_GLIMMER, src/llama-arch.cpp;
model implementation src/models/muse-glimmer.cpp; converter
conversion/muse_glimmer.py).
0. The transformers pin in llama.cpp's requirements will break the conversion
This is the one step that fails out of the box, so do it before anything else.
requirements/requirements-convert_hf_to_gguf.txt pulls in
requirements-convert_legacy_llama.txt, which pins transformers==4.57.6.
This repo's tokenizer_config.json declares "tokenizer_class": "TokenizersBackend", a class that only exists in transformers 5.x. With the
pinned version, conversion dies while reading the vocab:
ValueError: Tokenizer class TokenizersBackend does not exist or is not currently imported
Install transformers 5.x after the requirements file so it wins:
pip install -r requirements/requirements-convert_hf_to_gguf.txt
pip install 'transformers>=5.17' # overrides the 4.57.6 pin above
Do not work around this by editing tokenizer_config.json — the declared
class is correct for the tokenizer this model ships.
Pre-flight the vocab before committing to a ~52 GB write:
python convert_hf_to_gguf.py /path/to/muse-glimmer-30b-kernelgen \
--outfile /tmp/vocab-probe.gguf --vocab-only
1. Convert to GGUF
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
# ... the two pip commands from step 0 ...
python convert_hf_to_gguf.py /path/to/muse-glimmer-30b-kernelgen \
--outfile muse-glimmer-30b-kernelgen-bf16.gguf \
--outtype bf16
Measured output: 55,725,514,560 bytes (51.9 GiB), 731 tensors. Make sure the filesystem has room for that plus the quantised copy.
You do not need a vision projector. The converter registers two classes for
this architecture — MuseGlimmerModel(TextModel) and
MuseGlimmerVisionModel(MmprojModel). A plain convert_hf_to_gguf.py
invocation produces the text model only; the projector is a separate
--mmproj run. Verified on the output above: zero mmproj/vision_tower
tensors, consistent with the vision tower having been excluded from training.
Why the GGUF has 731 tensors when this repo has 627 non-vision ones
The converter is not a 1:1 repack, so don't compare the two counts directly:
- It synthesizes
attn_q_normandattn_k_norm(lengthhead_dim= 128) for every block to absorbqk_scale_factor, which this model applies as a scaleless RMSNorm followed by a scalar (conversion/muse_glimmer.py). That is 2 × 52 blocks = 104 tensors — exactly the 731 − 627 difference. - It adds 1.0 to every
*layernorm.weight(zero-centred norms). - It un-permutes Q/K projections to match ggml's interleaved RoPE.
So GGUF tensor values are deliberately not bit-identical to the safetensors.
2. Quantize
bf16 needs ~52 GiB resident. Quantize unless you have that much VRAM:
cmake -B build && cmake --build build --config Release -j
./build/bin/llama-quantize muse-glimmer-30b-kernelgen-bf16.gguf \
muse-glimmer-30b-kernelgen-Q4_K_M.gguf Q4_K_M
Measured on this repo's weights (Q4_K_M took 80 s on 48 threads):
| Quant | Size on disk | BPW | Status |
|---|---|---|---|
bf16 |
55,725,514,560 B — 51.9 GiB | 16.00 | measured |
Q4_K_M |
16,935,295,040 B — 15.8 GiB | 4.86 | measured |
llama-quantize reported model size = 53131.48 MiB → quant size = 16138.25 MiB. Other K-quants land between these two; the two rows above are the
only ones actually built and run here, so they are the only ones quoted.
For calibration, the base model card reports its own K-quants at 0.2% degradation in 32 GB of VRAM and 1.0% at 17 GB / 24 GB VRAM. Those are the base model's figures on the base model's benchmarks — not this fine-tune's, and not on this task.
3. Create the Ollama model
A ready-to-use Modelfile ships in this repo: it pins greedy
decoding, an 8,192-token context to match training, the two stop tokens, and the
verbatim training system prompt. Point its FROM line at the GGUF you built,
then:
ollama create kernelgen-muse-glimmer -f Modelfile
Verified — ollama show then reports:
Model
architecture muse-glimmer
parameters 27.9B
context length 131072
embedding length 6656
quantization Q4_K_M
Parameters
num_predict 2048
stop "<|eot|>"
stop "<|end_of_text|>"
temperature 0
top_k 1
num_ctx 8192
Three things that are easy to get wrong, all confirmed on this build:
num_ctxis load-bearing. Ollama sizes the default context from available VRAM and on this host chosedefault_num_ctx=262144. TheModelfilepins 8,192 to matchMAX_SEQ_LENat training time.- The chat template comes across intact.
ollama show --templatereturns the ATEM Jinja template embedded in the GGUF. That template is byte-identical (md5216c1d8e91a69ac1723bf341ec0d2c17) to llama.cpp's own bundledmodels/templates/muse-glimmer.jinja, and Ollama's rendering of the example below tokenised to 309 tokens — the same count thetransformerstokenizer produces for the same messages. ollama showlists atoolscapability. That comes from the base model's ATEM template, not from this fine-tune. This adapter was trained only on single-turn kernel generation; tool calling is untrained here.parameters 27.9Bis the right number, and it is a useful check. The base is 29.8B including a ~1.8B vision tower (see Model details); 28.0B of text weights is what should survive, and 27.9B is what Ollama counts. A figure near 29.8B here would mean you had converted the vision tower too.
4. Run it
ollama run kernelgen-muse-glimmer
Then paste your instruction, a blank line, and the PyTorch source in a fenced code block — the same shape as the training data:
Write a complete, self-contained Triton implementation that computes the same result.
```
import torch
class RMulInt(torch.nn.Module):
def forward(self, x):
return 10 * x
def get_inputs():
return [torch.rand([4, 4, 4, 4])]
def get_init_inputs():
return [[], {}]
```
Or via the API:
curl http://localhost:11434/api/generate -d '{
"model": "kernelgen-muse-glimmer",
"prompt": "Write a complete, self-contained Triton implementation that computes the same result.\n\n```\nimport torch\n\nclass RMulInt(torch.nn.Module):\n def forward(self, x):\n return 10 * x\n\ndef get_inputs():\n return [torch.rand([4, 4, 4, 4])]\n\ndef get_init_inputs():\n return [[], {}]\n```",
"options": {"temperature": 0, "num_predict": 2048, "num_ctx": 8192},
"stream": false
}'
The prompt above is abridged for readability. The verified run used this
same endpoint and model, with the full-length instruction and source of
Example 2 below (309 prompt tokens),
and "options": {"num_thread": 48} — every other decoding setting came from the
Modelfile. Ollama's reply:
"done": true, "done_reason": "stop",
"prompt_eval_count": 309, "eval_count": 469,
"load_duration": 13.38s, "prompt_eval_duration": 3.89s, "eval_duration": 49.26s
That is 9.52 generated tokens/s on CPU alone with no GPU offload, and the
response began with the to=user<|message|> header and ended cleanly at
<|eot|> (done_reason: "stop").
Set
num_threadif you are on a many-core shared box. Left to its own defaults, Ollama used all 192 logical cores on this host and the same request took over 17 minutes (≈0.45 tok/s) because it was contending with other tenants. Adding"num_thread": 48brought it to the 66 s above — a >15× difference from one option. Pass it inoptions, or addPARAMETER num_thread 48to theModelfile.
Two cross-checks that the Ollama path is faithful, both measured here:
- Ollama and
llama-serverproduce byte-identical output from this GGUF for this prompt under greedy decoding (1,379 characters each, 469 tokens each), so Ollama's template rendering and parameter handling introduce no drift. - Ollama's prompt tokenised to 309 tokens, the same count
transformersproduces for the same system+user messages — so theModelfileSYSTEMblock plus the GGUF's embedded template reconstruct the training-time prompt.
One difference from the transformers examples further down this card:
Ollama returns the raw <|message|> tag. The transformers snippet decodes
with skip_special_tokens=True and so yields to=user, while Ollama's HTTP
response literally begins to=user<|message|>. (On an older Ollama that uses
the Hub's Go template, that header is already in the prompt and is not repeated
— the loop below handles both.) Strip the whole prefix:
for prefix in (" to=user<|message|>", " to=user"):
if text.startswith(prefix):
text = text[len(prefix):]
break
Stop tokens: why the Modelfile lists them explicitly
Loading the GGUF prints:
load: special_eot_id is not in special_eog_ids - the tokenizer config may be incorrect
This is cosmetic. llama.cpp inserts <|eot|> (200008) into the
end-of-generation set and warns that the tokenizer config did not list it
(src/llama-vocab.cpp), so generation does stop on <|eot|> by itself — the
completions above ended with stop_type: eos, not on a stop string. The
Modelfile's explicit stop "<|eot|>" / stop "<|end_of_text|>" lines are
belt-and-braces for runtimes that don't apply that recovery.
Quantization fidelity
The same prompt (Example 2 below, greedy, temperature 0 / top_k 1) was run
twice: once against the bf16 safetensors in this repo via transformers, and
once against the Q4_K_M GGUF via llama-server's /completion. Both were
given the byte-identical 310-token prompt.
- Both produced valid, complete Triton that keeps the public class name and
forwardsignature. - They are not token-identical: bf16 emitted 457 new tokens,
Q4_K_Memitted 469, and the generatedcall()differs in how it obtains the CUDA device index — bf16 hard-coded device0(with torch.cuda._DeviceGuard(0),get_raw_stream(0)), whileQ4_K_Mderived it from the input tensor (with torch.cuda._DeviceGuard(arg0_1.device.index),get_raw_stream(arg0_1.device.index)). Both run; theQ4_K_Mversion is arguably the more portable of the two, but that is luck, not a property you can rely on.
One example is one example. The honest summary is that Q4_K_M on this model
stays on-task and on-format, and changes token-level details. Combined with the
fact that this model's task accuracy was never measured at any precision
(see Evaluation), the operative advice stands: if a generated
kernel matters, run it and check it.
Input / output examples
Example 1 — In-place ReLU (elementwise)
Validation row 343; 304 prompt tokens, 465 generated tokens.
Input (user turn, after the system prompt above):
You are given a PyTorch module together with the functions that produce its constructor arguments and its input tensors. Write a complete, self-contained Triton implementation that computes the same result.
Requirements:
- Emit one or more `@triton.jit` kernels plus the Python host code that launches them.
- Derive every compile-time constant (element counts, strides, block sizes) from the shapes implied by `get_inputs()` and `get_init_inputs()`.
- Keep the public class name and `forward` signature callable exactly as the reference is.
- Output only Python source. No explanation, no markdown fences.
```
import torch
import torch.nn.functional as F
from torch import nn
class relu(nn.Module):
def forward(self, x):
return F.relu(x, inplace=True)
def get_inputs():
return [torch.rand([4, 4, 4, 4])]
def get_init_inputs():
return [[], {}]
```
Output (verbatim, with the to=user header stripped):
import torch
import triton
import triton.language as tl
from torch._inductor.runtime.triton_heuristics import grid
from torch._C import _cuda_getCurrentRawStream as get_raw_stream
from torch._inductor.runtime import triton_helpers
from torch import nn
assert_size_stride = torch._C._dynamo.guards.assert_size_stride
empty_strided_cuda = torch._C._dynamo.guards._empty_strided_cuda
@triton.jit
def triton_poi_fused_relu_0(in_ptr0, out_ptr0, xnumel, XBLOCK: tl.constexpr):
xnumel = 256
xoffset = tl.program_id(0) * XBLOCK
xindex = xoffset + tl.arange(0, XBLOCK)[:]
xmask = xindex < xnumel
x0 = xindex
tmp0 = tl.load(in_ptr0 + x0, xmask)
tmp1 = tl.full([1], 0, tl.int32)
tmp2 = triton_helpers.maximum(tmp1, tmp0)
tl.store(out_ptr0 + x0, tmp2, xmask)
def call(args):
arg0_1, = args
args.clear()
assert_size_stride(arg0_1, (4, 4, 4, 4), (64, 16, 4, 1))
with torch.cuda._DeviceGuard(0):
torch.cuda.set_device(0)
buf0 = empty_strided_cuda((4, 4, 4, 4), (64, 16, 4, 1), torch.float32)
get_raw_stream(0)
triton_poi_fused_relu_0[grid(256)](arg0_1, buf0, 256, XBLOCK=256,
num_warps=4, num_stages=1)
del arg0_1
return buf0,
class reluNew(nn.Module):
def forward(self, input_0):
arg0_1 = input_0
output = call([arg0_1])
return output[0]
Correct elementwise ReLU, but not an exact match to the reference: the reference honours inplace=True by writing back into the input buffer, while the model allocates a fresh output buffer. The returned values agree; the aliasing semantics do not.
Example 2 — Scalar multiply via rmul
Validation row 81; 310 prompt tokens, 457 generated tokens.
Input (user turn, after the system prompt above):
You are given a PyTorch module together with the functions that produce its constructor arguments and its input tensors. Write a complete, self-contained Triton implementation that computes the same result.
Requirements:
- Emit one or more `@triton.jit` kernels plus the Python host code that launches them.
- Derive every compile-time constant (element counts, strides, block sizes) from the shapes implied by `get_inputs()` and `get_init_inputs()`.
- Keep the public class name and `forward` signature callable exactly as the reference is.
- Output only Python source. No explanation, no markdown fences.
```
import torch
class RMulInt(torch.nn.Module):
def __init__(self):
super(RMulInt, self).__init__()
def forward(self, x):
return 10 * x
def get_inputs():
return [torch.rand([4, 4, 4, 4])]
def get_init_inputs():
return [[], {}]
```
Output (verbatim, with the to=user header stripped):
import torch
import triton
import triton.language as tl
from torch._inductor.runtime.triton_heuristics import grid
from torch._C import _cuda_getCurrentRawStream as get_raw_stream
assert_size_stride = torch._C._dynamo.guards.assert_size_stride
empty_strided_cuda = torch._C._dynamo.guards._empty_strided_cuda
@triton.jit
def triton_poi_fused_mul_0(in_ptr0, out_ptr0, xnumel, XBLOCK: tl.constexpr):
xnumel = 256
xoffset = tl.program_id(0) * XBLOCK
xindex = xoffset + tl.arange(0, XBLOCK)[:]
xmask = xindex < xnumel
x0 = xindex
tmp0 = tl.load(in_ptr0 + x0, xmask)
tmp1 = 10.0
tmp2 = tmp0 * tmp1
tl.store(out_ptr0 + x0, tmp2, xmask)
def call(args):
arg0_1, = args
args.clear()
assert_size_stride(arg0_1, (4, 4, 4, 4), (64, 16, 4, 1))
with torch.cuda._DeviceGuard(0):
torch.cuda.set_device(0)
buf0 = empty_strided_cuda((4, 4, 4, 4), (64, 16, 4, 1), torch.float32)
get_raw_stream(0)
triton_poi_fused_mul_0[grid(256)](arg0_1, buf0, 256, XBLOCK=256,
num_warps=4, num_stages=1)
del arg0_1
return buf0,
class RMulIntNew(torch.nn.Module):
def __init__(self):
super(RMulIntNew, self).__init__()
def forward(self, input_0):
arg0_1 = input_0
output = call([arg0_1])
return output[0]
Byte-for-byte identical to the reference implementation.
Example 3 — Fused add + acos (libdevice)
Validation row 124; 328 prompt tokens, 494 generated tokens.
Input (user turn, after the system prompt above):
You are given a PyTorch module together with the functions that produce its constructor arguments and its input tensors. Write a complete, self-contained Triton implementation that computes the same result.
Requirements:
- Emit one or more `@triton.jit` kernels plus the Python host code that launches them.
- Derive every compile-time constant (element counts, strides, block sizes) from the shapes implied by `get_inputs()` and `get_init_inputs()`.
- Keep the public class name and `forward` signature callable exactly as the reference is.
- Output only Python source. No explanation, no markdown fences.
```
import torch
import torch.jit
import torch.onnx
import torch.nn
class SimpleACosModule(torch.nn.Module):
def __init__(self):
super(SimpleACosModule, self).__init__()
def forward(self, a):
return torch.acos(a + a)
def get_inputs():
return [torch.rand([4, 4, 4, 4])]
def get_init_inputs():
return [[], {}]
```
Output (verbatim, with the to=user header stripped):
import torch
import triton
import triton.language as tl
from torch._inductor.runtime.triton_heuristics import grid
from torch._C import _cuda_getCurrentRawStream as get_raw_stream
from torch._inductor.runtime.triton_helpers import libdevice
import torch.jit
import torch.onnx
import torch.nn
assert_size_stride = torch._C._dynamo.guards.assert_size_stride
empty_strided_cuda = torch._C._dynamo.guards._empty_strided_cuda
@triton.jit
def triton_poi_fused_add_acos_0(in_ptr0, out_ptr0, xnumel, XBLOCK: tl.constexpr
):
xnumel = 256
xoffset = tl.program_id(0) * XBLOCK
xindex = xoffset + tl.arange(0, XBLOCK)[:]
xmask = xindex < xnumel
x0 = xindex
tmp0 = tl.load(in_ptr0 + x0, xmask)
tmp1 = tmp0 + tmp0
tmp2 = libdevice.acos(tmp1)
tl.store(out_ptr0 + x0, tmp2, xmask)
def call(args):
arg0_1, = args
args.clear()
assert_size_stride(arg0_1, (4, 4, 4, 4), (64, 16, 4, 1))
with torch.cuda._DeviceGuard(0):
torch.cuda.set_device(0)
buf0 = empty_strided_cuda((4, 4, 4, 4), (64, 16, 4, 1), torch.float32)
get_raw_stream(0)
triton_poi_fused_add_acos_0[grid(256)](arg0_1, buf0, 256, XBLOCK=256,
num_warps=4, num_stages=1)
del arg0_1
return buf0,
class SimpleACosModuleNew(torch.nn.Module):
def __init__(self):
super(SimpleACosModuleNew, self).__init__()
def forward(self, input_0):
arg0_1 = input_0
output = call([arg0_1])
return output[0]
Semantically identical to the reference. The only differences are the kernel name's op ordering (triton_poi_fused_add_acos_0 vs the reference's triton_poi_fused_acos_add_0) and line wrapping.
What these examples do and do not show
All three produce plausible, well-formed torch._inductor-style Triton code with
the right kernel structure, and two of three are semantically equivalent to the
reference (one byte-identical). None was compiled or executed — no correctness
claim is being made here. The ReLU case shows the failure mode to watch for:
output that looks right and is subtly wrong about aliasing.
Decoding cost on CPU was 1.3 tokens/second for reference (2.6 minutes per
example above). That is a CPU number on a contended box, not a GPU benchmark.
Training details
Data. 8,949 training / 367 validation samples, assembled locally.
| Source | Rows | Handling |
|---|---|---|
GPUMODE/KernelBook |
6,971 | Permissively licensed rows only; de-duplicated; 462 rows overlapping KernelBench dropped |
GPUMODE/kernelbot-data (pmpp_v2_submissions) |
1,978 | Every submission re-run on an H200 under triton 3.1.0 / torch 2.5.1+cu121; kept only if it ran correctly and landed at or under the p75 wall-clock for its task |
8,011 further rows were dropped outright: the histogram_v2, sort_v2, and
conv2d_v2 task families are sealed out of training entirely because they are
the held-out speedup benchmark. Training on the benchmark you report against is
not a measurement.
Token lengths under the Muse-Glimmer tokenizer:
| Split | Median | p95 | p99 | Max | Fits 8,192 |
|---|---|---|---|---|---|
| Train | 1,780 | 4,982 | 7,724 | 9,813 | 99.3% |
| Validation | 1,933 | — | 8,206 | — | 98.9% |
Method
QLoRA: 4-bit NF4 quantized base, bf16 LoRA adapters, bf16 compute. TRL SFTTrainer,
loss over the full rendered sequence. 8 x H200, torchrun --nproc_per_node 8.
Final hyperparameters
| Knob | Value |
|---|---|
training_method |
qlora |
lora_r |
16 |
lora_alpha |
32 |
lora_dropout |
0.05 |
learning_rate |
2e-4 |
lr_scheduler |
cosine |
epochs |
2 |
batch_size (per device) |
1 |
grad_accum |
4 |
| effective batch | 32 (1 x 4 x 8 GPUs) |
warmup_ratio |
0.05 |
weight_decay |
0.01 |
max_seq_len |
8,192 |
use_dora / use_rslora |
false / false |
lora_init |
default |
loraplus_lr_ratio |
1.0 (off) |
neftune_noise_alpha |
0.0 (off) |
use_liger_kernel / use_sample_packing |
false / false |
Trials
training_method |
eval_loss |
Decision | Train runtime |
|---|---|---|---|
qlora |
0.078885 | keep — published | 5,970 s |
This is the published configuration, measured once. There was a single seed and no repeat run, so treat the loss as one measurement rather than a converged estimate of the method.
Observed training metrics
train_loss |
0.10914156969104494 |
eval_loss |
0.07888498902320862 |
train_runtime |
5,860.06 s (~1 h 37 m) |
train_samples_per_second |
3.054 |
train_steps_per_second |
0.096 |
total_flos |
6.980857555916423e+18 |
Evaluation
eval_loss = 0.078885 on the 367-row held-out validation split.
Environmental impact
Reported rather than estimated, since the hardware is shared and per-job power was not instrumented:
| Hardware | 8 x NVIDIA H200 |
| Training runtime (published trial) | 5,860 s (~1.63 h) |
| Total across all 3 trials | 19,105 s (~5.3 h) |
total_flos (published trial) |
6.98e+18 |
Carbon emitted was not measured; the grid region and PUE of the host are not known to the authors.
Framework versions
| PEFT | 0.18.1 |
| TRL | 1.0.0 |
| Transformers | 5.16.0.dev0 (git main) |
| PyTorch | 2.5.1+cu121 |
| Datasets | 4.8.4 |
| Tokenizers | 0.23.1 |
muse_glimmer is not in any stable transformers release as of 2026-09-14.
A git-main install is required to load this model.
Citation
Cite this model, the base model, and the training stack:
@misc{muse_glimmer_30b_kernelgen_2026,
title = {muse-glimmer-30b-kernelgen},
author = {{SASVA AI Model Cognition Labs (MCL) Team}},
year = {2026},
url = {https://huggingface.co/SASVAAI/muse-glimmer-30b-kernelgen}
}
@misc{muse-glimmer-30b,
title = {Muse-Glimmer-30B},
author = {Meta Superintelligence Lab},
year = {2026},
url = {https://huggingface.co/meta-models/Muse-Glimmer-30B}
}
@misc{trl,
title = {TRL: Transformer Reinforcement Learning},
author = {von Werra, Leandro and others},
year = {2020},
url = {https://github.com/huggingface/trl}
}
- Downloads last month
- 701