Files
Maven/docs/evals/2026-08-08-clarify-head-four-head.md
T

5.7 KiB

A clarify head, and a confidence that is not a hardcode

Measured 2026-08-08 on workpc, the same day and the same fixtures as 2026-08-08-routing-heads-two-head.md and 2026-08-08-slot-head-three-head.md. New script gen_clarify.py, new fixture eval_fixture_clarify.jsonl.

A softmax has no clarify class

That sentence closed the two-head measurement. It is why the head's fixture was 88 cases and not 96. The eight want_clarify cases sat outside every number measured, and the head had no way to produce the answer they wanted.

A fourth head is the answer. Clarify is not a value of intent. It is a second question asked of the same pooled vector: can Maven act on this at all.

The corpus had one class

Every row in train_heads_slots.jsonl was generated FOR an intent or a destination. So every row is answerable by construction. A head trained on that alone sees one class and learns to say yes.

gen_clarify.py makes the other class. Five shapes, ten topics. The shapes are the gate's own reasons in gateLLMDecision plus the two the fixture carries: bare noun, bare verb, demonstrative, deictic time, dangling reference.

The agreement filter that worked for destination cannot work here. routeGrammar has no clarify value. So the router always names an intent, and any generated line always agrees with itself. The second pass is a judge instead. Gemma is asked, without seeing the label, whether Maven would have to ask a question back.

The first judge was worthless and the second was measured

The first judge said "needs clarify" on 24 of 40 plainly answerable corpus rows. It flagged запиши что я пообедал and Покажи расписание поездов на вечер. It was judging against a generic assistant, one that asks "where?" about lunch. Maven writes that note.

Rewriting it to state what she can already do took false positives to 16 of 60. It also catches all eight fixture clarifies. So the judge discriminates.

On the generated pile it removed 7 of 306, a 97.7% keep rate. That is not the judge failing. The generator is aimed at underspecified lines, so there is little for a filter to catch. The 27% false-positive rate is the number to quote, and it is label noise on the positive class.

Both passes are gemma-4-12b. Generation and judging. So the corpus is gemma's opinion of what is underspecified, and the head distills that opinion. What keeps it honest is the fixture. Those eight cases were written by the owner and gemma never saw them.

299 rows kept, against 3604 answerable. The positive class carries intent: null, so it costs the intent head nothing.

Result

Three seeds, 24 epochs, epoch still chosen on the intent dev slice.

two heads three heads four heads
intent mean 93.6% 92.8% 91.7%
destination mean 80.8% 82.8% 79.8%
slot span F1 mean 72.4% 68.3%
clarify caught 7.0 of 8
false clarifies 2.3 of 88

The fourth head is not free the way the third was. Intent, destination and slot F1 all move down. The drop is one to four points, and the seed spread is wide enough to contain it. Seed 2 scores intent 94.3% and destination 84.8%, both above every three-head seed. Read the drop as unproven rather than as absent.

Accuracy is the wrong number for this head and is reported for completeness at 95.8% to 96.9%. Eight of ninety-six cases are positive, so a head that never asks scores 91.7%. Recall on those eight is the number.

Compare it to what ships. The cascade today misses 1 clarify and produces 2 false ones. The head catches 7 of 8 and produces 2.3 false ones. That is parity, from a 118M encoder with no rules in front of it.

The saved checkpoint is seed 2 at epoch 10. Intent 94.3%, destination 28/33, slot F1 73.6%, clarify 7 of 8 with 3 false. heads.pt carries four state dicts.

What it gets wrong is consistent across seeds

поужинал is a false clarify on all three seeds. That utterance is already recorded as a real defect. thinSingleToken was narrowed on 2026-08-01 to spare a token carrying a Russian verb ending. One word is routinely a whole sentence in Russian. The head relearned the mistake the rule was narrowed to fix.

что дальше? is a false clarify on two seeds. That one is a disagreement rather than an error. The utterance is underspecified, and V-498 decided stage 0 claims it for the calendar on purpose.

ну это is missed on two seeds. amb-003 is the shortest case in the fixture and the generated demonstratives are longer.

Confidence

Confidence: 1.0 was a hardcode in llmrouter.go, so a correct low confidence could not exist. Max softmax over the intent head is the replacement. It is only worth reading if it is lower where the head is wrong.

It is. Mean 0.851 where the head is right against 0.604 where it is wrong. It ranks a right case above a wrong one in 83.4% of pairs.

So there are two signals now and they are not the same signal. Confidence says the head is unsure which intent this is. The clarify head says the utterance does not carry enough to act on. A confident wrong route and an honest "I cannot tell" are different failures, and one number cannot report both.

What this does not measure

The same gap as every head run. Nothing of this runs in Go. Four heads instead of three does not change that.

There is no threshold. Both signals are reported as raw numbers. Turning either into a gate needs a decision about where to cut, and that trades false clarifies against wrong acts. The fixture has 8 positives, which is too few to fit a threshold on.

The 299 generated rows have no held-out slice of their own. Clarify is scored on the fixture alone.