Model reference · open weights
Moonfrost is an open-weight language model from whoashish115. AxForge deploys and operates it for you on dedicated EU-owned hardware — with the licence handled where one is required.
Available as managed deployment — configured and operated for you on dedicated EU hardware, quoted per deployment.
What it is
| Released by | whoashish115 |
|---|---|
| Type | Language models |
| Task | Text gen |
| Parameters (lead) | 777M |
| Context | 1k tokens |
| Runs with | transformers |
| Released | 2026-09-13 |
| Popularity | 1k downloads / month |
| Licence | Open weights |
About
Code · Site · Training runs
Moonfrost is a 777M-parameter Mixture-of-Experts language model written and trained from nothing: its own byte-level tokenizer, its own attention and routing code, its own training loop. No base model was adapted and no weights were borrowed. Pretraining took about ten GPU-hours on a rented H100 and read roughly six billion tokens of FineWeb-Edu.
This repository holds the base model: next-token prediction and nothing else. It has no chat template, no instruction tuning and no alignment, so it continues text rather than answering questions. Prompt it with the opening of a passage, not an instruction.
Two supervised fine-tunes start from these weights and differ from them only in the weights, sharing this architecture, tokenizer and parameter count: Instruct-v2, the one to use, and Instruct-v1, kept for comparison. For conversation, take v2.
| Property | Value |
|---|---|
| Parameters | 777,148,032 total, 161,036,224 active per token |
| Layers | 14, of which layer 0 is dense and 1-13 are Mixture-of-Experts |
| Hidden size / heads | 896 / 14 |
| Experts | 32 routed with top-3 routing, plus 1 shared expert |
| Attention | Multi-head Latent Attention, 320 KV latent + 32 decoupled rotary key |
| Context | 1,024 tokens |
| Vocabulary | 32,768, byte-level BPE trained from scratch on the same corpus |
| Training data | FineWeb-Edu sample/10BT, shards 0-7, ~6B tokens |
| Validation loss | 2.976, best at step 11,000 of phase 2 |
| Held-out perplexity | 51.64 on an unseen shard, loss 3.944 |
| Peak / min LR | 6e-4 / 6e-5, time-based cosine, continuous across both phases |
| Batch | micro-batch 24, accumulation 12, 294,912 tokens per step |
| Precision | bf16 autocast with fp32 master weights, gradients clipped at 1.0 |
| Throughput | 179,000 training tokens/sec on one H100 |
| Compute and cost | 1x H100, ~10 GPU-hours, part of a ~$55 total |
The architecture is not part of transformers, so the repository ships its own modelling
code and needs trust_remote_code=True.
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "whoashish115/Moonfrost-777M"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id, trust_remote_code=True, torch_dtype=torch.float32
).eval()
inputs = tokenizer("The water cycle begins when", return_tensors="pt")
output = model.generate(**inputs, max_new_tokens=64, do_sample=True,
temperature=0.8, top_p=0.9)
print(tokenizer.decode(output[0], skip_special_tokens=True))
Two ideas from DeepSeek-V2 do the work, and both trade stored parameters for cheap ones.
Multi-head Latent Attention replaces the usual per-head key and value cache with a single shared latent. Ordinary attention at fourteen heads and head dimension 64 caches 1,792 numbers for every token; this projects the input down to one 320-number latent, caches that, and reconstructs keys and values when it needs them. Position is the complication, because rotary embeddings rotate a key by where it sits and a rotated key cannot be rebuilt from an unrotated latent. So position travels separately, on a 32-number rotary key shared across all heads, and attention runs over the two concatenated. The cache holds 352 numbers per token instead of 1,792, roughly five times smaller. At inference the up-projection matrices fold into the query and output projections once, which is exact because both are linear, and after that the model never reconstructs keys and values at all.
DeepSeekMoE makes the feed-forward layers sparse. Every layer above layer 0 holds 32 routed experts and one shared expert; a router scores the token against all 32, the top 3 run, the shared one always runs, so a token passes through four of thirty-three. Layer 0 is a plain SwiGLU feed-forward because routing from the very first layer destabilised early training and one dense layer costs almost nothing. A load-balancing auxiliary loss at weight 0.01 keeps the router from collapsing onto a few favourites.
The implementation detail that mattered most was mechanical rather than mathematical. The
experts are stored as three stacked (32, hidden, ffn) tensors and dispatched by capacity
in the GShard style, so all 32 run as three batched matrix multiplies. The first version
looped over experts in Python, which forced a GPU synchronisation thirty-two times per
layer per step and ran at 6,056 tokens per second. Same mathematics, same results, but the
stacked version runs at 179,000.
Beyond those: RMSNorm with no bias terms anywhere, SwiGLU activations, RoPE at theta 10,000 computed in float32 and cast back because bfloat16 lost enough precision at long positions to matter, and tied input and output embeddings sharing one 32,768 x 896 matrix, which saves 29M parameters.
| Component | Parameters | Share |
|---|---|---|
| Routed experts (13 layers x 32) | 543M | 70% |
| Attention (14 layers) | 118M | 15% |
| Shared experts + dense layer | 84M | 11% |
| Embedding (tied) | 29M | 4% |
Seventy per cent of the model is experts that stay idle for any given token. That is the whole trade: the capacity of a 777M model at roughly the compute of a 161M one.
Pretraining ran in two phases on two separate machines, reading disjoint shards so no document was seen twice. Phase 1 took shards 0-2 over 276 minutes for about 2.9B tokens; phase 2 took shards 3-7 over 340 minutes for about 3.1B and ended at validation loss 2.976.
Splitting one annealing schedule across two machines works because the learning rate
From the published model card. Full card on the HuggingFace links in the sidebar.
Benchmarks
As published on the model card — the maker's own numbers, not measured by AxForge.
| Task | Dataset | Metric | Score |
|---|---|---|---|
| Multiple-choice science questions | ARC-Easy | accuracy (5-shot, 250 examples) | 44.400 |
| Multiple-choice science questions | ARC-Challenge | accuracy (5-shot, 250 examples) | 24.400 |
| Commonsense sentence completion | HellaSwag | accuracy (5-shot, 250 examples) | 37.200 |
| Pronoun coreference | WinoGrande | accuracy (5-shot, 250 examples) | 54 |
| Yes/no reading comprehension | BoolQ | accuracy (5-shot, 250 examples) | 58.800 |
| Multitask knowledge | MMLU | accuracy (5-shot, 250 examples) | 30.800 |
Using it via the API
Once AxForge deploys moonfrost for you, it answers on the OpenAI-compatible API — the same base URL and keys as every other model. (moonfrost below is illustrative; you get the exact model name on deployment.)
$ curl -sS https://api.axforge.ai/v1/chat/completions \
-H "Authorization: Bearer $AXFORGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"moonfrost","messages":[{"role":"user","content":"Hello"}]}'
Create an account — your API key is available in the console. 3M free tokens every 30 days with every new account.