vojo/apps/ai-bot/router_test.go

81 lines
3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import "testing"
// TestRouteLayer0 is the heuristic golden set (RU+EN). The critical property is the
// safe floor: anything substantive must land on grok_direct, and a long message that
// merely starts with a greeting must NOT be trivial (no leaking real questions to the
// cheap model, §8.6).
func TestRouteLayer0(t *testing.T) {
cases := []struct {
body string
want string
}{
// trivial: short greetings/acks and bare arithmetic
{"привет", routeTrivial},
{"Привет!", routeTrivial},
{"спасибо", routeTrivial},
{"спс", routeTrivial},
{"ок", routeTrivial},
{"hi", routeTrivial},
{"hello", routeTrivial},
{"thanks", routeTrivial},
{"thank you", routeTrivial},
{"ok", routeTrivial},
{"2+2", routeTrivial},
{"100 * 50", routeTrivial},
{"12 / 4 - 1", routeTrivial},
// web: freshness signals
{"какие новости сегодня?", routeWebThenGrok},
{"что сейчас происходит в мире", routeWebThenGrok},
{"курс доллара сегодня", routeWebThenGrok},
{"what's the weather today", routeWebThenGrok},
{"latest news on AI", routeWebThenGrok},
{"current bitcoin price", routeWebThenGrok},
// grok_direct: substantive (the safe floor)
{"посоветуй фильм на вечер", routeGrokDirect},
{"explain how TCP works", routeGrokDirect},
{"расскажи историю римской империи", routeGrokDirect},
{"спасибо, а теперь подробно объясни квантовую запутанность", routeGrokDirect}, // starts w/ ack but long
{"hi, can you help me debug this Go program?", routeGrokDirect}, // starts w/ hi but a real ask
{"напиши функцию сортировки на python", routeGrokDirect},
}
for _, c := range cases {
if got := routeLayer0(c.body).Route; got != c.want {
t.Errorf("routeLayer0(%q) = %q, want %q", c.body, got, c.want)
}
}
}
func TestNormalizeRoute(t *testing.T) {
cases := map[string]string{
"trivial": routeTrivial, "web": routeWebThenGrok, "reason": routeReason,
"normal": routeGrokDirect, "garbage": routeGrokDirect, "": routeGrokDirect,
}
for in, want := range cases {
if got := normalizeRoute(in); got != want {
t.Errorf("normalizeRoute(%q) = %q, want %q", in, got, want)
}
}
}
func TestExtractJSON(t *testing.T) {
if got := extractJSON("prefix {\"route\":\"web\"} suffix"); got != `{"route":"web"}` {
t.Errorf("extractJSON = %q", got)
}
if got := extractJSON("no json here"); got != "" {
t.Errorf("extractJSON(no json) = %q, want empty", got)
}
}
func TestContainsTrigger(t *testing.T) {
if !containsTrigger("ну подумай глубже про это", "подумай глубже") {
t.Error("should match trigger phrase mid-sentence")
}
if containsTrigger("just a normal question", "подумай глубже") {
t.Error("must not match when phrase absent")
}
if containsTrigger("anything", "") {
t.Error("empty trigger must never match")
}
}