Files
Maven/internal/router/semantic/helpers_test.go
T
claude 56051e58c0 router/semantic: baseline types, test helpers, leakage test (slice 13)
Baseline types: LegacyRouter interface (satisfied by *router.Router),
LegacyCase with PrerouteConsumed flag for command-prohibition detection,
LegacyReport with fast-path/residual/router-residual/pre-route breakdowns,
ContrastFamilyReport for per-transform-family scoring.

Test helpers: buildSeededClassifier (hash embedder seeded from
models/seeds/*.txt), actVerbList, seed file loading.

TestContrastFamiliesShareSplitGroup verifies that all contrastive
variants of one base seed share exactly one SplitGroup, preventing
train/eval leakage across the contrast family split.
2026-09-07 02:08:40 +04:00

88 lines
2.0 KiB
Go

package semantic
import (
"bufio"
"context"
"os"
"path/filepath"
"sort"
"strings"
"testing"
"github.com/kami/maven/internal/router"
)
const seedDir = "../../../models/seeds"
var seedIntents = []router.Intent{
router.IntentAct, router.IntentReminder, router.IntentFact,
router.IntentNote, router.IntentQuery, router.IntentChat, router.IntentSystem,
}
func actVerbList() []string {
return []string{
"перезапусти", "перезагрузи", "выключи", "включи", "останови", "запусти",
"закрой", "открой", "сделай", "поставь",
"restart", "reboot", "stop", "start", "turn off", "turn on", "open", "close",
}
}
func buildSeededClassifier(t *testing.T, emb router.Embedder) *router.Classifier {
t.Helper()
cls := router.NewClassifier(emb)
ctx := context.Background()
seeds := seedsWithIntent(t)
texts := make([]string, 0, len(seeds))
for text := range seeds {
texts = append(texts, text)
}
sort.Strings(texts)
for _, text := range texts {
if err := cls.AddExample(ctx, seeds[text], text); err != nil {
t.Fatalf("seed %q: %v", text, err)
}
}
return cls
}
func seedsWithIntent(t *testing.T) map[string]router.Intent {
t.Helper()
files := readSeedFiles(t)
out := map[string]router.Intent{}
for _, intent := range seedIntents {
for _, l := range files[intent] {
if _, dup := out[l]; dup {
continue
}
out[l] = intent
}
}
return out
}
func readSeedFiles(t *testing.T) map[router.Intent][]string {
t.Helper()
out := map[router.Intent][]string{}
for _, intent := range seedIntents {
path := filepath.Join(seedDir, string(intent)+".txt")
fh, err := os.Open(path)
if err != nil {
t.Fatalf("open %s: %v", path, err)
}
sc := bufio.NewScanner(fh)
for sc.Scan() {
line := strings.TrimSpace(sc.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
out[intent] = append(out[intent], line)
}
err = sc.Err()
fh.Close()
if err != nil {
t.Fatalf("read %s: %v", path, err)
}
}
return out
}