Instructions to use Guru0381/krino-2b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use Guru0381/krino-2b with PEFT:
from peft import PeftModel from transformers import AutoModel base_model = AutoModel.from_pretrained("Qwen/Qwen3.5-2B-Base") model = PeftModel.from_pretrained(base_model, "Guru0381/krino-2b") - Notebooks
- Google Colab
- Kaggle
Krino-2B
Krino (Greek κρίνω, to decide; the root of criterion) is a 2B-parameter System One decision model. You give it
a piece of text (the state) and one or more typed questions — noul (yes/no), choice (pick one option),
score (an ordered level) — and it returns a probability for every option of every question in one forward pass.
It never generates text, so there is nothing to parse and nothing to hallucinate; what you get is a distribution you can
threshold, route on, or log.
Krino is built on Kev (Apache-2.0): a rank-16 LoRA adapter and a pointer head on a
frozen Qwen/Qwen3.5-2B-Base, served with the TypeSafe System One wire format (POST /v1/systemone). It is the
2B-parameter member of that family, between Kev-0.8B and Kev-4B, trained on Kev's open data plus a commercially licensed
breadth mix, and served with one temperature per question type.
- Weights, code and training data: Apache-2.0 or more permissive. No research-only sources (XNLI, RACE and BeaverTails, which make other 2B decision models non-commercial, are deliberately out).
- Repository: github.com/guru0381/Krino — the recipe, every script, the
evaluation protocol (
docs/EVAL.md), every number (docs/RESULTS.md) and the decision log (PLAN.md). - Base:
Qwen/Qwen3.5-2B-Baseat revisionb1485b2fa6dfa1287294f269f5fb618e03d52d7c(1.9B parameters, Apache-2.0).
Serve
pip install "krino @ git+https://github.com/guru0381/Krino.git@v0.1.0"
krino-serve --run Guru0381/krino-2b@v0.1.0 --host 0.0.0.0 --port 8008
krino-serve is Kev's server (kev.serve: batching, prefix cache, CUDA graphs, bearer auth with KEV_API_KEY) with
one addition: the checkpoint is loaded raw and every answer is re-served at its question type's temperature
(krino.json in this repo; see Calibration). GET /v1/krino shows the map in use. It runs on any CUDA GPU with
about 8 GB free in bf16 (an L4 is enough), on Apple Silicon through Kev's MLX backend, and on CPU for testing.
KEV_TRUNCATE_STATES=1 truncates states over 65,536 tokens instead of refusing them with a 422.
curl -s http://127.0.0.1:8008/v1/systemone -H 'content-type: application/json' -d '{
"model": "kev-latest",
"state": "Shoes arrived two weeks late and in the wrong size. Also I see two charges on my card.",
"questions": {
"department": {"type": "choice", "instructions": "Which team should handle this?",
"criteria": {"returns": "Exchanges, refunds, wrong or damaged items",
"shipping": "Delivery status, delays, lost packages",
"billing": "Charges, invoices, payment problems"}},
"escalate": {"type": "noul", "instructions": "Does this need urgent human attention?"},
"frustration":{"type": "score", "instructions": "How frustrated is the customer?",
"criteria": ["Calm", "Frustrated", "Very angry"]}}}'
The response carries probabilities for every question ({"returns": 0.71, "shipping": 0.17, "billing": 0.12},
{"false": 0.3, "true": 0.7}, a probability per level), the argmax answers, and usage.input_tokens. The TypeSafe
Python client works unchanged (TypeSafeClient(base_url="http://127.0.0.1:8008", api_key="local")).
Results
Every number below is on a partition that never entered training, read at the raw temperature (T = 1) unless the column
says otherwise. Partitions, the decision rule and the disclosure log are in
docs/EVAL.md; the full tables with seeds and
intervals are in docs/RESULTS.md.
Locked test (read once, after the release candidate was chosen on development)
| suite | questions | accuracy | Brier | ECE |
|---|---|---|---|---|
| transfer-v4 test (six never-trained public sources + held-out policy structures) | 656 | 0.790 | 0.311 | 0.110 |
| decision-v7 test (Kev's trained sources) | 1,200 | 0.848 | 0.227 | 0.074 |
transfer-v4's test accuracy equals its development accuracy (0.790), so nothing was tuned to the development split. The nine breadth suites have no test partition (they are Malkuth's development-only suites); their numbers below are development reads, used to choose the checkpoint.
Development panel (chose the checkpoint; two seeds, the released seed shown)
| suite | what it measures | questions | accuracy | Brier | ECE |
|---|---|---|---|---|---|
| hard-v1 | Kev's seven hard families: long policies with exceptions, trade-offs, probability, multi-hop, dates and arithmetic, judging an answer, missing-fact abstention | 1,083 | 0.717 | 0.392 | 0.091 |
| documents-v1 | real US consumer-finance complaints (CFPB), product and issue, states to 7k tokens | 920 | 0.860 | 0.224 | 0.080 |
| devtools-v1 | developer tooling: code review, commit type, flaky tests, content safety, tool routing, prompt injection | 1,074 | 0.682 | 0.450 | 0.108 |
| transfer-v4 dev | never-trained public sources (MMLU, QNLI, PAWS, SciQ, emotion, tweet_offensive) + held-out policy structures | 656 | 0.790 | 0.312 | 0.090 |
| decision-v7 dev (guard) | Kev's trained sources | 1,264 | 0.842 | 0.236 | 0.088 |
| krino-breadth (nine suites) | datasets neither Kev nor the breadth mix trained on: Belebele, SIB-200, RTP-LX, PolyGuard, GoEmotions, LEDGAR, KOLD, Laya apps, MultiEURLEX | 7,657 | 0.655 (mean) |
Option-order permutation flip rate on transfer-v4: 2.8 % (13.9 % after stage 1 of the same recipe).
JevBench public items (report-only)
JevBench publishes 231 of its decisions (original 72, easy 48, hard 111)
and keeps 1,200 sealed. Krino never trained on the public items — every training set is screened against them
(screen_overlap.py, 0 offending records) — and never used them to choose a checkpoint; they were read twice for this
checkpoint, once at a global temperature and once with the per-type map, both logged in docs/EVAL.md.
| tier | correct | accuracy |
|---|---|---|
| original | 66 / 72 | 0.917 |
| easy | 48 / 48 | 1.000 |
| hard | 47 / 111 | 0.423 |
| all public | 161 / 231 | 0.697 |
For scale on the same harness and items: Malkuth-2B 159/231 (hard 45/111), Kev-0.8B 147/231 (hard 41/111). The sealed
score is the board's to measure; the request for a row is docs/jevbench-request.md in the repository.
Calibration: one temperature per question type
Krino's head is trained at T = 1 and served through a per-type map, krino.json:
| type | served T | why |
|---|---|---|
| choice | 1.95 | minimises top-label ECE on the nine never-trained breadth suites (five-fold, out-of-fold ECE 0.023); hard-v1 dev ECE 0.091 → 0.041 |
| noul | 0.30 | yes/no answers are read as decisions: a probability near 0.5 is an abstention, and a soft temperature puts half of them there. 0.3 keeps 90 % of answers decisive at the argmax accuracy |
| score | 0.50 | ordered levels are read by expected level; a soft distribution drags the expectation to the middle of the scale |
The argmax never changes with the temperature, so accuracy is identical under any map; what changes is how the
distribution should be read. If you want raw probabilities, run with KRINO_TEMPERATURES="choice=1,noul=1,score=1".
If you want a single global temperature as Kev serves, choice=1.95,noul=1.95,score=1.95. Hard, out-of-distribution
inputs are over-confident at every setting: on the JevBench hard tier the per-type map gives Brier 0.844 / ECE 0.321
against 0.706 / 0.236 for the global 1.95 — the price of decisive yes/no answers.
Training
Two stages, both with Kev's trainer (kev.train) on one H100 through Kev's Modal runner, LoRA rank 16 (α 32, dropout
0.05, all linear projections), pointer head from scratch, bf16, gradient checkpointing, cross-entropy over each
question's options, option order shuffled, "none of the above" options and distractors inserted at random, a quarter
of choice records paired with their none-of-the-above minimal pair (p_none_pair 0.25).
- Stage 1 — Kev's base recipe. Two epochs on
decision-v7(12,576 records: ten public classification datasets with native labels, generated policy minimal pairs, generated rule structures), learning rate 7e-5, batch 4 × 2 accumulation. Two seeds; the seed with the better transfer-v4 development accuracy was carried forward. - Stage 2 — one combined delta. One epoch from stage 1 at learning rate 2e-5, batch 2 × 4, states to 7,552 tokens,
on mix v1 (79,484 records) plus 6,000 records replayed from
decision-v7: the breadth half is Malkuth's commercially licensed sources — MASSIVE intent and scenario (Apache-2.0), PAWS-X without English (free for any use), CLINC150 (CC BY 3.0), KLUE (CC BY-SA 4.0), NSMC (CC0), KoBEST (CC BY-SA 4.0), typed-decisions (Apache-2.0), ARC (CC BY-SA 4.0), multilingual toxicity (OpenRAIL++), jailbreak classification (Apache-2.0), Civil Comments (CC0), APEACH (CC BY-SA 4.0), XQuAD without English (CC BY-SA 4.0), Aegis 2.0 (CC BY 4.0); the depth half is Kev's own training partitions —hard-v1(generated, twice),documents-v1(CFPB narratives, public domain) anddevtools-v1(permissive per-source licences in its manifest). Two seeds; both passed every clause of the decision rule; the released seed was chosen by transfer-v4 development.
Out, by measurement rather than by taste: a KL anchor to the frozen base (null in Kev's and strands-decider's logs), a
second stacked delta of answer-adequacy and multi-step-document rows (docs/RESULTS.md, Run 1: +15 to +39 points on
its own held-out formats and nothing on the hard families, so it was not released), and Malkuth's weights as a warm
start (research-only licence). No output of Jev (TypeSafe's hosted model) was used anywhere.
Limitations
- A 2B torso has a ceiling on reading. Dates and arithmetic (hard-v1 temporal_numeric 0.56) and probability (0.60) are where it is weakest, then trade-offs (0.69); long policies, multi-hop and judging sit at 0.73–0.80.
- Over-confident out of distribution. The temperatures are fitted on development rows; on harder, unfamiliar
inputs the confidence runs ahead of the accuracy (JevBench hard tier: 42 % accurate at ECE 0.32 with the per-type
map). Treat the probabilities as rankings there, or re-fit
krino.jsonon your own held-out data. - Abstention is a label, not a behaviour. The model picks the best option it is given; it will not refuse. Put an
explicit "insufficient information" option in
criteriaif that is a valid answer. - Context. States are encoded up to 65,536 tokens; with
KEV_TRUNCATE_STATES=1longer ones are cut, otherwise refused. - English-centred with multilingual breadth. Korean, the six PAWS-X languages and the XQuAD languages appear in the mix; everything else is zero-shot from the base.
- A decision model answers the question it is asked, on the state it is given. It has no access to anything else.
Reproduce
The repository pins every input: Kev at fe64b1274ea7f80d4095866df90666abb03e9cf6, the base revision above, the
suite checksums in third_party/kev/evals/*/manifest.json, the mix builder (tools/build_mix.py) with its screen, the
study plans (experiments/stage1-2b.json, experiments/stage2-2b-s1.json) and the serving map (tools/typed_competence.py --write). provenance.json and training_config.json beside the weights carry the trial's hashes.
Citation
@misc{krino2b,
title = {Krino-2B: a 2B System One decision model with per-type serving temperatures},
author = {Gurunath Reddy},
year = {2026},
url = {https://huggingface.co/Guru0381/krino-2b}
}
Built on Kev by Jared Palmer (Apache-2.0) and on Malkuth's breadth recipe by newfull5 (Apache-2.0 code); evaluated with JevBench by Benchmark Heaven. Thanks to all three.
- Downloads last month
- 12
Model tree for Guru0381/krino-2b
Base model
Qwen/Qwen3.5-2B-BaseDatasets used to train Guru0381/krino-2b
stanfordnlp/imdb
fancyzhx/ag_news
Evaluation results
- accuracy on transfer-v4 test: six never-trained public sources and held-out policy structuresself-reported0.790
- brier_score on transfer-v4 test: six never-trained public sources and held-out policy structuresself-reported0.311
- expected_calibration_error on transfer-v4 test: six never-trained public sources and held-out policy structuresself-reported0.110
- accuracy on decision-v7 testself-reported0.848
- brier_score on decision-v7 testself-reported0.227