87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/kami/maven/internal/router"
|
|
"github.com/kami/maven/internal/router/semantic"
|
|
)
|
|
|
|
// Seed loading replicated from cmd/mavend/voicewire.go (seedClassifier) and
|
|
// internal/router/semantic/helpers_test.go, which build the same classifier
|
|
// from models/seeds/<intent>.txt. The daemon and the eval fixture must agree
|
|
// on the seeds; so must a measurement.
|
|
const seedDir = "models/seeds"
|
|
|
|
var seedIntents = []router.Intent{
|
|
router.IntentAct, router.IntentReminder, router.IntentFact,
|
|
router.IntentNote, router.IntentQuery, router.IntentChat, router.IntentSystem,
|
|
}
|
|
|
|
// buildMinimalRouter reproduces internal/router/semantic/buildMinimalRouter:
|
|
// the daemon's grammar set, a hash-embedder classifier seeded from
|
|
// models/seeds, and the deployed 0.55 threshold. Deterministic and
|
|
// reproducible. The ONNX embedder and the routing heads score elsewhere;
|
|
// this is the floor the eval fixture reports as the legacy baseline.
|
|
func buildMinimalRouter() *router.Router {
|
|
acts := router.DefaultActMatcher{Fns: semantic.ExperimentActVerbs()}
|
|
cls := router.NewClassifier(router.NewHashEmbedder(1024))
|
|
seedClassifier(cls)
|
|
return router.New(router.Config{
|
|
Grammars: router.StageZeroGrammars(acts),
|
|
Classifier: cls,
|
|
Extractor: router.Extractor{
|
|
Time: router.StubDateTimeParser{},
|
|
Acts: acts,
|
|
Facts: router.DefaultFactParser{},
|
|
},
|
|
Threshold: 0.55,
|
|
})
|
|
}
|
|
|
|
func seedClassifier(c *router.Classifier) {
|
|
// Walk up to find models/seeds like the daemon's seedPath, so the program
|
|
// can run from any depth of the repo tree.
|
|
dir := seedDir
|
|
for i := 0; i < 5; i++ {
|
|
if st, err := os.Stat(dir); err == nil && st.IsDir() {
|
|
break
|
|
}
|
|
dir = filepath.Join("..", dir)
|
|
}
|
|
ctx := context.Background()
|
|
total := 0
|
|
for _, intent := range seedIntents {
|
|
path := filepath.Join(dir, string(intent)+".txt")
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
log.Printf("legacy: open seed %s: %v", path, err)
|
|
continue
|
|
}
|
|
sc := bufio.NewScanner(f)
|
|
lines := []string{}
|
|
for sc.Scan() {
|
|
line := strings.TrimSpace(sc.Text())
|
|
if line == "" || strings.HasPrefix(line, "#") {
|
|
continue
|
|
}
|
|
lines = append(lines, line)
|
|
}
|
|
f.Close()
|
|
sort.Strings(lines)
|
|
for _, line := range lines {
|
|
if err := c.AddExample(ctx, intent, line); err != nil {
|
|
log.Printf("legacy: seed %s %q: %v", intent, line, err)
|
|
continue
|
|
}
|
|
total++
|
|
}
|
|
}
|
|
log.Printf("legacy: loaded %d seed examples from %s", total, dir)
|
|
} |