v0.18.0 Release notes

Decisions you can trust, on your own hardware. Open source.

Send a text and a question with its options. Get back a probability for every option, in one call. Teach it your task, and it certifies which answers to trust.

  • 81 ms for one question about a new 300-token text
  • 1.08 s for 50 questions about a 3,000-token document
  • 10.1 s for 50 questions about a 32,000-token document

Server time on Gemma 4 31B and one RTX PRO 6000: the first on decisio 0.8.1 at 585 W, on 2026-10-06; the other two on decisio v0.11.1 at 600 W, on 2026-10-11. How these were measured.

recordedGemma 4 31B, decisio 0.17.0, RTX PRO 6000 at 600 W, 2026-10-19
Support ticketModerationForm checkTool decision

Incoming support ticket · record 1 of 60

I was charged twice for October. Both charges are 49.00 EUR, same day. Please refund one.

reads it oncethen scores every question in one batch

urgentyes/no

Does this ticket need a response within the hour?

  • yes0.16

queuechoicebilling

Which team should handle this ticket?

  • billing0.96
  • bug0.02
  • access0.01
  • +3 more

impactscoreexpected level 0.9

Rate the business impact using only the reported facts.

  • 00.26
  • 10.65
  • 20.05
  • 30.04

3 answers in one batch · 79.1 ms server time

See the request and its answer

Teach it

Teach it your labels. It tells you which answers to trust.

A support inbox with 77 kinds of request: the server learns what each label means from a few examples, then marks every answer it is sure of. The model's weights never change.

  1. 1 Learn your labels
  2. 2 Draw the line
  3. 3 Route the answers
Teaching a task, then certifying its answers Labelled examples of BANKING77 go into Decisio; the answer sharpens and accuracy goes from 77.6% to 84.2% on the Gemma 4 31B. Then 48 answers of banking77's test messages, on the Gemma 4 31B, are ordered by confidence; a threshold line moves down until 19 are above it. Those are certified and go to automation, 0 of them wrong; the other 29 go to a person. 1 Your labelled examples label card_arrivallabel exchange_ratelabel lost_or_stolen_cardlabel pending_card_paymentlabel cash_withdrawal_chargelabel declined_transferlabel card_linking Decisiolearns your labelsmodel unchanged An answer, before and after Accuracy, BANKING77 before77.6% after teaching84.2% 770 examples (10 per label) 2 48 answersmost confident firstBANKING77's test messages,Gemma 4 31B. a right answera wrong one threshold 0.941: 19 above it 3 Certified: automated Not certified: a person CERTIFIED Teaching a task, then certifying its answers Labelled examples of BANKING77 go into Decisio; the answer sharpens and accuracy goes from 77.6% to 84.2% on the Gemma 4 31B. Then 48 answers of banking77's test messages, on the Gemma 4 31B, are ordered by confidence; a threshold line moves down until 19 are above it. Those are certified and go to automation, 0 of them wrong; the other 29 go to a person. 1 Your labelled examples label card_arrivallabel exchange_ratelabel lost_or_stolen_cardlabel pending_card_paymentlabel cash_withdrawal_chargelabel declined_transfer Decisiolearns your labelsmodel unchanged An answer, before and after Accuracy, BANKING77 before77.6% after teaching84.2% 770 examples (10 per label) 2 48 answersmost confident firstBANKING77's test messages, Gemma 4 31B. rightwrong threshold 0.941: 19 above it 3 Certified: automated Not certified: a person CERTIFIED
Right answers, untaught and taught
77.6% to 84.2%
Taught with
770 examples 10 for each label

The dots are 48 of its answers, a seeded random sample, split by the certificate at most 5% wrong.

BANKING77's test split, Gemma 4 31B from its FP8 checkpoint on one RTX PRO 6000 Blackwell, decisio 0.14.0, 2026-10-16.

  1. Teach.

    Send labelled examples of your question. It takes minutes, and the weights stay as they are.

  2. Certify.

    The server holds some of your examples back and finds the confidence above which wrong answers stay under the rate you pick.

  3. Act.

    Every answer says whether it is certified. Automate the certified ones and send the rest to a person.

Certify

