Confident and wrong

2 October 2026 · When can you trust a model that says how sure it is?

Run it in Colab · Code on GitHub

Some AI models do not write text. You give them a text and a list of possible answers, and they give back a probability for each answer. The promise is that you can rely on that probability: let the model act when it says 95 %, send the case to a person when it says 60 %. I built a small model of this kind for sorting security alerts and tested where that reliability comes from. The way the model was trained mattered far less than its makers suggest. What mattered was how much data it had seen and whether the input looked like that data. On logs it could not read, it was right 26 % of the time and still 52 % sure.

The claim

Many steps in an AI system are decisions, not writing: which team gets this support ticket, whether this message is an attack, what kind of alert this is. The usual way to make them is to ask a chatbot-style model and read its reply. That is slow and costly for what is really a multiple-choice question.

A decision model is built for the multiple-choice question. It takes a text and a list of options and returns one probability per option, in a single step. In September 2026 the company TypeSafe launched one called Jev, available only through its paid service. Shortly afterwards Nandakishor M released Laya, a free and open one, which collected about 29,500 stars on GitHub in two weeks. This post examines the open one in a toy world. I did a test of Jev on real agent failures in a second post, Can a decision model find where an agent failed?

Two words carry the rest of this post.

Calibration is what makes a rule like “act automatically above 90 %” safe. Without it, the number is decoration.

Laya's author says its calibration comes from the way it is trained. Training works like this: the model answers many examples, a formula gives each answer a score, and the model is adjusted to score higher. I will call that formula the reward. The standard reward is called cross-entropy. The author argues that cross-entropy makes a model over-confident, and that Laya avoids this with a different training method, called RLCD. Laya's documentation draws the practical conclusion: because of that training, its “confidence scores are statistically meaningful”.

That is a claim about a reward, and a reward can be tested on a small model.

Hypothesis

First, what makes a reward good for calibration. Suppose an answer is truly 70 % likely to be right, and the model has to report a probability.

Average reward against reported probability when the truth is 70 percent: one point for a right answer peaks at 100 percent, the log score and the spherical score peak at 70 percent
The average reward for each probability the model could report, when the truth is 70 %. Only the two on the right reward the honest answer.

The middle panel, the log score, is cross-entropy under another name. Laya's reward is the log score plus half of the spherical score in the right panel. Both pay for honesty, so I doubted that the choice between them decides anything. My two predictions:

If Laya's documentation is right, the first prediction should fail: Laya's method should give a clearly better-calibrated model than cross-entropy.

Setup

How a decision model works

A chatbot-style model writes its answer in small pieces, each a word or part of a word. Every piece needs one full run of the network, and each new piece is fed back in to produce the next. If you ask it how sure it is, that number is written text as well, and nothing ties it to how often the model is right. A decision model runs the network once and reads the probabilities directly.

A generative LLM writes its answer one piece at a time and the text is then parsed; a decision model returns one probability per option in a single run
The same decision, two ways.

Inside Laya the trick is in how the input is laid out. For each question it builds one sequence: the question, then every option with a placeholder in front of it, written [MASK], then the text to judge.

The input passes through an encoder and a decision head; the output at each MASK position is turned into a raw score per option, and a formula called softmax turns the scores into probabilities
Laya's design, drawn from the code in its repository, with a security example. The scores are made up for illustration.

Reading the diagram from top to bottom:

The size of a network is counted in parameters, the numbers that training adjusts. Laya has 421 million. My model has 76,353. It is the same design, small enough to train on a laptop in a couple of minutes.

A world where the right confidence is known

Calibration is normally checked by comparing confidence with accuracy on examples that have a known answer. I wanted something stricter: for every single case, the probability that an ideal model should report. To have that, I had to generate the data myself.

The setting is a security team. Monitoring software raises alerts, and someone has to decide what each one is. This sorting is called alert triage. In my toy version:

Because I wrote the program that generates the sessions, I can calculate the exact probability of each class for any session. A short, ambiguous session has an honest answer that is well below 100 %.

An example session of five events and the exact probability of each of four offered classes: brute force 0.63, credential stuffing 0.34, phishing 0.00, benign 0.02
Two failed logins among ordinary activity. An ideal model would say 63 % brute force, and no more.

Each question offers the true class and a few wrong ones, in random order. With 4 options, even an ideal model is right only 84.7 % of the time, because the remaining sessions are truly ambiguous. That is the best possible accuracy in this world.

The sessions are invented. Nothing here comes from real logs. The security setting is there because it makes the stakes easy to see: a confident wrong answer is either an attack filed as harmless or an analyst's morning spent on nothing.

Three ways to train it

The same small model is trained with three rewards.

Each is trained on 1,000, 4,000, 16,000 or 64,000 sessions, for the same number of training steps. Every run is repeated three times with different random starting points, and I report the average. That makes 36 training runs.

What is measured

Each trained model answers 5,000 new sessions, and I record three numbers:

The models are tested in five situations:

Experiment

On sessions like the training data

Calibration error with 4 options. Each cell is the average of 3 runs, with the spread between runs after the ±. Lower is better and 0.010 is the best achievable.

