voicewire: fix drifted seed comments, dedupe dialogue TTL (V-581)

buildRouter's third bullet described a hardcoded 6-example bootstrap
set that predates seedClassifier's file-based loader; seedClassifier's
own comment named 5 seed files where there are 7 (chat.txt and
system.txt were missing). Also named the repeated 2*time.Minute
dialogue session TTL literal as dialogueSessionTTL so the two call
sites can't drift apart.
This commit is contained in:
2026-08-06 02:05:01 +04:00
parent 0886662360
commit 0feb8d3dbd
+11 -9
View File
@@ -236,21 +236,22 @@ func wireVoice(cfg *config.Config, coreAPI ipc.CoreAPI, phr phraser.Phraser, mem
memStore = memory.NewInMemoryStore()
}
// ----- dialogue (multi-turn slot carry-over; 2-min follow-up window) -----
// ----- dialogue (multi-turn slot carry-over; dialogueSessionTTL follow-up window) -----
// Store-backed when the daemon passes a store, so a restart mid-conversation
// keeps the thread (Vikunja #363). Sessions past their TTL are dropped on
// load, never revived. Clarify's parked question stays in memory only, and
// that is a decision rather than an omission (Vikunja #385, docs/design.md):
// a restart expires it, so the thread comes back and the open question does
// not.
const dialogueSessionTTL = 2 * time.Minute
var dialogueSessions *dialogue.SessionStore
if dataStore != nil {
dialogueSessions = dialogue.NewPersistentSessionStore(2*time.Minute, dataStore)
dialogueSessions = dialogue.NewPersistentSessionStore(dialogueSessionTTL, dataStore)
if err := dialogueSessions.Load(context.Background(), time.Now()); err != nil {
log.Printf("dialogue: load saved sessions: %v", err)
}
} else {
dialogueSessions = dialogue.NewSessionStore(2 * time.Minute)
dialogueSessions = dialogue.NewSessionStore(dialogueSessionTTL)
}
clarifyStore := dialogue.NewClarifyStore(clarifyTTL)
timeParser := router.NewPythonDateParser()
@@ -376,9 +377,9 @@ func pickLLMRouter(enabled bool, c router.Completer) *router.LLMRouter {
// - The embedder is provided by wireVoice: HashEmbedder (floor) when no
// embedder config is present, or the ONNX multilingual model when
// configured — same interface, one constructor change.
// - 6 bootstrap examples covering the 5 intents + one compound-capture
// placeholder. Spec calls for ~10 per intent at production; this is the
// bootstrapping floor swapped by tuning the seed set later.
// - The classifier is floored by seedClassifier, which loads one file per
// intent from seedDir (models/seeds/<intent>.txt) — see seedClassifier
// below for the current intent list and file names.
// - Threshold is from voice.router_threshold config (default 0.55).
func buildRouter(emb router.Embedder, acts router.ActMatcher, threshold float64, llmR *router.LLMRouter) *router.Router {
cls := router.NewClassifier(emb)
@@ -461,9 +462,10 @@ func seedPath() string {
// seedClassifier floors the embedded examples so the cold-boot path
// doesn't return ErrNoIntents. Loads examples from seedDir — one file per
// intent (act.txt, reminder.txt, fact.txt, note.txt, query.txt). When the
// classifier can't decide it falls through to Clarify — the last-resort
// path asks the user to rephrase rather than guessing wrong.
// intent (act.txt, reminder.txt, fact.txt, note.txt, query.txt, chat.txt,
// system.txt). When the classifier can't decide it falls through to
// Clarify — the last-resort path asks the user to rephrase rather than
// guessing wrong.
func seedClassifier(c *router.Classifier) {
intents := []router.Intent{
router.IntentAct,