basal-omni-pico
basal-omni-pico is our smallest typed-decision model for Polish and English. It has 0.8B parameters, it is built on Qwen3.5-0.8B-Base (the larger basal-omni models are built on Gemma 4), it reads text only, and it was trained with our basal-omni-1.0-ultra (31B) as the teacher. It reads the same requests as the larger basal models.
What it is. The model reads a state (a message, a document, a sensor log, retrieved passages) and answers a typed
question about it (choice, yes/no noul, score, multi, act, tool) by returning a probability for each
allowed answer, in one forward pass, without generating text. The answer never falls outside the options you give.
| model | params | base |
|---|---|---|
| basal-omni-pico | 0.8B | Qwen3.5-0.8B-Base, text only; also as GGUF for llama.cpp (basal-omni-pico-GGUF) |
| basal-omni-1.0-mini | E4B | Gemma 4 E4B |
| basal-omni-1.1-max | 12B | Gemma 4 12B |
| basal-omni-1.0-ultra | 31B | Gemma 4 31B |
Intended use
- Good for: routing a request to the right queue, team or tool, and picking the relevant passage (Werdykt: routing 0.912, retrieval 0.886, real documents 0.848); Polish decisions (our Polish check set: 0.876).
- Languages: Polish and English.
- Not for: writing text or chatting; facts that are not in the state; rule checks (Werdykt rules 0.316); using the probabilities as error rates on a new kind of data before you check them there (see Calibration); decisions with serious consequences for people without human review. For harder cases use a larger basal model.
Quick start
1. Install basal 2.5.0 into a fresh uv environment (CPU wheels shown; for an NVIDIA GPU
use the cu128 index and add "flash-linear-attention==0.5.2", on a Mac the default index):
uv venv --python 3.12 --allow-existing ~/basal-env && source ~/basal-env/bin/activate
uv pip install torch==2.11.0 --index-url https://download.pytorch.org/whl/cpu
uv pip install "basal @ https://github.com/rkinas/basal/archive/refs/tags/v2.5.3.tar.gz"
2. Start the server. It prints basal: model ... ready:
basal-serve --model Remek/basal-omni-pico --port 8000
Without --mode, basal serves this model in its fast CUDA-graph engine (fast) on Hopper GPUs (H100) when
flash-linear-attention is installed, and in eager elsewhere. basal 2.4 or later is needed for --mode fast; 2.3.2 or
later serves it in eager and gguf. fp8 and nvfp4 refuse this model.
3. Ask questions, as with every basal model:
curl -s localhost:8000/v1/systemone -H 'content-type: application/json' -d '{
"state": "Klient: od wczoraj nie mogę zalogować się do bankowości internetowej, system pokazuje błąd hasła.",
"questions": {
"dept": {"type": "choice", "instructions": "Do którego działu skierować zgłoszenie?",
"criteria": {"cards": "Reklamacje kart", "online": "Wsparcie bankowości elektronicznej", "loans": "Kredyty"}},
"urgent": {"type": "noul", "instructions": "Czy klient nie może korzystać z usługi?"}}}'
The answer (this model on one H100, installed as above, shortened):
{"model": "basal-omni-pico",
"answers": {
"dept": {"type": "choice", "choice": "online", "probabilities": {"cards": 0.0009, "online": 0.9983, "loans": 0.0008},
"confidence": 0.9983},
"urgent": {"type": "noul", "noul": 0.762, "probabilities": {"true": 0.762, "false": 0.238}, "confidence": 0.762}}}
Full API (multi, act, tool, option keys, max_error): API.
GGUF (llama.cpp, CPU or GPU)
basal-omni-pico-GGUF has a Q8_0 file with its own calibration file, served
by the same basal-serve with --mode gguf (llama.cpp in process, basal[gguf], basal 2.3.2 or later). On 1,700
development items it picks the same answer as this model in 99.24% of cases on one H100 and in 99.29% on the CPU.
On 16 CPU threads the request above takes about 0.5 s.
Serving modes (basal 2.5)
| mode | where | notes |
|---|---|---|
fast |
NVIDIA GPU with flash-linear-attention (checked on the H100) | the default there; --prefix-cache on and --batches compact (opt-in) need basal >= 2.5.0 |
eager |
anywhere (CPU or GPU) | float32, the reference; the default where fast is not available |
mlx |
Mac (Apple Silicon), basal >= 2.5.0 | float32 compute from this repository's bf16 weights; quantised MLX weights are refused for this model |
gguf |
CPU, NVIDIA GPU or Mac (llama.cpp, Metal on a Mac) | the file of basal-omni-pico-GGUF |
vllm |
NVIDIA GPU | the default preset (--vllm-preset deterministic is refused for this model) |
Refused for this model in basal 2.5: --mode fp8, nvfp4, fast-exit and mps, and --lanes. --long-lane is
refused unless --long-lane-gdn on is given (opt-in).
Results
Werdykt (our hidden Polish + English benchmark, 5,000 items): macro 0.660 [0.648, 0.671] (Polish 0.661, English 0.659). For comparison, basal-2.0-mini (1.5B) scores 0.618, basal-2.0 (4.5B) 0.729 and basal-omni-1.0-mini 0.769. By category: routing 0.912, retrieval 0.886, real documents 0.848, judging 0.752, scores 0.624, actions 0.592, long states 0.582, abstaining 0.544, contracts 0.542, rules 0.316.
Against the other decision models of 2B parameters or less that we ran (the same benchmark client for every model, each served by its own runtime):
| model | params | Werdykt macro [95% CI] | Polish / English | Werdykt ECE | dev v2 | LEK PL / EN | Polish check |
|---|---|---|---|---|---|---|---|
| basal-omni-pico | 0.8B | 0.660 [0.648, 0.671] | 0.661 / 0.659 | 0.138 | 0.646 | 35.9 / 45.1 | 0.876 |
| decider-2b (Mapika) | 1.9B | 0.587 [0.574, 0.599] | 0.580 / 0.593 | 0.123 | 0.576 | 45.0 / 59.1 | 0.582 |
| krino-2b | 2B | 0.566 [0.553, 0.579] | 0.552 / 0.580 | 0.051 | 0.528 | 36.8 / 50.7 | 0.598 |
| decision-2b (flymy-ai) | 2B | 0.546 [0.534, 0.558] | 0.492 / 0.600 | 0.030 | 0.532 | 29.0 / 45.7 | 0.542 |
| qev-0.8b | 0.8B | 0.544 [0.530, 0.556] | 0.530 / 0.558 | 0.088 | 0.572 | 33.2 / 44.5 | 0.592 |
| jiwo-0.8b | 0.75B | 0.542 [0.529, 0.554] | 0.516 / 0.567 | 0.047 | 0.518 | 30.0 / 40.8 | 0.533 |
- dev v2: our development set of 10,606 decisions (accuracy). LEK: the Polish medical final exam, Polish and English versions. Polish check: our Polish decision check set.
- Where others are ahead: decider-2b on LEK (45.0 / 59.1) and on our English, generated-Polish and panel check sets; every other model in the table is better calibrated on Werdykt (ECE 0.030 to 0.123 against 0.138), and decider-2b automates 9.8% of Werdykt at a 1% target, where this model automates none.
Public benchmarks: BH 75.3 (ECE 0.070); JevExtra 68.4, JevSpatial 68.7, Rules-7 68.6; JevBench accuracy 83.9, coherence 74.3. qev-0.8b is ahead on BH (77.9), JevExtra (71.8), JevSpatial (74.2) and JevBench accuracy (85.1).
Development sets (not test sets): dev macro 0.685 (panel 0.789, BH 0.552, JDI-shaped 0.706, agent 0.693); dev v2 accuracy 0.646 (Polish 0.633, English 0.656); our check sets: Polish 0.876, generated Polish 0.601, English 0.607, real Polish cases 0.940, panel 0.593.
Accuracy by document length
Accuracy of basal-omni-pico on Werdykt (5,000 items, Polish and English; a hidden set, so only these totals are shown) by the length of the state, in characters (a token is about 2 characters; 1,000 characters is about half a page). 66.0% overall. 95% Wilson intervals in brackets.
| state length | items | accuracy |
|---|---|---|
| 0-1k | 709 | 54.3% [51, 58] |
| 1k-2k | 2598 | 64.2% [62, 66] |
| 2k-4k | 796 | 76.8% [74, 80] |
| 4k-8k | 394 | 86.3% [83, 89] |
| 8k-16k | 128 | 68.8% [60, 76] |
| 16k+ | 375 | 54.9% [50, 60] |
Short states are mostly rules and abstention items, which are harder for every basal model, so read the rows as accuracy per bucket, not as the effect of length alone. The long-document family keeps the task and varies only the length:
| state length (long-document family) | items | accuracy |
|---|---|---|
| 8k-20k | 226 | 63.7% [57, 70] |
| 20k-30k | 194 | 59.3% [52, 66] |
| 30k+ | 80 | 40.0% [30, 51] |
Run 2026-10-22 with basal-serve --mode eager on one NVIDIA H100 80GB HBM3 (bf16). The intervals are about the items, not about run-to-run noise.
By prompt length in tokens (held-out tests)
The held-out tests of the Results table by the length of the whole prompt as served (state, question and options; this model's tokenizer), with the Results table's predictor. Accuracy (items):
| prompt tokens | PL decisions (7,081) | EN corpus test (1,479) | PL-Real (300) |
|---|---|---|---|
| 0-255 | 87.7% (3,119) | 62.8% (1,133) | – |
| 256-511 | 91.0% (2,330) | 56.3% (263) | – |
| 512-1,023 | 82.7% (1,622) | 45.8% (83) | 80.0% (5) |
| 1,024-2,047 | 90.0% (10) | – | 93.5% (186) |
| 2,048-4,095 | – | – | 95.4% (109) |
Calibration
CALIBRATION.json holds per-type temperatures and certified thresholds for max_error 1% and 5%. It was fitted on
readouts of this model as basal-serve runs it (--mode eager, bf16, one option order, the default), on our
calibration set (fit and certification splits), and evaluated on a frozen test split of 8,560 decisions:
| choice | yes/no (noul) |
score | all | |
|---|---|---|---|---|
| ECE after the temperature (test) | 0.0125 | 0.0109 | 0.0645 | 0.0059 |
| accuracy (test) | 0.883 | 0.813 | 0.601 | 0.831 |
- Automation on the test split: at
max_error1%, 35.0% of decisions are decided automatically (observed error 0.93%); at 5%, 58.2% (observed error 4.38%). At 1% onlychoicequestions have a threshold (yes/no and score questions defer); at 5% score questions defer. - Held-out-family check (each task family left out of the fit in turn, pooled ECE per type): choice 0.015, yes/no 0.016, score 0.038, all under our 0.05 bar.
CALIBRATION.o2.jsonis the same fit for--orders 2(both option orders); basal-serve picks it when you serve with--orders 2.- What the guarantees cover. The 1% and 5% thresholds hold on our held-out test split (35.0% and 58.2% of decisions automated, above). On Werdykt, an out-of-domain benchmark, served with this file, the model is overconfident: mean confidence 0.80 against accuracy 0.66 (ECE 0.138, Brier 0.475). At a 1% target nothing is automated; at 5%, 33.9% is automated with an observed error of 6.3%, so the 5% target is not met there.
- Outside our domains, refit first. Fit the thresholds on your own labelled cases (
basal-calibrate) before you automate withmax_error.
Speed
basal 2.4 on one H100 80 GB, basal-serve --no-calibration, one connection per request; p50 at concurrency 1 /
throughput at 16 clients (decisions/s; questions/s with five questions per request). Short states are about 1,500
tokens, long ones 3,000–10,000.
| path | 1 question, short state | 5 questions, short state | 1 question, long state | 5 questions, long state |
|---|---|---|---|---|
--mode fast (basal 2.4, the default on an H100) |
13.5 ms / 134.6 | 26.6 ms / 400.4 | 45.9 ms / 34.4 | 90.6 ms / 94.4 |
--mode fast-nocompile (basal 2.4) |
17.4 ms / 89.3 | 33.5 ms / 328.2 | 64.0 ms / 22.9 | 110.5 ms / 80.1 |
--mode eager |
45.5 ms / 32.8 | 112 ms / 41.9 | 183 ms / 6.6 | 908 ms / 6.6 |
--mode vllm (vLLM 0.31.0) |
54.3 ms / 93.9 | 67 ms / 188.7 | 39 ms / 43.7 | 109 ms / 90.6 |
--mode gguf Q8_0 on the GPU |
56.5 ms / 18.1 | 98 ms / 54.7 | 283 ms / 4.7 | 360 ms / 18.6 |
- basal 2.4 serves this model in its fast CUDA-graph engine: 3.5x eager's speed on one question and 4-10x with
five questions over one state, whose recurrent state is computed once for all of them. Install
flash-linear-attention for it:
uv pip install "flash-linear-attention==0.5.2". Without it, and on GPUs other than Hopper, the model runs ineagerunless you pass--mode fast(on other GPUs it has not been checked). - The same answers as eager: in fp32 the top answer agrees with
--mode eageron 99.94–99.99% of 1,700 development items (one question, five questions, two option orders, both); in bf16fastagrees with the fp32 answers as often aseagerdoes (99.44–99.65% against 99.48–99.71%). Under load,--deterministicand batched serving gave the same top answer on 99.83% of the 10,606 dev decisions (eager: 99.42%). - One question over a long state is still faster in
--mode vllm(39 against 46 ms). - Werdykt's own speed pass on this model (one H100, eager): 47 ms p50 at concurrency 1, 32.4 decisions/s at 16.
--mode vllmagreed with eager on the top answer for 99.47% of 1,700 development items (same checkpoint); it has no calibration file of its own and usesCALIBRATION.json.--mode fastusesCALIBRATION.jsontoo.- CPU: see the GGUF section.
Evaluation notes
- Contamination checks on the training mix (exact, 13-gram and short-state matching), hits left in the final mix in brackets: Werdykt, hidden (0); the Jev Decision Index 0.3 test requests, 150 rows dropped (0); our evaluation documents, 204 rows dropped (0); the insurance benchmark v1 325 + v2 3,042 items (0); LEK, the Polish medical final exam, pl 4,727 + en 3,151 items, 331 rows dropped (0): statute and social-insurance wording that our legal rows share with 29 medical-law questions, not exam items.
- Werdykt (hidden benchmark). Run on these weights with basal 2.3.1
--mode eager(flash-linear-attention 0.5.2), one H100 80 GB (RunPod), 5,000 of 5,000 items answered; then rerun on a RunPod pod with this repository's files (basal 2.3.2,--mode eager, the shippedCALIBRATION.json): the same macro (0.660). The Werdykt calibration numbers on this card come from the rerun. - Selection. Two runs of the same recipe (seeds 0 and 1) and their 50/50 weight average were the candidates. The rule fixed before the runs picked the single seed-0 run, since the average led it on dev by only 0.28 points (0.685 vs 0.682, inside the rule's 0.5-point tie). We release the average: we chose it after both Werdykt results were known (0.660 vs 0.649, overlapping intervals).
Files
model.safetensors,config.json,generation_config.json: the weights (bf16; the 18A_logtensors and the 18 Gated DeltaNet norms in fp32; Qwen3_5ForCausalLM, text only);model.safetensorssha256ac52f85bf4af603b2d2408d314e9c1bb59e351884f7cacd72464c49dca9149e9- the tokenizer files and
chat_template.jinja basal.json(prompt format 2, readout),CALIBRATION.json(one option order),CALIBRATION.o2.json(two)MANIFEST.md: training data by source and language, guard reportsprepared/<key>/(basal >= 2.5.0): the prepared start-up for the H100 (compiled kernels and fla's kernel configs);basal-serve --prepared auto, the default, fetches only the directory of its own GPU and versionsSHA256SUMS: the sha256 of every file above and ofREADME.md(check withsha256sum -c SHA256SUMSin a full download such ashf download Remek/basal-omni-pico; basal's own download leavesprepared/out)
How it works
Prompt format 2 of the basal engine: the state and the question with its options as one prompt, then a short answer prefix; the logits of the option codes at the first answer position, scaled by the calibrated temperature of the question type, are the probabilities. Nothing is generated.
Training
Full fine-tuning of Qwen/Qwen3.5-0.8B-Base (revision
dc7cdfe2ee4154fa7e30f5b51ca41bfa40174e68; the language model, every weight) on 1,428,543 rows in prompt format 2, none
over 6,144 tokens: the guarded basal training mix plus 100k generated short edge cases (rows by source and language:
MANIFEST.md). Two runs with seeds 0 and 1, each 1.4 epochs: 27,778 steps at a global batch of 72 (8 sequences × 3
accumulation steps × 3 GPUs), learning rate 5e-6 with 20 warm-up steps and a cosine decay to 0.1×, AdamW (0.9, 0.95),
no weight decay, fp32 master weights with a bf16 forward. The released weights are the 50/50 average of the two final
checkpoints.
The loss is cross-entropy on the gold answer plus three terms:
- a Brier term on
choicequestions (weight 0.5); - the squared error of the expected level on
scorequestions (weight 1.0); - distillation from basal-omni-1.0-ultra (31B), whose option-code probabilities are the targets (weight 1.0) on 1,254,097 rows. It is skipped on 67,885 rows where the teacher's top answer differs from the gold label, and on yes/no rows where the teacher is not decisive.
Trained on 3× H100 with PyTorch 2.11, the flash-linear-attention 0.5.2 kernels for the Gated DeltaNet layers and Triton 3.7.1.
Limitations
- Trained on prompts of up to 6,144 tokens (Werdykt long states: 0.582); at most 255 options per question (prompt format 2).
- A 0.8B model knows little: put every fact the decision needs into the state.
- Rule checks are its weakest area (Werdykt rules 0.316): check it on your own rule cases before you rely on it.
- Exact arithmetic is a weak spot of one-pass decisions: compute numbers in code and pass the result.
- Overconfident on new kinds of data (see Calibration).
- Decisions with serious consequences for people should be reviewed by a person.
Citation
@software{kinas2026basal20,
title = {basal-2.0: typed-decision models and inference engine for Polish and English},
author = {Kinas, Remigiusz},
year = {2026},
version = {2.0.0},
url = {https://github.com/rkinas/basal}
}
License and attribution
Apache-2.0. Fine-tuned from Qwen/Qwen3.5-0.8B-Base (Apache-2.0) by the Qwen team; the base's vision encoder is not included (text only).