training sessionscross-entropyLaya's methodone point if right
1,0000.198 ± 0.0050.201 ± 0.0030.209 ± 0.004
4,0000.152 ± 0.0150.108 ± 0.0100.163 ± 0.002
16,0000.016 ± 0.0020.019 ± 0.0040.153 ± 0.003
64,0000.009 ± 0.0020.011 ± 0.0020.148 ± 0.003
Calibration error against training-set size: cross-entropy and Laya's method fall together from 0.20 to 0.01, one point if right stays near 0.15
The shaded band is the spread between the 3 runs. The grey line is the best achievable.

Cross-entropy and Laya's method give the same result. With 16,000 sessions or more, both reach the best achievable value: their confidence is the true probability, give or take chance. With 1,000 sessions both are badly over-confident, 97 % sure and 77 % right. A small model shown the same few examples many times ends up memorising them instead of learning the pattern, and a model that has memorised its examples is sure of everything.

So the amount of data changes the calibration error twenty-fold. The choice between these two rewards changes nothing at three of the four sizes. At 4,000 sessions Laya's method is somewhat better, 0.108 against 0.152. My guess is that its random changes slow the memorising down a little. I did not test that, and 0.108 is still ten times the best achievable.

One point if right never becomes calibrated. That model is 99 % confident at every size, and its error stays at 0.15 however much data it sees. Its accuracy is as good as the others', 84.2 %. It knows the answer as well as they do and has learned to overclaim, as the figure in the hypothesis predicted.

The first prediction holds. A reward that pays for honesty is needed. Laya's method is one way to get it, and ordinary cross-entropy is another.

On sessions unlike the training data

This is the best case for every model, 64,000 training sessions. Each cell shows accuracy, then confidence. When the two numbers are close, the model is calibrated.

situationcross-entropyLaya's methodone point if rightbest possible accuracy
like training84 % / 85 %84 % / 85 %84 % / 99 %85 %
8 options78 % / 76 %78 % / 77 %77 % / 99 %78 %
12 options73 % / 71 %73 % / 70 %73 % / 98 %73 %
unreadable format26 % / 52 %27 % / 50 %26 % / 89 %25 %
90 % benign86 % / 69 %86 % / 70 %86 % / 99 %98 %
Accuracy and confidence in five situations for the three training methods; they coincide like training and with more options, and separate on the unreadable format and under 90 percent benign traffic
The filled dot is accuracy, the ring is confidence. Where they sit together the model is calibrated; the further apart, the less its confidence means.

More options did no harm. I expected this to break calibration, and it did not. With 8 and 12 options, cross-entropy and Laya's method stay within three points of the truth. This design treats the options as an unordered list, so a longer list is nothing new to it.

Input it cannot read breaks it completely. On the unreadable format, accuracy drops to 26 %, which is what guessing gives, and confidence is 52 %. The honest answer was 25 %. The reward taught the model to be honest about sessions like the ones it saw. It has no way of noticing that these are different. The model trained with one point if right is 89 % confident on the same input.

A different mix of traffic breaks it the other way. When 90 % of sessions are benign, a model that knew this would be right 98 % of the time. These models are right 86 % of the time and too unsure, at 69 %. They learned from data where every class was equally common, so they keep suspecting attacks that are not there.

The second prediction holds, with one correction. Not every change matters. The ones that do are the ones that change what the evidence means.

What this does to an automatic rule

Take the rule “handle the session automatically when confidence is 90 % or more, otherwise pass it to a person”. The 90 % is the threshold. For the model trained with cross-entropy:

situationhandled automaticallyof those, right
like training, 64,000 training sessions62 %98.6 %
like training, 1,000 training sessions90 %81 %
unreadable format3 %40 %
90 % benign9 %84 %

The first row is the promise kept: an ideal model would handle 62 % at 98.7 %, and this one matches it. The second row is the same design and the same reward with less data. It handles nine sessions in ten on its own and gets one in five of them wrong. In the last row the rule fails quietly in the opposite direction. It passes 91 % of an almost entirely harmless queue to people, where an ideal model would have handled 95 % of it automatically.

Can it be repaired afterwards?

The usual repair uses the temperature from the diagram. Take some examples with known answers that the model was not trained on, try different temperatures, and keep the one that makes confidence match accuracy. It is one number, and it cannot change which option the model picks.

The same five raw scores at temperatures 0.5, 1 and 2: the top probability is 0.78, 0.52 and 0.35 and the order of options does not change
The same raw scores at three temperatures. The winner stays the winner; only how sure the model sounds changes.

For each model and each situation I chose the temperature on 5,000 separate sessions from that same situation, then measured again on the test sessions.

casecalibration error beforeaftertemperature chosen
cross-entropy, 1,000 training sessions, like training0.1980.0177.8
one point if right, 64,000 training sessions, like training0.1480.02012.4
cross-entropy, 64,000 training sessions, unreadable format0.2590.03112.6
cross-entropy, 64,000 training sessions, 90 % benign0.1950.0610.6