Pick an error rate. See what it answers on its own.

The certificate promises, nine times in ten, that at most the rate you pick of its certified answers are wrong. A stricter rate sends more of the inbox to a person.

At most wrong
Answered on its own
43.3% 1,335 of 3,080 messages
Wrong among those
3.2% 43 messages
Sent to a person
1,745 messages

Certify answers: the promise, and how to make a certificate for your task.

Use cases

One question, asked of every item.

Each recipe is the question, the code that routes on its certificate, and what it did when measured.

  • Support routing

    Send each ticket to the right queue.

    Measured: the support inbox above.

  • Coding-agent gatekeeper

    Allow, ask or block an agent's shell command, by your rules.

    34% to 40% of commands decided on their own at a 5% error rate.

    Gemma 4 12B on a Mac, decisio 0.14.0, 2026-10-17 and 2026-10-18

  • Issue triage

    Label the kind of a new issue and its owning team.

    85.1% right on an issue's kind, untaught, on 1,000 kubernetes issues.

    Gemma 4 31B, decisio 0.11.1, one RTX PRO 6000, vLLM 0.30.0, 2026-10-14 to 2026-10-15

  • Guardrails

    Flag a message that breaks a policy.

    97.3% right on ToxicChat's toxicity question.

    Gemma 4 31B, one RTX PRO 6000, vLLM 0.30.0, 2026-10-04

  • RAG: answer or abstain

    Answer only when a retrieved passage answers the question.

    82.7% right on SciFact's claims and their evidence.

    Gemma 4 31B, one RTX PRO 6000, vLLM 0.30.0, 2026-10-04

  • Document classification

    Sort incoming documents by type.

    A recipe: no run on documents is published yet.

Every use case, and the recorded demos: Pong, a driving simulator, a browser agent and ticket triage.

Is it for you

Good fit, and not a good fit

Good fit

  • You ask the same question about many texts, with fixed options: route a ticket, flag a message, approve a command.
  • You have labelled examples: 118 or more, at the defaults, for a task you want certified.
  • You want the answers it is sure of automated, and the rest sent to a person.
  • You want to know when traffic drifts: certification pauses on its own while the confidence alert is on.
  • Your options run into the hundreds: up to 255 per question.
  • Your documents are long: at least 32,768 tokens on a Gemma model on a card, and up to 98,304 on the 31B, as the card allows.
  • Your data must stay on your machines: the default model runs on one NVIDIA card, measured on 96 GB and also run on an 80 GB H100, or on a 64 GB Mac.

Not a good fit

  • You need written text back, such as a summary or a reply: every answer is a probability for each option.
  • You have no labelled examples but need answers it stands behind: below 59 held-out examples it will not certify.
  • You need almost no errors from a few examples per option: at most 2% wrong, the support inbox above certified nothing.
  • Your labels or your serving setup change every week: a certificate covers one task on one serving setup, so certify again after changing either, and after upgrading decisio.
  • You want these numbers on a laptop with Ollama: Ollama builds its own prompt and applies no calibration.
  • You have long documents on a Mac: there the 31B is documented for texts up to 16,383 tokens.

Hardware, context lengths and what was measured on what: Requirements and limits.

On the board

What the public board says

JevBench v1.6.1 composite, with 95% intervalsDecisio 31B: 71.69, 95% interval 69.86 to 72.81; Jev 1.13.0: 71.49, 95% interval 69.14 to 72.40.68697071727374Decisio 31BJev 1.13.0

