Repository navigation
basal 2.0
basal 2.0
basal-2.0 is a family of three typed-decision models for Polish and English, with engine v2.0.0: up to 255 options per
question, one forward pass with one option order, a faster single-GPU server, a tool question type, calibration you
can refit on your own data, and an experimental thinking mode on the 4.5B model. Models on Hugging Face:
Remek/basal-2.0-mini,
Remek/basal-2.0-4.5B,
Remek/basal-2.0-max
(basal-2.0 collection).
The same engine also serves basal-omni-1.0 (experimental): basal-omni-1.0-mini (4B) and basal-omni-1.0-max (12B),
typed-decision models built on Google Gemma 4 that can take images and audio in a request:
Remek/basal-omni-1.0-mini,
Remek/basal-omni-1.0-max.
Highlights
- Three models: basal-2.0-mini (1.5B), basal-2.0 (4.5B) and basal-2.0-max (11B), in bf16, FP8 (NVIDIA ModelOpt,
served by the basal engine), GGUF (Ollama, llama.cpp) and MLX 8-bit (Apple Silicon). - Werdykt (hidden Polish–English decision benchmark, 5,000 decisions): basal-2.0-mini 0.618, basal-2.0 0.729,
basal-2.0-max 0.784, against 0.607 / 0.721 / 0.773 for basal-1.5 (+1.2 / +0.7 / +1.1 points). Calibration error
0.035 / 0.060 / 0.044 against 0.086 / 0.068 / 0.074. Hosted API models and larger open decision systems score higher;
the public board lists every tested system. - Faster on one H100 (bf16, 16 clients, Werdykt speed pass): mini 106.4 decisions/s (basal-1.5-mini 20.5, ×5.2);
4.5B 32.2 (basal-1.5 on SGLang 23.0, ×1.4); max 16.2 (basal-1.5-max on SGLang 10.2, ×1.6). - Up to 255 options per question (basal-1.5: 10), read in one forward pass with one option order by default.
basal-1.5 left 17.2% of the Decision Index (JDI 0.2.1) requests unanswered; basal-2.0 answers all but 26 of 150,317
(mini) or all of them (4.5B, max). JDI: 26.69 / 39.86 / 44.07 (basal-1.5: 16.41 / 27.65 / –). - Where basal-2.0 is not better: on a panel of 10 public English decision tasks all three are below basal-1.5
(−2.1 / −3.6 / −1.8 points); basal-2.0-mini is below basal-1.5-mini on Polish decisions (−1.4 points); at the 1%
target error on Werdykt, 4.5B and max automate fewer decisions than basal-1.5. - Calibration per question type and option-count bucket, fitted on question families the models were not trained
on; the shipped files certify the 5% error target, not the 1% target (exceptCALIBRATION.ollama.jsonof
basal-2.0-max-GGUF, which certifies 1% forchoice, confidence 0.989).basal-calibraterefits temperatures and
certified thresholds on your own labelled requests. - Thinking mode (basal-2.0 4.5B, experimental, off by default):
--think autowrites a short reasoning note for
uncertain questions on a vLLM sidecar. On Werdykt it lowered the macro score (0.719 vs 0.729), raised the calibration
error (0.099 vs 0.060) and cut throughput to 11.5 from 31.2 decisions/s; we recommend leaving it off.
basal-omni-1.0 (experimental): images and audio
- Two models on Google Gemma 4: basal-omni-1.0-mini (4B, Gemma 4 E4B) and basal-omni-1.0-max (12B). They
answer the same typed questions over the same API; with--media ona request may also carry images and audio
("media"). - Trained on text decisions only: Gemma 4's own encoders read the images and audio zero-shot, and answers with media
use the text calibration ("calibration": "text"). Validate them on your own media before automating with them. --mode eageronly, bf16 on an NVIDIA GPU: no FP8, NVFP4, GGUF or MLX ports and no thinking mode yet.- Install the
mediaextra and serve with--media on:
uv pip install torch==2.11.0 torchvision==0.26.0 --index-url https://download.pytorch.org/whl/cu128
uv pip install "basal[media] @ https://github.com/rkinas/basal/archive/refs/tags/v2.0.0.tar.gz"
basal-serve --model Remek/basal-omni-1.0-mini --mode eager --media on --port 8000 # or Remek/basal-omni-1.0-maxDetails: images and audio and
docs/OMNI.md.
Install
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/cu128
uv pip install "basal[fp8] @ https://github.com/rkinas/basal/archive/refs/tags/v2.0.0.tar.gz"
basal-serve --model Remek/basal-2.0-4.5B --mode fast --template-prefix off --port 8000Every engine (FP8, vLLM, SGLang, MLX, Ollama, llama.cpp) and the thinking mode:
README. basal-serve is the decision layer in every mode: vLLM, SGLang,
MLX, Ollama and llama.cpp run the weights, and the typed, calibrated answers come from basal-serve --mode <engine> in
front of them.
Engine v2.0.0
Models and formats
- Prompt format 2: up to 255 single-token option codes, the state before the question, one option order by default
(--orders 1 | 2 | auto); runtime contract with test vectors indocs/FORMAT2.md. - Calibration file 2: a temperature per question type and option-count bucket, thresholds certified per question type,
gates and themultifallback threshold; per-engine files (CALIBRATION.<engine>.json) and per-order files
(CALIBRATION.o2.json). - Option-code logits in fp32 in every backend (PyTorch, MLX).
--mode fp8loads NVIDIA ModelOpt FP8 checkpoints natively in the CUDA graph engine;--fp8-accum fast | full.- vLLM reads more than 128 option codes.
- the basal-omni models (Gemma 4 architecture) in
--mode eager, and with--media onand thebasal[media]extra (pillow,
soundfile, scipy, torchvision) requests with images and audio:"media","detail"(image tokens) and"lang". --mode eager, every model: option codes read in fp32, left-padded prompts read at their own positions, prompts
over 2,048 tokens prefilled in 2,048-token chunks, batches capped at 16,384 padded tokens.
Speed
- Compact batching (
--batches compact, FlashAttention 3 varlen): +19% decisions/s at 16 clients, +17% at 32, +8% at
one client (4.5B, bf16, one H100). - The prompt template computed once at start-up (
--template-prefix): +20% at 8 clients (mini, max). - A scheduler for long requests (
--scheduler): in a mixed load at 32 clients short requests answer in 0.81 s instead
of 1.38 s (p50); long requests take about 7% longer. - FlashAttention 3 on Hopper by default for bf16 weights when installed (FP8 keeps FlashAttention 2, the checked
path, unless--attn fa3: 21–26% faster, but 3–8% of decisions differ, mostly near ties, and accuracy moved by
−0.8 to +1.4 points on a development sample;
--attn auto | fa2 | fa3 | fa4 | cudnn), merged q/k/v and gate/up projections for bf16 weights
(--merge), pass-2 CUDA graphs for branched requests. - Opt-in, off by default:
--lean,--tree flex,--readout-layer,--state-cache-gb,--prefix-cache,
--long-lane.
API and tools
toolquestion type: the next tool, or answer directly / ask the user / no suitable tool, from OpenAI, MCP or
Anthropic tool definitions;rank,"multi": truefor a set of tools,max_errordeferral (experimental).- MCP for agents (experimental,
basal[mcp]):basal-serve --mcp onalso serves the decisions as an MCP server at
/mcp(streamable HTTP; toolsdecidefor one question anddecide_manyfor every question type over one
state), andbasal-mcp --url <server>connects a running server to agent hosts over stdio. multi: set objectivesiou,f1andexact;exclusiveandfallbacklabels.basal-calibrate: fits temperatures and certified thresholds on labelled requests, with the engine you serve.--deterministic: answers independent of load and of other requests;basal-loadtest --determinism Nalso counts
decision flips under load.--context-overflow truncate | refuse: a state over the context loses its middle (marked inusage.truncated).--think off | auto,--think-tokens,--think-python(experimental thinking mode, basal-2.0 4.5B).basal-bench --identity: every prefix-reuse path of the fast engine against an eager forward of its own prompt;
synthetic long-state items for speed runs;basal-loadtest --questions-per-request.GET /v1/modelsreports the temperatures in use.
Upgrading from v1.5.0
- Long states are cut, not refused. With the default
--context-overflow truncate, a state over the context loses
its middle and the answer says so inusage.truncated;--context-overflow refusekeeps HTTP 422. max_errordefers without a certified threshold. When the calibration file has no threshold certified for the
question's type and target, every automaticact/tooldecision of that type is deferred; a threshold pooled
over all types is never applied. With the basal-2.0 files,max_error: 0.01defers every decision
(except that onechoicecertificate of basal-2.0-max-GGUF in--mode ollama).- Calibration and option orders. A calibration file's thresholds apply only to the option orders it was fitted
with; served with other orders, the server keeps the temperatures, drops the thresholds and says so at start-up. A
missing--calibrationfile is refused at start-up. - Answers are not bit-identical to v1.5.0 (fp32 option-code logits, other GEMM row counts); decisions can change
near ties.--deterministicis reproducible on a given GPU. - basal-1.5 and basal-1.0 models are served unchanged (prompt format 1, two option orders by default).
Known limitations
- The calibration is cautious on new tasks: no 1% threshold is certified in the shipped files (except
basal-2.0-max-GGUF'sCALIBRATION.ollama.json, forchoice); use 0.05 or fit your own thresholds. - basal-2.0-mini has an 8,192-token context (4.5B and max: 32,768).
- The basal-2.0 models ship no evidence head:
"evidence": trueis refused for them. - Ollama returns at most 20 log-probabilities, so questions with more than 20 options need llama.cpp or another engine.
- The basal-2.0 numbers were measured with the basal engine; vLLM and SGLang were checked against it with basal-1.5.
act,tool,multiover many labels, the MCP server and the thinking mode are experimental. The MCP endpoint,
like the HTTP API, has no authentication: bind--host 127.0.0.1or put it behind a gateway.- basal-omni is experimental: trained on text decisions only, images and audio read zero-shot and answered with the
text calibration;eagermode only, without the ports and the thinking mode of basal-2.0. - Decisions with serious consequences for people should be reviewed by a person.