Let the LLM router answer "unknown" when it cannot route

Chose an 8th enum value over a confidence number: the model already picks
one enum token, so it costs nothing in the grammar, while a score from a
0.8B model would be uncalibrated noise. A refusal returns "no decision"
with no error, which is the fall-through the caller already uses for a
bad parse, so the classifier and its clarify gate take the turn.

Reviewers: the prompt's counter-examples matter most — a small model will
over-use any easy escape hatch. The training workspace copy of the prompt
still needs the same edit (Vikunja #362).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGeSZxh1DCtRxmFVSYVGvJ
This commit is contained in:
kami
2026-07-31 11:35:37 +04:00
parent c47886c2bc
commit bd16ca69e5
3 changed files with 98 additions and 11 deletions
+7 -7
View File
@@ -262,13 +262,13 @@ type VoiceConfig struct {
// the model gets 50.0% of intents right against the classifier's 36.8%, but
// it costs about 800ms per turn instead of 30ms.
//
// TODO: the default stays false until two things land.
// 1. The LLM router cannot refuse. LLMRouter.Route hardcodes
// Confidence: 1.0, so the stage-3 clarify gate never fires and an
// unclear utterance becomes a confident wrong action (Vikunja #359).
// 2. Extractor.Extract never runs on an LLM decision, so acts arrive with
// no Fn and reminders with no Time.
// Turning this on today makes routing more accurate and less safe.
// TODO: the default stays false until this lands.
// Extractor.Extract never runs on an LLM decision, so acts arrive with no
// Fn and reminders with no Time. Turning this on today makes routing more
// accurate and less safe.
//
// The router can now refuse: it answers "unknown" when it cannot route, and
// the turn drops to the classifier and its clarify gate (Vikunja #359).
LLMRouter bool `json:"llm_router,omitempty"`
// QueryMinScore — the note-recall confidence gate. Top cosine below this