__                    
 __ / /___ _ ___  __ __ ___
/ // // _ `// _ \/ // /(_-<
\___/ \_,_//_//_/\_,_//___/

Janus 4B: calibrated typed decisions in one forward pass.

Janus is an independent reconstruction of a "System 1" decision model, built from public descriptions of the interface. Give Janus 4B a state (a ticket, a log, a policy, a JSON record) and any number of choice, score and noul (yes/no) questions. In one forward pass, it returns a calibrated probability for every option of every question, with no text generation. It is a LoRA adapter (r16) plus a pointer decision head on Qwen/Qwen3.5-4B at revision 851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a. The state is encoded once however many questions ride on it, each question is answered independently, a choice can have up to 255 options, and one short question takes about 17 ms on an RTX 5090. For a smaller footprint, use Janus 0.8B.

Code, server and Docker image: github.com/IcarusAICo/janus.

Questions choice (1 to 255 options), score (2 to 10 ordered levels, with the expected level), noul (p(true))
Input Up to 16,384 tokens in the Docker image (--max-tokens sets it); trained on requests up to 8,192
Wire format The POST /v1/systemone request and response shape; output tokens are always 0
Memory bf16 on an RTX 3090: 9.0 GB peak with a 150-token state, 9.9 GB with 4k tokens; about 17 GB reserved with the server's start-up pre-capture

Results

All numbers are from 2026-09-23/24, with every system served by its own code: accuracy on one RTX 3090, latency on an RTX 3090 and an RTX 5090. Janus 4B is the v3-instruct checkpoint. Full tables and sources: release/RESULTS.md in the GitHub repository.

set metric Janus 0.8B Janus 4B JevK5 v0.2 Laya 0.3.11
JevBench public items, easy / standard / hard accuracy 1.000 / 0.778 / 0.613 1.000 / 0.972 / 0.712 1.000 / 0.972 / 0.730 0.958 / 0.694 / 0.333
JevBench public items, all 231 accuracy 0.745 0.853 0.861 0.576
JevBench public hard tier ECE 0.072 0.071 0.062 0.206
MASSIVE, 51 locales, official test split 20-way intent accuracy / ECE 0.635 / 0.059 0.767 / 0.039 refused (16-option limit) 0.272 / 0.173
XNLI, 15 languages, official test split accuracy / ECE 0.655 / 0.044 0.757 / 0.055 0.608 / 0.165 0.522 / 0.051

The JevBench rows are our runs of the 231 public items through JevBench's own runner. They are not an official JevBench score (the official v1.4 score also pools 308 sealed items), and they were never used to select a checkpoint, with one disclosed exception: at our request, a candidate trained further on new multi-step data was run on them before we settled on this checkpoint. It scored hard 0.703 and was not chosen; this checkpoint is the one our pre-set procedure kept. A v1.4 what-if with an assumed sealed accuracy of 0.31 for every system (not an official score), scored the way the board scores self-hosted rows (list-price cost, timing on an RTX 5090), puts Janus 4B at 55.3 and JevK5 at 55.7: slightly behind, within run-to-run noise.

Latency. Median / p90 ms per request, warm, one request at a time, on the final serving code (start-up pre-capture on). Every system was served by its own code on the same card. Laya truncates long states to its context (26-35% of long-state requests), which also shortens its latency there. On the smaller cards Janus's long-state p90 includes graph re-captures after a memory release.

request card Janus 0.8B Janus 4B JevK5 v0.2 Laya 0.3.11
1 short question (XNLI) RTX 5090 5.0 / 5.4 17.3 / 18.1 18.7 / 19.6 6.1 / 7.4
RTX 3090 10.7 / 11.2 47.0 / 47.5 40.9 / 41.4 6.3 / 8.9
public-dataset test (1-2 questions) RTX 5090 8.7 / 14.4 27.9 / 55.7 40.3 / 117.8 9.1 / 14.8
RTX 3090 16.9 / 32.6 69.7 / 149.4 82.0 / 322.1 14.5 / 31.4
1 question, long state (hard-tier v2) RTX 5090 7.9 / 44.4 27.0 / 161.6 32.6 / 247.0 9.1 / 13.9
RTX 3090 16.4 / 94.3 75.0 / 462.1 80.6 / 647.7 14.9 / 23.8
8 questions, one long state RTX 5090 34.3 / 88.5 107.0 / 271.4 251.8 / 1,964.4 26.0 / 56.4
RTX 3090 73.4 / 169.6 337.8 / 857.3 641.7 / 5,194.8 66.6 / 110.9

Not chosen: distillation. We also trained 4Bs on a distilled mix (targets blended 0.5 gold + 0.5 from our own Janus 35B-A3B, plus multilingual rows), and kept this gold-trained checkpoint twice.

  • Partial epoch. The first distilled 4B (38% of an epoch) was set aside before any of its neutral results had been read. It then scored:
    • JevBench public: 0.823 overall, hard 0.649, hard ECE 0.103.
    • MASSIVE-51: 0.815 / 0.020 (better than this checkpoint). XNLI-15: 0.767 / 0.027 (better than this checkpoint).
    • Hard-tier v2: 0.797 / 0.018. Judge v2: 0.740 / 0.092. Public-dataset test: 0.709 / 0.026.
  • Full epoch. Distillation was then tested at a full epoch, under a rule agreed beforehand: keep distillation only if it beats this checkpoint on judge v2 and hard-tier v2. It was better on dev (NLL 0.336 against 0.374, accuracy 0.854 against 0.840), tied on hard-tier v2 (0.827 against 0.828) and on public test (0.728 both), and was worse on judge v2 (0.860 against 0.870, NLL 0.449 against 0.417). So distillation was dropped for the 4B. That decision was made before any of the full-epoch model's MASSIVE-51, XNLI-15 or JevBench results existed.

