MoE for OpenTelemetry trace analysis and agent-coding observability.
390.1M total / 191.9M active per token (16 experts, top-2), vocab 151,936.
Counted from the weights, not derived from config:
component
params
experts (all 16 x 12 layers)
226.5M
embeddings + LM head
155.6M
attention
7.9M
norms / router gates
0.1M
total
390.1M
active per token (embed + attn + 2 of 16 experts)
191.9M
active excluding embed/head
36.3M
The last row is the one that sets expectations: embeddings are 40% of the model and
81% of the "active" count, but they are a lookup. Only ~36M parameters actually
compute per token.
SFT'd from …-sft-s3.1
on TraceVerse observability corpora. Emits structured tool-call JSON against
<trace> payloads.
Results
value
eval_loss
1.365
eval token accuracy
0.750
train_loss
1.44
train_loss > eval_loss, i.e. no overfitting. Nine consecutive eval improvements;
the early-stopping gate (patience 3 on eval_loss) never fired.
Scored on the goldens
LLM-as-judge (gpt-oss-120b, rubric-anchored, untruncated, with the session trace in
context), on the 142-row held-out agent-coding golden. contract% is a deterministic
task-aware check of the output contract -- no model involved.
Acc
Comp
Fmt
Gnd
Overall
contract%
think%
…-sft-s3.1 (base)
1.01
1.01
1.00
1.00
1.01
0%
0%
this model @ 1.4 ep
2.20
2.60
5.07
2.27
2.78
88%
92%
this model (2.4 ep)
2.25
2.69
5.34
2.39
2.87
88%
96%
General-purpose golden (218 rows): 1.71. The drop is the specialisation showing --
Format falls 5.34 → 2.43 off-domain.
Read the shape of this, not just the number. Format 5.34 against Accuracy 2.25 says
the model learned the output contract almost completely and the substance far less.
Contract adherence went 0% → 88% from SFT. For comparison on the same golden,
gpt-oss-120b scores near the top on judge overall with 0% contract adherence -- it
writes good prose that ignores the required output shape entirely. If you are consuming
structured output, that difference matters more than the overall gap suggests.
Usage — transformers
python
1import torch
2from transformers import AutoModelForCausalLM, AutoTokenizer
34REPO ="kshitijthakkar/loggenix-moe-0.4B-0.2A-sft-s4"5tok = AutoTokenizer.from_pretrained(REPO, trust_remote_code=True)6model = AutoModelForCausalLM.from_pretrained(7 REPO, dtype=torch.bfloat16, trust_remote_code=True8).eval().cuda()910messages =[11{"role":"system","content":"You are a TraceVerse observability analyst."},12{"role":"user","content":(13"Which MCP tools should be called to diagnose this? Respond with a JSON array.\n\n"14'<trace>[{"service":"checkout-api","child":"payment-svc",'15'"http.status_code":503,"duration_ms":4200}]</trace>'16)},17]1819enc = tok.apply_chat_template(20 messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"21)22# apply_chat_template returns a BatchEncoding, not a tensor -- index input_ids.23ids =(enc["input_ids"]ifhasattr(enc,"keys")else enc).to(model.device)2425out = model.generate(26 ids,27 max_new_tokens=1500,# NOT 128. This model reasons before answering;28# a low budget truncates it mid-thought.29 do_sample=True,# NOT greedy -- greedy decoding sends this model30 temperature=0.7,# into repetition loops. Measured, not theoretical.31 top_p=0.95,32 top_k=20,33)34print(tok.decode(out[0][ids.shape[-1]:], skip_special_tokens=True))
Two settings that matter more than usual
Do not use greedy decoding. With do_sample=False this model degenerates into
repetition loops. With temperature=0.7 / top_p=0.95 / top_k=20 it produces clean
structured output. This is a measured difference on identical prompts, and it
matches vendor guidance for the Qwen3 family generally.
Give it enough tokens. 400 was not enough to finish a response in testing;
1,500 is a safe floor. Truncation mid-reasoning looks like incoherence but is not.
Prompt shape
Trained on <trace>-grounded prompts with a system role. Bare questions with no
trace payload are out of distribution and degrade noticeably.
Usage — GGUF / ollama
Three quantisations under gguf/:
file
size
measured
…-f16.gguf
786 MB
218 tok/s
…-Q8_0.gguf
421 MB
—
…-Q4_K_M.gguf
256 MB
344 tok/s
Q4_K_M is ~1.6x faster than f16 with no quality degradation observed on
structured-output prompts.
ollama create loggenix-s4 -f gguf/Modelfile.Q4_K_M
ollama run loggenix-s4
The bundled Modelfiles set num_ctx 8192 — matching the training context. Do not
drop this to 4096: trace payloads routinely exceed it and llama.cpp truncates the
prompt silently, so the model answers on a partial trace with no error raised.
norm_topk_prob
This checkpoint is trained with norm_topk_prob=true. llama.cpp's qwen3moe
graph hardcodes norm_w=true and ignores the GGUF expert_weights_norm key, so a
checkpoint trained with false converts to a GGUF that produces garbage on every
llama.cpp runtime. That setting is why these GGUFs are coherent.
Training
Base
loggenix-moe-0.4B-0.2A-sft-s3.1
Method
TRL SFTTrainer, full fine-tune (LoRA does not work for MoE)
Precision / attn
bf16 / FlashAttention-2
Sequence
8192, packing enabled
Batch
1 x grad-accum 8 = 65,536 tokens/step
LR
2e-4, cosine, warmup ratio 0.1
Hardware
1x RTX 5090 (24 GB)
Corpus
source
rows
share
TraceVerse-RL-SFT-AgentMix3
49,017
61.9%
TraceVerse-RL-SFT-Clean
18,303
23.1%
loggenix-stage4-sft-dataset (synthetic)
11,880
15.0%
total
79,200
2,000 held out for eval
100% observability domain, filtered to n_tokens <= 8192.
Limitations
Specialist. Trained on trace analysis and tool-calling; general capability is
not a target and will be weak.
Synthetic data is 15% of rows.
Accuracy and Grounding are the weak axes (2.25 / 2.39 against Format 5.34). It
reliably produces well-formed answers that are often not the right answer. Do not
deploy it as an autonomous analyst; it is suited to structured extraction and
first-pass triage where the shape is the hard part and a human or a stronger model
checks the content.
Off-domain use is not supported. The general-golden score (1.71, Format 2.43) is what
happens outside trace analysis.
Scores above come from an LLM judge and carry its noise. The contract% column does
not -- it is deterministic and is the number to trust for format claims.