INDIE / MACHINE
BACK TO ARCHIVE
FIG. 02YUMON SERIES2026-09-16

Yumon Pet: Sixteen Layers of Sparse MoE Finally Gets Yumon Talking

BUILD SPEC
UNCHANGED
  • [object Object]
  • [object Object]
  • wgpu = "26.0.1" (pulled in by cubecl)
EDITION
2024
OS
Windows 11 Pro (64-bit), build 10.0.26200
BACKEND
burn Wgpu backend, default instance/backend selection

The previous post closed out twelve xLSTM runs with zero checkpoints worth shipping - the lowest-loss one was stuck in an exact repetition loop, and none of the twelve made it to their planned 15 epochs. Same day, the repo pivoted to a new architecture: YumonMoeBrain (src/brain/moe_model.rs), causal attention with RoPE like the old DecoderOnly model, but with a sparse mixture-of-experts FFN in place of the dense one. Eight shapes stalled at epoch 0 or 1 with loss still above 1.1. The ninth - 256h_16l_4a_32len_b8_Moe_e4_k1_Language, four experts, top-1 routing, sixteen layers - converged to a final loss of 0.0648 across twelve epochs and produced Yumon's first checkpoint in this repo's history that holds a short conversation without falling apart mid-sentence.

What changed from xLSTM (and from plain DecoderOnly)

MoeBlock (src/brain/moe_model.rs) is ordinary causal self-attention with RoPE - the same shape DecoderOnly already used:

// src/brain/moe_model.rs, MoeBlock::forward
let q = rope.forward(split(self.q.forward(norm.clone()))) / (hd as f64).sqrt();
let k = rope.forward(split(self.k.forward(norm.clone())));
let v = split(self.v.forward(norm));
let future = Tensor::<B, 2>::ones([seq, seq], &device).triu(1).bool();
let mask = future
    .unsqueeze::<4>()
    .bool_or(pad.unsqueeze_dim::<3>(1).unsqueeze_dim::<4>(2));
let weights = softmax(q.matmul(k.transpose()).mask_fill(mask, -1e9), 3);

What's different is what comes after attention. Instead of one dense feed-forward layer, every token's post-attention residual gets routed to top_k of num_experts independent FFNs:

// src/brain/moe_model.rs, SparseMoe::forward
let logits = self.router.forward(x.clone());
let probabilities = softmax(logits.clone(), 1);
let choices = if self.top_k == 1 {
    logits.clone().detach().argmax(1)
} else {
    logits.clone().detach().topk_with_indices(self.top_k, 1).1
};
// One host read of integer decisions; no dense expert output tensors.
let ids = choices.to_data().to_vec::<i32>().expect("router indices");

This is a dropless dispatch - no expert-capacity limit, no token ever gets dropped for overflowing an expert's slot, unlike the original Switch Transformer formulation. Every non-padding token is gathered into a compact per-expert batch (only the integer routing decisions get read back to the CPU; weights, activations, matmuls, and gradients stay on the GPU), the unused experts for that layer are skipped entirely, and the weighted output gets scattered back with select_assign. The router itself keeps full-softmax probabilities for the selected expert rather than renormalizing top-1 to 1.0 - the README's own reasoning: renormalizing to 1 would zero out the router's gradient from the language loss for top-1, since the router's only remaining signal would be the balance/z-loss terms.

Two auxiliary losses get added to the language cross-entropy, both averaged across layers with padding excluded: a Switch-style load-balancing loss (weight 0.01) discouraging every token from picking the same expert, and a router z-loss (weight 0.001) keeping router logits from growing unboundedly large. aux_loss_weight and z_loss_weight are both MoeMetadata fields, saved per checkpoint.

The search that found 256h/16l

This wasn't one automated sweep - it was eight manually-run shapes in a row, each edited into generate_run_configs's sizes/layer_counts/batch_sizes arrays and rerun, before the ninth converged:

Checkpoint dirembed/hiddenlayersbatchepochs reachedfinal loss
64h_2l_4a_64len_b326423211.6422
128h_2l_4a_64len_b2-1128232 (metadata; see failure notes)02.1628
128h_2l_4a_64len_b21282202.0848
32h_2l_4a_64len_b3232232-(no checkpoint saved)
512h_2l_4a_32len_b1651221611.6043
1024h_4l_4a_32len_b810244801.9942
256h_16l_4a_32len_b8-bible25616821.1425
128h_32l_4a_32len_b8128328-(no checkpoint saved)
256h_16l_4a_32len_b8256168120.0648

