- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| data | ||
| examples | ||
| primes | ||
| validation | ||
| .gitignore | ||
| CITATION.cff | ||
| config.json | ||
| head.safetensors | ||
| head_config.json | ||
| LICENSE | ||
| manifest.json | ||
| model.safetensors | ||
| README.md | ||
| tokenizer.json | ||
| tokenizer_config.json | ||
Primes 0.6b
A 0.6B base decision model. Give it a situation, an optional query, and a set of options; it returns a calibrated probability distribution over the options — one forward pass per option, softmax across them. No token generation, no sampling, no prompt tricks: the same inputs always produce the same distribution. Built as a base for finetuning on domain-specific decision problems.
This is the base model designed for fine-tuning.
state = "The warehouse door is locked. Security patrols every 20 minutes.
A side window is open two floors up. Your lockpick is bent."
query = "get inside without being seen" # optional
options= ["pick the lock", "climb to the window", "wait for the patrol", "leave"]
-> climb to the window (0.46) wait for the patrol (0.27)
pick the lock (0.21) leave (0.05)
Model description
- Architecture: Qwen3-0.6B backbone (
Qwen3Model, 28 layers, hidden 1024, tied embeddings; the language-model head is dropped) + a 0.5M-parameter decision head:Linear(1024, 512) → GELU(exact erf) → Linear(512, 1)over the mean-pooled final hidden state. Merged inference weights — no adapters to attach. - Training: fine-tuned from
Qwen/Qwen3-0.6Bon English decision problems (everyday scenarios, games, shopping, legal and data-science reasoning, structured HTML/JSON documents) with soft labels distilled from a larger Qwen3 teacher. - Intended use: a base model for finetuning on your own decision data; also usable zero-shot as a scorer/reranker for multiple-choice selection.
- Release: 1.0.0, 2026-10-11. Checksums in
manifest.json.
Metrics (public validation set, 423 decisions)
Reference run of validation/validate.py (bf16 backbone + fp32 head,
single consumer GPU; validation/results.json):
| metric | value |
|---|---|
| top-1 accuracy | 0.9456 |
| MRR | 0.9716 |
| NLL | 0.2388 |
| ECE (10 bins) | 0.0975 |
| random baseline | 0.2930 |
| split | n | top-1 |
|---|---|---|
| with query | 273 | 0.9560 |
| query-less | 150 | 0.9267 |
Per option-count (K=2..8): 0.946, 0.965, 0.918, 0.950, 0.886, 1.000, 0.929. The validation set excludes the numeric-reasoning lane (see Limitations), so these numbers describe the model's supported scope.
Quickstart (torch)
python examples/decide.py # three demo decisions
or in code:
import sys; sys.path.insert(0, ".")
from examples.decide import Primes
m = Primes() # cuda/bf16 if available, else cpu/fp32
out = m.decide(
"Two job offers: a stable team with legacy code, or a risky startup doing ML.",
["stable team", "risky startup"],
query="maximize career growth in two years")
print(out["choice"], out["confidence"]) # -> stable team 0.689
Deps: torch, transformers, safetensors, numpy. The decision
head always runs in fp32 (numpy) exactly as shipped, independent of
the backbone dtype/device.
Input & output contract
Every input text is serialize(query, option, context) — this must be
byte-identical in training and inference or the input distribution
shifts silently:
Query: {query} # missing/empty -> "select best"
Option: {option}
Context: {context} # whitespace runs collapsed to single spaces
Truncated at 704 tokens. The head consumes the mean-pooled final
hidden state over non-pad tokens (Qwen adds no BOS, so plain
tokenization matches). One decision = K forward passes (batched) +
softmax over the K logits. primes/runtime.py is the reference
implementation; vendor it rather than reimplementing.
Finetuning
The model is a standard Qwen3Model + a small separable head, so the
usual toolbox applies (PEFT/LoRA on the backbone, head retrained or
frozen):
-
Data format — one JSON record per decision, exactly as in
data/train_example.jsonl(16 samples from the training distribution):{"id": "train-ex-001", "query": null, "context": "...", "options": ["...", "..."], "gold": 0}querymay benull(serialized asselect best);goldis the 0-based index of the correct option. Train one example per (query, option, context) triple with a cross-entropy over the K logits of the decision. -
Keep
serialize()byte-identical and the 704-token cap. -
The head is 0.5M parameters — retraining it alongside the backbone is cheap; it also transfers as-is if only the domain shifts.
-
After finetuning,
validation/validate.pydoubles as a drift check against the published numbers (--no-gateto just measure).
Limitations
- Numeric multi-value reasoning is out of scope. Decisions that require argmax-style comparison over five or more numeric values were excluded from training (the 0.6B backbone cannot carry that objective without degrading the rest); the public validation set excludes the lane accordingly. Route such decisions to a dedicated numeric expert or plain code.
- English-centric training data; no generation of any kind; contexts beyond 704 tokens are truncated.
- Calibrated for single-choice decisions over small option sets (validated on K=2..8). Confidence is a probability of correctness among these options — re-score with a different option set and the distribution changes accordingly.
- Decisions with no single defensible answer (unanswerable or multi-select) are not represented in the public data.
Files
| file | size | what |
|---|---|---|
model.safetensors |
1.19 GB | merged backbone (bf16, Qwen3Model) |
head.safetensors + head_config.json |
2.1 MB | decision head (fp32) |
config.json, tokenizer.json, tokenizer_config.json |
11 MB | config + tokenizer |
primes/ |
reference runtime (serialize, Head, softmax) |
|
examples/decide.py |
torch scorer + demos | |
validation/ |
public val set (423), validate.py, reference results.json |
|
data/train_example.jsonl |
16-sample finetuning-format example | |
manifest.json |
sha256 checksums of everything above |
Validation
python validation/validate.py # ~3 min on one GPU
python validation/validate.py --device cpu # slower, same numbers
Prints top-1/MRR/NLL/ECE plus splits and per-K breakdown, writes
validation/results.json, and exits non-zero if top-1 or ECE drift
beyond tolerance of the published numbers — usable as an install
smoke test.
License
Apache-2.0. Derivative of Qwen/Qwen3-0.6B (Apache-2.0); see
LICENSE and manifest.json.
Citation
@misc{nesterov2026primes,
author = {Anton A. Nesterov},
title = {Primes: a 0.6B base decision model},
year = {2026},
url = {https://vski.sh},
note = {version 1.0.0}
}
Anton A. Nesterov — vski.sh