an alarm verb reaches stage 0, and the reminder grammar reads the lexicon (V-627)
reminder_verbs held five words and none named an alarm, and ReminderGrammar did not read the set anyway — it carried the literal напомни|remind me. So no part of the cascade recognised разбуди, and the three alarm cases in the fixture went to fact and act at over 0.89. The lexicon addition alone moved nothing, measured at 66/91. Every consumer reads the set after a reminder route already exists. Building the grammar's alternation from the set is what scored: 66/91 to 69/91, three cases gained, none lost, and each alarm now carries its time slot. Longest-first ordering in the alternation is load-bearing. Go's regexp alternation is leftmost-first, so напомнить after напомни would never match. Found while training the V-546 intent head, where the same three cases went to system. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117tgnmbgZpHVV3XSNw8Qua
This commit is contained in:
@@ -173,10 +173,11 @@
|
||||
]
|
||||
},
|
||||
"reminder_verbs": {
|
||||
"note": "The imperatives that mean \"remind me\", in the forms he speaks. The same kind of set as capture_verbs and decided the same way: it is her vocabulary, not a discovery about Russian (Vikunja #530).",
|
||||
"note": "The imperatives that mean \"remind me\", in the forms he speaks. The same kind of set as capture_verbs and decided the same way: it is her vocabulary, not a discovery about Russian (Vikunja #530). The alarm verbs joined them in V-627. \"разбуди меня в 6:30\" is a reminder that fires at the hour he gets up, and the set knew no form of it, so an alarm reached IntentReminder only by resembling one to the embedder.",
|
||||
"words": [
|
||||
"напомни", "напомните", "напомнить", "напоминай",
|
||||
"remind"
|
||||
"разбуди", "разбудите", "разбудить", "буди",
|
||||
"remind", "wake"
|
||||
]
|
||||
},
|
||||
"half_hour": {
|
||||
|
||||
@@ -2,6 +2,7 @@ package router
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
@@ -94,10 +95,41 @@ func DefaultGrammars(actMatcher ActMatcher) []Grammar {
|
||||
// stage-0 decision too (fillMatchedSlots in router.go). Before that it did not,
|
||||
// so "напомни в 11:00 позвонить маме" reached the daemon with HasTime false and
|
||||
// was asked "Когда?" about an hour he had just said.
|
||||
//
|
||||
// The verb alternation is built from lexicon.ReminderVerbs rather than written
|
||||
// out (V-627). The literal here knew "напомни" and "remind me" and nothing
|
||||
// else, so "разбуди меня в 6:30" never reached stage 0 — and it does not reach
|
||||
// IntentReminder further down either, where the classifier calls it fact at
|
||||
// 0.918. An alarm is a reminder that fires at the hour he gets up, and the
|
||||
// verb that names one is her vocabulary, so it belongs in the lexicon with the
|
||||
// rest of it.
|
||||
//
|
||||
// Longest-first ordering matters: Go's regexp alternation is leftmost-first,
|
||||
// not longest-match, so "напомнить" listed after "напомни" would never match.
|
||||
var reminderVerbPattern = regexp.MustCompile(
|
||||
`(?i)^\s*(?:` + longestFirstAlternation(lexicon.ReminderVerbs()) +
|
||||
`)\s*(?:мне|меня|me)?[\s,:]+(.+)$`)
|
||||
|
||||
// longestFirstAlternation joins a word set into a regexp alternation, longest
|
||||
// alternative first, with every member escaped.
|
||||
func longestFirstAlternation(set []string) string {
|
||||
out := make([]string, 0, len(set))
|
||||
for _, w := range set {
|
||||
out = append(out, regexp.QuoteMeta(w))
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
if len(out[i]) != len(out[j]) {
|
||||
return len(out[i]) > len(out[j])
|
||||
}
|
||||
return out[i] < out[j]
|
||||
})
|
||||
return strings.Join(out, "|")
|
||||
}
|
||||
|
||||
func ReminderGrammar() Grammar {
|
||||
return Grammar{
|
||||
Name: "reminder-wakeword",
|
||||
Pattern: regexp.MustCompile(`(?i)^\s*(?:напомни|remind me)[\s,:]+(.+)$`),
|
||||
Pattern: reminderVerbPattern,
|
||||
Build: func(m []string) (Decision, bool) {
|
||||
rest := strings.TrimSpace(m[1])
|
||||
if rest == "" {
|
||||
|
||||
Reference in New Issue
Block a user