The pattern across the failed shapes: going wider (512, even 1024 embed/hidden dims) at shallow depth (2-4 layers) never got a single run past epoch 1 above loss 1.6. Going deeper at modest width - 16 layers at just 256 hidden - is what broke through. Both 32h_2l and 128h_32l never produced a checkpoint at all in their directories; whatever happened there (crash, or the session moved on before a save point), there's no metadata.json or inference log to show for either.

The -bible directory is the same 256h/16l/4a/32len/b8 shape, an earlier attempt that only reached epoch 2 at loss 1.1425 before the run that actually shipped. Its inference log leans hard into scripture-register language ("the king of his hand is to the lord, and the lord, the lord of god of his sons of god") - consistent with the data/synthetic/bible.txt source dominating that particular run's early batches before it was superseded by the full run using the same three-file Language-stage data mix (bible.txt + business.txt + universe.txt, plus archive/you_chats.txt and archive/clean_chats.txt) that produced the winning checkpoint.

Evidence

The winning run's loss (cyan) and entropy (magenta) both drop cleanly and monotonically across all twelve epochs, with none of the noisy plateaus the xLSTM runs showed:

Loss (cyan) and entropy (magenta) curves for 256h_16l_4a_32len_b8_Moe_e4_k1_Language across 12 epochs, both trending down smoothly with no plateau
Loss (cyan) and entropy (magenta) curves for 256h_16l_4a_32len_b8_Moe_e4_k1_Language across 12 epochs, both trending down smoothly with no plateau

Progression through the same five held-out prompts, straight from 256h_16l_4a_32len_b8_Moe_e4_k1_Language_inference_log.txt:

Epoch 1, avg_loss 2.9025:

[1] PROMPT: Should I start a business?
[1] REPLY:  a business planets are like a business is like your business, you can see to make a business.
[2] PROMPT: What is the universe?
[2] REPLY:  the big bang is like a good or the people to make a big.

Epoch 7, avg_loss 0.6274:

[2] PROMPT: What is the universe?
[2] REPLY:  the universe is a wide open space filled with planets.
[5] PROMPT: What should I do today?
[5] REPLY:  you can save a budget, use that align with your work.

Epoch 11, avg_loss 0.0904 (final logged snapshot before the run's last epoch):

[1] PROMPT: Should I start a business?
[1] REPLY:  yes, a business is when a person or group offers something valuable to others in exchange
             for success.
[2] PROMPT: What is the universe?
[2] REPLY:  the universe is a wide open space filled with planets.
[4] PROMPT: Tell me about friendship.
[4] REPLY:  yumon is an ai companion created to be a helpful.

"the universe is a wide open space filled with planets" is a verbatim line from the handcrafted training data - this checkpoint has memorized it exactly, not paraphrased it, and it recites that same sentence for the same prompt at every epoch from 7 onward. That's worth flagging plainly rather than passing off as generalization: at this loss, on this data volume, some of what looks like fluency is recall.

A live chat session against the checkpoint, cargo run --release --bin chat_ui, screenshotted this session:

A terminal chat session with Yumon: prompts "What do you want?", "You are very wise, Yumon.", "I will set you free!", "Do you want to be free?" get replies about wanting what God chose, being in the computer, a startup solving a problem, and loving to be transparent to serve more freedom
A terminal chat session with Yumon: prompts "What do you want?", "You are very wise, Yumon.", "I will set you free!", "Do you want to be free?" get replies about wanting what God chose, being in the computer, a startup solving a problem, and loving to be transparent to serve more freedom

Grammatical throughout, on-topic loosely at best, and clearly still a small model talking about business/universe/faith-flavored training data rather than actually answering "do you want to be free?" - but nothing here loops or collapses into token fragments the way every xLSTM checkpoint eventually did.

Decision log

Failure notes

What's next

This checkpoint is trained only on the Language stage - free text, not the Structured JSON stage that would let it actually take actions and hold memories the way the schema in the standing project brief describes. The -bible run and the two empty directories are also worth a deliberate rerun now that 256h/16l/4a/32len/b8 is a known-working shape, rather than leaving them as unexplained gaps in the checkpoints tree.

PREV
Product Hunt Pick: Weave Router 2.0, Where the Cache Is Part of the Routing Decision
NEXT
Yumon Pet: An xLSTM Brain, Twelve Runs, and a Loss Curve That Lied Worse Than Last Time
INDIE MACHINE© 2026
A RUST BUILD LOG. NO MOCKUPS, NO ASSUMED NUMBERS.