router/semantic: slice 23 corpus fast-path reconciliation — DeriveFastPath over the real router replaces the regex mirror, factory/merge validated, corpus rebuilt (dataset_hash unchanged), drift diagnostic and rerun tooling
This commit is contained in:
@@ -15,7 +15,6 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -1089,85 +1088,11 @@ func generatorQuestion(seed semantic.SemanticSeed) []semantic.GeneratedSurface {
|
||||
}
|
||||
|
||||
// ─── Fast-path classifier ────────────────────────────────────────────────────
|
||||
// Simplified pattern matcher that mirrors stage-0 grammar outcomes.
|
||||
|
||||
var (
|
||||
reminderVerbRe = regexp.MustCompile(`(?i)^\s*(напомни|напомните|напомнить|напоминай|разбуди|разбудите|разбудить|буди|remind|wake)\b`)
|
||||
timeQueryRe = regexp.MustCompile(`(?i)^\s*(сколько\s+сейчас\s+времени|который\s+час|какое\s+число|какой\s+день|what\s+time|what's\s+the\s+date)\b`)
|
||||
captureVerbRe = regexp.MustCompile(`(?i)^\s*(запиши|запомни|отметь|заметь|добавь|сохрани|занеси|внеси|note|remember|log|save|add)\b`)
|
||||
praxisItemRe = regexp.MustCompile(`(?i)\b(item[_-][a-z0-9_-]+)`)
|
||||
quietOnRe = regexp.MustCompile(`(?i)(тихий\s+режим|режим\s+тишина|тише|потише|quiet\s+(mode|on))`)
|
||||
quietOffRe = regexp.MustCompile(`(?i)(хватит\s+тихого|громкий\s+режим|выключи\s+тихий|quiet\s+(off|end))`)
|
||||
taskDoneRe = regexp.MustCompile(`(?i)^\s*(закрой\s+задачу|заверши\s+задачу|close\s+the\s+task|finish\s+the\s+task)\b`)
|
||||
taskDropRe = regexp.MustCompile(`(?i)^\s*(убери\s+задачу|удали\s+задачу|отмени\s+задачу|drop\s+the\s+task|remove\s+the\s+task)\b`)
|
||||
)
|
||||
|
||||
// tool aliases → fast-path matchers (subset of what DefaultActMatcher would match)
|
||||
var toolAliasRe = []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?i)^\s*(перезапусти|перезагрузи|рестарт)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(останови|выключи)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(запусти|старт)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(перезапусти\s+контейнер|перезагрузи\s+контейнер)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(останови\s+контейнер)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(перезагрузи\s+сервер|перезагрузи\s+хост|ребут)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(покажи\s+статус|проверь\s+статус|статус)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(покажи\s+контейнеры|список\s+контейнеров|что\s+запущено)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(покажи\s+uptime|аптайм|как\s+работает\s+сервер)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(покажи\s+диск|сколько\s+места\s+на\s+диске)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(покажи\s+память|свободная\s+память)\b`),
|
||||
regexp.MustCompile(`(?i)^\s*(покажи\s+логи|логи|лог)\b`),
|
||||
}
|
||||
|
||||
// praxis lifecycle verbs (bare, without item reference → residual action)
|
||||
var praxisLifecycleRe = regexp.MustCompile(`(?i)^\s*(закрой|закрыть|resolve|close|принято|принять|acknowledge|ack|игнорируй|игнорировать|пропусти|ignore|skip|закрепи|закрепить|pin)\b`)
|
||||
var praxisAttentionRe = regexp.MustCompile(`(?i)^\s*(что\s+требует\s+внимания|что\s+нового\s+по\s+(задачам|проектам|сервисам)|needs\s+attention)\b`)
|
||||
var praxisChangesRe = regexp.MustCompile(`(?i)^\s*(что\s+изменилось|какие\s+изменения|changed|changes)\b`)
|
||||
var praxisEntityRe = regexp.MustCompile(`(?i)^\s*(статус|status|как\s+дела\s+у|how\s+is)\s+`)
|
||||
|
||||
// classifyFastPath determines whether a surface would be handled by stage-0.
|
||||
func classifyFastPath(text string) bool {
|
||||
t := strings.TrimSpace(text)
|
||||
|
||||
// Reminder verbs → always fast-path
|
||||
if reminderVerbRe.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
// Time/date queries → fast-path
|
||||
if timeQueryRe.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
// Task-status commands → fast-path
|
||||
if taskDoneRe.MatchString(t) || taskDropRe.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
// Tool aliases → fast-path (only for verbs alone, not when combined with objects in ways the matcher wouldn't handle)
|
||||
for _, re := range toolAliasRe {
|
||||
if re.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Praxis lifecycle with item reference → fast-path
|
||||
if praxisLifecycleRe.MatchString(t) && praxisItemRe.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
// Praxis attention/changes → fast-path
|
||||
if praxisAttentionRe.MatchString(t) || praxisChangesRe.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
// Praxis entity attention → fast-path
|
||||
if praxisEntityRe.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
// Quiet mode → fast-path (resolved pre-route)
|
||||
if quietOnRe.MatchString(t) || quietOffRe.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
// Capture verbs → some are fast-path (note capture)
|
||||
if captureVerbRe.MatchString(t) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
// Fast-path metadata is derived from the real router, not a regex mirror:
|
||||
// DeriveFastPath runs the production TryFastPath over the stage-0 grammars
|
||||
// with the experiment's act allowlist (see internal/router/semantic/fastpath.go).
|
||||
// A hand-maintained pattern list drifted from the grammars and labelled 185
|
||||
// residual rows as fast (docs/evals/2026-09-08-slice22-*); it is removed.
|
||||
|
||||
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -1241,7 +1166,7 @@ func buildCorpus(seeds []semantic.SemanticSeed) []semantic.RouteExample {
|
||||
exampleCounter++
|
||||
srcID := fmt.Sprintf("%s-%03d", seed.ID, exampleCounter)
|
||||
|
||||
fp := classifyFastPath(surf.Text)
|
||||
fp := semantic.DeriveFastPath(surf.Text).Matched
|
||||
isResidual := !fp
|
||||
|
||||
tags := append([]string{}, seed.Tags...)
|
||||
|
||||
Reference in New Issue
Block a user