One number repairs both over-confident models almost completely, including the one trained with the wrong reward. That model was ranking the options correctly all along and only its scale was off. On the unreadable format the repair turns the temperature up until every answer is close to 25 %, which is honest and of no use. For the benign-heavy traffic it helps least, and accuracy stays at 86 % where 98 % was possible. A temperature cannot tell the model that most traffic is harmless.

In every row, the repair needed examples with known answers from the very situation being repaired.

The same pattern in the real model

I did not run Laya itself. Its repository publishes its own test results, and they show the same pattern.

My unreadable-format test has a direct counterpart. Laya comes in an English version and a multilingual one, and the project tested both on the same 20-option question in 51 languages, 100 cases each.

Confidence against accuracy for 51 languages and two versions of Laya; every point lies below the diagonal of perfect calibration
Laya's own measurement, re-plotted from its result files. On the diagonal a model is calibrated; every dot is below it, so the model is more sure than it is right.

On Khmer, the English version gets 0 of 100 right while being 71 % sure on average. This is why Laya ships with a language check that runs before the model and sends non-English text to the multilingual version. The safeguard had to sit outside the model, because the model's own confidence gave no warning.

The repair has a counterpart too. Choosing a new temperature on separate examples, across 49 test sets, takes the English version's average calibration error from 0.466 to 0.081.

Calibration error on 49 test sets for two versions of Laya: averages of 0.466 and 0.314 as released, 0.081 and 0.106 after choosing a new temperature
Laya's own measurement, re-plotted from its result files. Each dot is one test set; the tick marks the average.

A model whose error falls by four fifths when one number is changed was not made calibrated by its training. It behaves like my models trained on too little data: the ranking is sound and the scale is wrong.

One result differs. My model stayed calibrated with more options, and Laya's does not: a report in its repository shows a 0.85 threshold working with 3 options and failing with 20. The same report finds the cause in the temperature that Laya is released with for long option lists, 0.10, which makes every answer sound about ten times surer. So this is the repair step going wrong, not the design of the model.

It is to the project's credit that all of this is in its own repository, much of it under a heading called “Honest limits”.

Conclusion

The claim was that the training method is what makes a decision model's confidence trustworthy. In a world where the right confidence is known, the result was narrower. A reward that pays for honesty is needed, and without one the model overclaims however much data it sees. But Laya's method and plain cross-entropy were indistinguishable. What decided whether either was calibrated was how much data it had, and whether the input resembled that data.

So the confidence of a decision model is a raw signal. It ranks answers well. It becomes a probability you can act on only after it has been checked, and usually adjusted, on examples from the place where it will be used. That checking is the job of whoever puts the model to work.

An alert passes a format check, a decision model answers attack type, severity and exfiltration questions in one run, and a confidence rule sends the result to close as benign, contain automatically, or escalate to an analyst
Where such a model sits in alert triage, with the two things the experiment says it needs: a check before it and a feedback loop after it.

If I were putting one in front of a security team, I would:

Limitations

This is a toy. Sessions are a handful of independent events from a program I wrote, and my model is several thousand times smaller than Laya. The toy can show whether a reward produces calibration when everything else is kept the same. It cannot say how large these effects are in the real model reading real text.

My version of Laya's method follows the author's written description, because the code that trained the released model is not public. The fine-tuning code that is public uses different settings and, notably, adds ordinary cross-entropy to the reward. If anything that makes the two methods more alike than I made them.

All three rewards used the same training settings, chosen once and not tuned for each. With a fixed number of steps, the small training sets are seen many times over. Stopping training earlier would have reduced the over-confidence at 1,000 and 4,000 sessions, and it would have done so for every reward.

My unreadable format is harsher than a real unknown language, where some characters and word pieces are shared. Laya's numbers suggest the real case is no kinder: 0 % on Khmer at 71 % confidence.

The Laya figures are the project's own measurements, taken from its repository on 1 October 2026 at version 0.3.22. Some samples are small, 100 cases per language, and the project changes quickly. I have not run the real model, and that is the obvious next step.

Run it yourself

The quickest way is the notebook. Open it in Colab and it runs in your browser, with nothing to install. It shows one session with its exact probabilities, trains the model in the three ways in a short run of about a minute, and draws the two main charts from the saved results of the full run. All the code and the results are in the repository on GitHub.

To run the full experiment on your own machine:

The experiment needs PyTorch and NumPy and runs on an ordinary processor; the full set of runs took about 45 minutes on an M1 laptop. The figure script needs only Python.

pip install torch numpy
python alert_triage.py smoke     # under a minute, checks the setup
python alert_triage.py run       # all 36 runs -> results.json
python alert_triage.py example   # the worked session -> example.json
python make_figs.py              # the figures

The code is here: alert_triage.py and make_figs.py, with the raw results. The two Laya result files that the figure script reads, the 51-language test and the benchmark results, are unchanged copies from its repository, which is published under the Apache 2.0 licence.

Two things worth changing: SIGNAL, which sets how often a session shows its class's typical events and therefore how ambiguous the world is; and the share of benign traffic in the benign90 situation, to see how quickly the automatic rule degrades.

Sources

Back to writing