Choice probabilities
direct readout · no decodingRead the model’s choice logits and normalize only across the options you supplied.
- total
- —
- input
- —
- output
- 1 readout
edulab
SemIf browser lab
A local model can either read probabilities for your allowed options without decoding them, or write the same kind of distribution token by token.
One forward pass over your state, question and options. The model never writes a word: we take its next-token logits for the option letters and softmax across them.
Same decision, but the model is asked to type a JSON distribution token by token. You watch every token arrive and compare the wall time of both paths on your own GPU.
| Model | Download | Authored | Perturbed | TypeSafe |
|---|---|---|---|---|
| Qwen3 0.6B | 639 MB | 44.0% | 52.8% | 40.7% |
| Published Jev | hosted | — | — | 88.3% |
Owned columns are balanced accuracy. TypeSafe is equal-case agreement on the same 102-row public subset; Jev is the published value. Browser quantization may change model accuracy.
{{ text }}
Weights come from Hugging Face and remain in your browser cache. Inputs never leave this page. First load can take a few minutes depending on network and GPU.
Both paths receive the same decision. One reads option probabilities directly; the other asks the model to write its option probabilities as JSON text.
Read the model’s choice logits and normalize only across the options you supplied.
Ask the model to estimate the same displayed-option distribution and write it as JSON. Watch every token arrive.
waiting for a run
The methods run sequentially on the same loaded model so they do not contend for one GPU. Direct runs first, then generation.
Because they measure two different things, and only one of them is a probability in the strict sense.
Direct readout takes the model's logits at the first answer position, keeps only the option letter tokens, and applies a softmax across them. That is the model's actual next-token preference between the options. It reflects what the network computes, including small residual mass on unlikely options. These are conditional probabilities over the displayed options only; they are not calibrated confidence. A typical run gives something like A 0.865, B 0.000, C 0.135.
Generation asks the model to write numbers as text. The values in the JSON are just tokens the model decided to emit, not a readout of anything internal. A 0.6B model has strong habits here: it writes round, stereotyped numbers like 0.5 / 0.4 / 0.1, or collapses to 1.0 on one key, because "1.0" is a common pattern in its training data. Verbalized probabilities are known to be poorly calibrated even for large models, and for a tiny one they are closer to a formatting reflex than an estimate.
There are also two smaller contributors:
The timing gap has a simpler cause. Direct needs one forward pass over the prompt and reads the logits. Generation needs that same pass plus one full forward pass per emitted token, run sequentially, so 30 to 40 tokens costs 2 to 3× the wall time. That ratio is what the page is designed to show. Setup, warmup and both paths are timed with performance.now(); no canned results appear.
So the honest reading of the two panels: the left one is the model's decision, the right one is the model's story about its decision.