Instructions to use FahrenheitResearch/Rankine-0.6B-v1-mlx-4bit with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use FahrenheitResearch/Rankine-0.6B-v1-mlx-4bit with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir Rankine-0.6B-v1-mlx-4bit FahrenheitResearch/Rankine-0.6B-v1-mlx-4bit
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
Rankine 0.6B v1
Fahrenheit Research. The typed decision engine. Zero means zero.
One state in, typed probabilistic decisions out. Rankine reads one piece of unstructured state and answers every typed question about it at once. Each answer is a probability distribution, not a single label. The domain knowledge arrives inside the input at inference time, so one model covers every workflow.
Facts
| Backbone | Qwen/Qwen3-0.6B, Apache-2.0 |
| Build | LoRA fine-tune, fused into the backbone, quantized to 4-bit MLX at group size 64 |
| Size | 331 MiB of repository files, of which 320 MiB is weights |
| Context | 40,960 tokens |
| Options per question | up to 255 single-token markers |
| Primitives | choice, score, noul |
A choice returns a distribution over named options. A score returns a
distribution over ordered rubric levels plus an expected score that may fall
between levels. A noul returns the probability that a proposition holds.
Results on typed-decisions, test split
400 cases, 2,000 decisions, P50 99 ms per case on Apple M5.
| model | n | accuracy | soft_accuracy | macro_f1 | kl | tv | brier | ece | score_mae | within_1 |
|---|---|---|---|---|---|---|---|---|---|---|
| Rankine v1, 4-bit (this model) | 2000 | 0.743 | 0.546 | 0.605 | 0.122 | 0.173 | 0.067 | 0.154 | 0.256 | 0.971 |
| Rankine v1, fp16 adapters (unshipped fp16) | 2000 | 0.764 | 0.567 | 0.647 | 0.102 | 0.153 | 0.056 | 0.159 | 0.229 | 0.974 |
The shipped 4-bit build scores 0.743 accuracy against a teacher self-agreement ceiling of 0.735 on this benchmark. Scoring near or above that ceiling means the remaining error is mostly disagreement with the teacher's own spread rather than misreading the state.
Per workflow, 4-bit
| workflow | n | accuracy | soft_accuracy | macro_f1 | kl | tv | brier | ece | score_mae | within_1 |
|---|---|---|---|---|---|---|---|---|---|---|
| agent_trace_observability | 500 | 0.738 | 0.500 | 0.634 | 0.094 | 0.159 | 0.055 | 0.204 | 0.204 | 1.000 |
| customer_service | 500 | 0.730 | 0.553 | 0.657 | 0.161 | 0.196 | 0.088 | 0.129 | 0.265 | 0.995 |
| invoice_processing | 500 | 0.800 | 0.621 | 0.613 | 0.137 | 0.182 | 0.070 | 0.144 | 0.305 | 0.935 |
| security_incidents | 500 | 0.704 | 0.511 | 0.439 | 0.095 | 0.156 | 0.056 | 0.140 | 0.251 | 0.955 |
Per primitive, 4-bit
| primitive | n | accuracy | soft_accuracy | macro_f1 | kl | tv | brier | ece | score_mae | within_1 |
|---|---|---|---|---|---|---|---|---|---|---|
| choice | 600 | 0.750 | 0.527 | 0.557 | 0.157 | 0.189 | 0.079 | 0.171 | - | - |
| noul | 600 | 0.830 | 0.651 | 0.784 | 0.075 | 0.137 | 0.052 | 0.156 | - | - |
| score | 800 | 0.672 | 0.482 | 0.560 | 0.131 | 0.188 | 0.069 | 0.141 | 0.256 | 0.971 |
Weakest cells, and the targets for the next iteration: score accuracy at
0.672 and security_incidents macro F1 at
0.439.
Comparison
Scored on the same test split. Every row is marked specialist, meaning fitted on these workflows, or zero-shot, meaning the model had never seen these schemas.
| Model | Kind | Accuracy | Brier | ECE |
|---|---|---|---|---|
| Rankine 0.6B v1, 4-bit (this model) | specialist | 0.743 | 0.067 | 0.154 |
| Rankine 0.6B v1, fp16 adapters (unshipped fp16) | specialist | 0.764 | 0.056 | 0.159 |
| Laya typed-decisions | specialist | 0.766 | 0.062 | 0.213 |
| meraGPT Decider 1 | zero-shot | 0.768 | 0.052 | reference, not published |
| TypeSafe Jev 1.13.0 | zero-shot | 0.727 | 0.148 | 0.144 |
| Teacher self-agreement | ceiling | 0.735 | not applicable | not applicable |
Teacher self-agreement on this benchmark is 0.735. Gold labels are the mean of three samples from a teacher endpoint, so a fresh teacher sample scored against gold built from the other two reaches 0.735. Read that as the point above which accuracy measures agreement with the teacher's idiosyncrasies rather than the task. Read KL and Brier alongside accuracy for that reason.
The Laya, meraGPT Decider 1 and Jev figures are the benchmark card reference values carried by this project's evaluation harness. They were not re-measured here.
Speed
All figures below are Apple M5, 200 runs per measurement, with compiled
graphs and packed sequences both enabled. Laya is measured on the same Apple M5
machine from aac6fef/laya-mlx rather than quoted from its own card. Laya wins the
single-question rows and the many-questions-per-state row.
| end to end, Apple M5 | Rankine, Apple M5 | Laya, Apple M5 |
|---|---|---|
| One question, P50 | 15.96 ms | 11.23 ms |
| One question, P95 | 16.27 ms | 11.57 ms |
| One question over a prepared state, P50 | 20.84 ms | not available |
| One question over a prepared state, P95 | 21.75 ms | not available |
| 50 questions on one state | 181.8 q/s | 384.6 q/s |
| 5-question typed case, packed, P50 | 47.23 ms | 62.42 ms |
| 5-question typed case, packed, P95 | 55.35 ms | 65.10 ms |
| 5-question typed case, batched over a prepared state, P50 | 46.90 ms | not available |
| 5-question typed case, sequential over a prepared state, P50 | 46.83 ms | not available |
Rankine keeps one KV cache for the state and runs each question as a short suffix over it, so a question asked over a prepared state costs 20.84 ms at P50 on Apple M5 regardless of how long the state is. Laya has no equivalent prepared-state path. Laya answers a single fresh question faster, at 11.23 ms P50 on Apple M5 against 15.96 ms, and sustains 384.6 q/s against 181.8 q/s when 50 questions run over one state on Apple M5. Rankine is ahead on the 5-question typed case, the shape this model is built for, at 47.23 ms P50 on Apple M5 against 62.42 ms.
Quickstart
Rankine uses its own prompt layout, not a chat transcript. The state is encoded
once as a prefix, each question is a short suffix ending in Answer:, and the
answer is read from the logits over the option marker tokens. Nothing is
generated. The rankine package builds those strings and does the readout.
The rankine package ships inside this repository, under rankine/. The
package named rankine on PyPI is an unrelated project and is not this one, so
do not install it from there.
pip install mlx-lm huggingface_hub
hf download FahrenheitResearch/Rankine-0.6B-v1-mlx-4bit --local-dir rankine-v1
cd rankine-v1
From that directory:
import rankine
agent = rankine.load(".") # the directory you just downloaded
state = {
"channel": "email",
"subject": "Charged twice for the October plan",
"body": "My card shows two charges of 49.00 on 3 October. Please refund one.",
"account_age_days": 412,
}
out = agent.predict(state, {
"department": {
"type": "choice",
"instructions": "Which team should handle this message?",
"criteria": {
"billing": "payments, refunds, invoices",
"technical": "bugs, outages, integration errors",
"sales": "pricing questions from prospects",
},
},
})
answer = out["answers"]["department"]
print(answer["label"], round(answer["probabilities"][answer["label"]], 3))
# billing 0.958
Several questions in one call share one encoding of the state:
out = agent.predict(state, {
"department": {"type": "choice", "instructions": "Which team should handle this message?",
"criteria": {"billing": "payments, refunds, invoices",
"technical": "bugs, outages, integration errors",
"sales": "pricing questions from prospects"}},
"urgent": {"type": "noul", "instructions": "This needs a reply today."},
"refund": {"type": "noul", "instructions": "The customer is asking for money back."},
"severity": {"type": "score", "instructions": "How severe is the issue for the customer?",
"criteria": ["Cosmetic", "Minor", "Major", "Blocking"]},
"churn_risk": {"type": "score", "instructions": "How likely is this customer to leave?",
"criteria": ["Very low", "Low", "Moderate", "High"]},
})
For a state that is reused across many questions, encode it once:
prepared = agent.prepare(state)
out = agent.predict(prepared, questions)
rankine.load also accepts the repository id,
rankine.load("FahrenheitResearch/Rankine-0.6B-v1-mlx-4bit"), which pulls the
weights into the Hugging Face cache instead of reading them from the current
directory.
The MLX backend is selected automatically on Apple silicon when mlx-lm is
installed. The PyTorch backend exposes the same interface elsewhere.
chat_template.jinja ships in this repository so that generic tooling can load
the tokenizer, and it is the stock Qwen3 template inherited from the backbone.
It is not used by the typed decision path and applying it would break the
marker readout.
Calibration
Training targets are soft: half the teacher distribution and half the gold label, so the loss is a soft-label cross-entropy rather than a hard-label one. A proper scoring rule is then read off the held-out split, so the reported Brier score and KL from gold measure the distribution and not only the argmax.
After training, one temperature is fitted per question bucket on held-out data
and stored in calibration.json. A bucket is the primitive plus its option
count, because a three-option choice and a nine-option choice are not sharpened
by the same amount. rankine.load reads the file and applies the temperature
before the softmax.
| bucket | temperature |
|---|---|
choice:3 |
0.980 |
choice:4 |
0.994 |
choice:5 |
1.035 |
choice:6 |
1.152 |
choice:9+ |
1.192 |
noul |
1.508 |
score:4 |
1.070 |
score:5 |
1.130 |
Choices with nine or more options share one 9+ bucket. A bucket with no
fitted entry falls back to the mean of the fitted temperatures for its own
primitive, and to 1.0 only when that primitive has none. A temperature above
1.0 softens the distribution, which is what a bucket that was overconfident
needs. Calibrated overall ECE on the test split is 0.154 and Brier is
0.067.
Calibration can be disabled per call with agent.predict(..., calibrate=False).
Limitations
- English only. Every training and evaluation row is English.
- Four workflows:
agent_trace_observability,customer_service,invoice_processingandsecurity_incidents. Behaviour on an unseen schema is not characterised by the numbers above. - Quantization costs 0.021 accuracy against the fp16 adapters, 0.764 down to 0.743. The fp16 build is not shipped.
- The zero-shot score is not yet measured. Every Rankine number on this card is a specialist number, fitted on these four workflows. It is not comparable like for like with the zero-shot rows for meraGPT Decider 1 and Jev.
- Accuracy is agreement with a teacher-derived gold label, not ground truth. The per-question ceiling varies widely across the benchmark.
- This is a typed decision engine, not a chat model. It does not generate text.
Citation
@misc{rankine-0.6b-v1,
title = {Rankine 0.6B v1: typed probabilistic decisions on device},
author = {Fahrenheit Research},
year = {2026},
url = {https://huggingface.co/FahrenheitResearch/Rankine-0.6B-v1-mlx-4bit}
}
Links
- Fahrenheit Research: f-r.co
- Benchmark: LocalLLaMA/typed-decisions
- Backbone: Qwen/Qwen3-0.6B
License
Apache-2.0, inherited from the Qwen3-0.6B backbone.
- Downloads last month
- 16
4-bit
Model tree for FahrenheitResearch/Rankine-0.6B-v1-mlx-4bit
Dataset used to train FahrenheitResearch/Rankine-0.6B-v1-mlx-4bit
Evaluation results
- Accuracy on Typed Decisionstest set self-reported0.743
- Soft accuracy on Typed Decisionstest set self-reported0.546
- Macro F1 on Typed Decisionstest set self-reported0.605
- KL from gold on Typed Decisionstest set self-reported0.122
- Brier score on Typed Decisionstest set self-reported0.067
- Expected calibration error on Typed Decisionstest set self-reported0.154
- Score MAE on Typed Decisionstest set self-reported0.256
- Within one level on Typed Decisionstest set self-reported0.971