Use

pip install "janus @ git+https://github.com/IcarusAICo/janus"
import janus

m = janus.load("cmxu/janus-4b", device="cuda")   # downloads this repo and the Qwen/Qwen3.5-4B backbone
response = m.predict(
    "Refunds need a receipt and a purchase within 30 days. The customer bought 12 days ago and has no receipt.",
    {"refund": {"type": "noul", "instructions": "Is a refund permitted under the policy?"},
     "route": {"type": "choice", "instructions": "Which team should handle this?",
               "criteria": {"billing": "Payments and refunds", "support": "Anything else"}}},
)
response["answers"]["refund"]["noul"]           # p(true)
response["answers"]["route"]["probabilities"]   # {"billing": ..., "support": ...}

m.predict_batch([request, ...]) scores many /v1/systemone bodies with shared forward passes. To serve over HTTP from a download of this repo:

python -m janus serve --checkpoint model.pt --calibration calibration.json --model-id janus-4b --device cuda

The repository's Dockerfile builds an offline container around a pinned revision of this repo.

Files

file contents
model.pt trainable tensors only (LoRA + decision head), sha256 95101dff8cadd8519496a6a880366351b14b9df3dac9cbc6068e901a664f41de (v3-instruct); the backbone is fetched from Qwen/Qwen3.5-4B at 851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a
calibration.json global, per-family and per-option-count temperatures, bound to model.pt by its sha256
janus_config.json model id and pinned base model

The global (fallback) temperature is 1.0239. A request whose group_id starts with family: gets that family's temperature. Calibrated families: adversarial, ambiguous, arena, badges, civil, delivery, evidence, helpsteer, judge_hard, long_policy, massive, multi_hop, ord, post, probability, quality, record_match, rel, retrieval, routing_hard, tabfact, temporal_numeric, tradeoff, trap, urgency, wikispeedia.

Training

Run: runs/phase4/production/qwen35_4b_prod_v3_instruct.

  • Data. 51,996 requests (data/production-v3):

    • synthetic decision families, some generated by code and some written by GPT-5.6 Luna and reviewed by GPT-5.6 Terra (hard-tier policies, multi-step lookups, dates and numbers, probability, trade-offs, answer judging);
    • public datasets converted to typed requests (the datasets above);
    • Wikispeedia next-click decisions, long-context and many-option rows.

    English only (MASSIVE en-US is its only MASSIVE data). Gold targets only, with no distillation. Rows are deduplicated by state and kept disjoint from evaluation states. The hard-tier generators reject any state sharing a 12-word sequence with a public JevBench item. The datasets and their licences are listed in the GitHub README.

  • Schedule. One full epoch: 1,625 steps of 32 requests, 50 warm-up steps, then cosine decay (backbone lr 2e-4, head lr 1e-3, weight decay 0.01). Cross-entropy plus an option-order consistency term (weight 0.1). RTX 5090, about 10.4 h.

  • Selection. Step 1,500 within the run, by the rule fixed before training: dev NLL plus the NLL on 300 held-out requests from unseen families. We then chose this run over the partial-epoch distilled 4B. On a shared dev split the two tied (NLL 0.3737 against 0.3720), and this run led on our three internal held-out splits (hard-tier v2 0.828 against 0.797, judge v2 0.870 against 0.740, public test 0.728 against 0.709). For this model those three splits are therefore selection numbers, not unbiased test results. The neutral comparisons are JevBench public, MASSIVE-51 and XNLI-15. JevBench did not enter the choice: this run's JevBench public numbers had been seen, but the distilled run had none yet, so no comparison was possible. The distilled run's MASSIVE-51 metrics existed but were unread when the choice was made, and its XNLI-15 had not run.

Multi-step top-up (not released). We then trained this checkpoint further on 848 new GPT-written multi-step lookup rows (data/hardtier-v3). The selection rule, fixed beforehand, kept step 0, i.e. this checkpoint unchanged. The final step was checked diagnostically and passed our held-out gate (hardtier-v3 multi_hop test 0.924 against 0.889). At our request its JevBench public score was then seen (hard 0.703, what-if 54.1) before we chose. It was not chosen, and none of that data is in this model.

Apart from that one look at the top-up candidate, JevBench items were never used for selection. The per-family temperatures were fitted after selection on 2,925 held-out calibration requests that share no state or group with training or selection data. The global (fallback) temperature, used for every request without a calibrated family, was then refit on the 1,028 hard-tier requests among them (1.1025 to 1.0239). That lowered hard-tier ECE (JevBench public hard 0.097 to 0.071, by exact re-tempering of the served probabilities) at a small cost on easier sets (public-dataset test 0.031 to 0.033; most on the multilingual sets, MASSIVE-51 0.028 to 0.039 and XNLI-15 0.045 to 0.055).

License and credits

Code and adapter weights: Apache-2.0. The base model Qwen3.5-4B is by the Qwen team (Apache-2.0). The training datasets keep their own licences.

"Jev", "System One" and TypeSafe are names of TypeSafe AI's products, used here only to describe interface compatibility.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for cmxu/janus-4b

Finetuned
Qwen/Qwen3.5-4B
Adapter
(652)
this model

Datasets used to train cmxu/janus-4b