On JevBench v1.6.1 (the board's file, October 2026), Decisio 31B scored 71.69 on the composite (95% interval 69.86 to 72.81) and Jev 1.13.0 scored 71.49 (69.14 to 72.40); the two intervals overlap.

Source: the JevBench board's v1.6.1 file, read on 2026-10-09; its Decisio 31B row is decisio v0.8.0.

The live board has today's standings, and Benchmarks has what was measured and how.

Get started

Run it, then ask it a question.

Pick where it runs, paste its block, then send the request below. Get started walks through each step.

Linux with one NVIDIA card.

python3.12 -m venv .venv && . .venv/bin/activatepip install "decisio[serve]==0.18.0"python -m decisio.serve.vllm_engine  # serves Gemma 4 31B; the first start downloads about 31 GBcurl -s http://127.0.0.1:8000/health  # answers once it is ready

On a cloud GPU: the whole guide, and what to check before production.

A GPU host with Docker and the NVIDIA Container Toolkit.

docker run -d --gpus all --shm-size 8g --restart unless-stopped \  -p 127.0.0.1:8000:8000 -v decisio-data:/data \  ghcr.io/aminry/decisio@sha256:9a162580b0c2bdd1effc9dc6130f0bc38e988606a83aae7c3de9afdbece941e1curl -s http://127.0.0.1:8000/health  # answers once the first start has fetched the weights

With Docker: the whole guide, and what to check before production.

A Mac with Apple silicon; the guide says which build fits yours.

git clone --branch v0.18.0 https://github.com/aminry/decisiocd decisiouv sync --extra mlxuv run python -m decisio.serve.vllm_engine --backend mlx --base gemma-4-31b --model mlx-community/gemma-4-31b-it-6bit

On a Mac: the whole guide, and what to check before production.

A quick try on a laptop. Ollama builds its own prompt, so its numbers are not the ones on this page.

ollama pull aminroudaki/decisio-gemma  # the Gemma 4 12B base, for 16 GB laptopsollama pull aminroudaki/decisio  # the Qwen base
curl http://localhost:11434/v1/systemone \  -H 'Content-Type: application/json' \  -d '{  "model": "aminroudaki/decisio-gemma",  "state": "Hi, since this morning none of our 40 staff can log in to the dashboard. We get \"session expired\" right after entering the password. Payroll is due today.",  "questions": {    "urgent": {      "type": "noul",      "instructions": "Does this ticket need a response within the hour?"    },    "category": {      "type": "choice",      "instructions": "Which team should handle this ticket?",      "criteria": {        "billing": "Invoices, payments, refunds",        "access": "Login, passwords, permissions",        "bug": "The product behaves wrongly",        "other": null      }    },    "impact": {      "type": "score",      "instructions": "Rate the business impact using only the reported facts.",      "criteria": [        "No function impaired",        "One user impaired, with a workaround",        "Many users blocked from a core function",        "Data loss or legal exposure"      ]    }  }}'

With Ollama: the whole guide, and what to check before production.

Then ask a question

One request with a support ticket and three questions about it, to the server on port 8000:

curl http://127.0.0.1:8000/v1/systemone \  -H 'Content-Type: application/json' \  -d '{  "state": "I was charged twice for October. Both charges are 49.00 EUR, same day. Please refund one.",  "questions": {    "urgent": {      "type": "noul",      "instructions": "Does this ticket need a response within the hour?"    },    "queue": {      "type": "choice",      "instructions": "Which team should handle this ticket?",      "criteria": {        "billing": "Invoices, payments, refunds, prices, VAT",        "access": "Login, passwords, two-factor, SSO, permissions, invitations, account security",        "bug": "The product behaves wrongly: errors, crashes, wrong numbers, lost data",        "feature": "A request for something the product does not do yet",        "cancellation": "Cancelling, pausing or closing an account, deleting data",        "other": "Press, partners, jobs, sales pitches, wrong address, thanks, general questions"      }    },    "impact": {      "type": "score",      "instructions": "Rate the business impact using only the reported facts.",      "criteria": [        "No function impaired",        "One user impaired, with a workaround",        "Many users blocked from a core function",        "Data loss or legal exposure"      ]    }  }}'
Its answer: every question under its name, with a probability for each option
{  "answers": {    "urgent": {      "type": "noul",      "noul": 0.159    },    "queue": {      "type": "choice",      "choice": "billing",      "probabilities": {        "billing": 0.962,        "access": 0.011,        "bug": 0.016,        "feature": 0.004,        "cancellation": 0.005,        "other": 0.003      }    },    "impact": {      "type": "score",      "probabilities": {        "0": 0.256,        "1": 0.648,        "2": 0.053,        "3": 0.042      }    }  }}

The hero above draws this answer. Call it from your code: the same request from Python, JavaScript and TypeScript.

Run it on your own task.