Preserve context across conversation intents (V-542)

Owner explicitly requested direct commits to master; bypass the branch-only hook.
This commit is contained in:
2026-08-13 02:14:46 +04:00
parent a0e6643465
commit da9114b623
15 changed files with 499 additions and 56 deletions
+7 -2
View File
@@ -5,6 +5,7 @@ import (
"strconv"
"strings"
"time"
"unicode"
"github.com/kami/maven/internal/lexicon"
"github.com/kami/maven/internal/morph"
@@ -507,8 +508,12 @@ type AnaphoraResolver struct{}
//
// Returns the matching pronoun class for cross-referencing with prior slots.
func (AnaphoraResolver) Resolve(text string) (ref string, ok bool) {
s := strings.ToLower(strings.TrimSpace(text))
toks := strings.Fields(s)
// Pronouns are a closed grammatical class. Split on punctuation instead of
// trying to encode word boundaries in a regexp: "это?" and "его," are the
// same pronouns as "это" and "его", including next to Cyrillic letters.
toks := strings.FieldsFunc(strings.ToLower(strings.TrimSpace(text)), func(r rune) bool {
return !unicode.IsLetter(r) && !unicode.IsDigit(r)
})
for _, tok := range toks {
switch tok {
case "это", "этого", "этому", "этим", "этом", "эти", "эта":
+19
View File
@@ -50,6 +50,25 @@ func TestDefaultFactParserRU(t *testing.T) {
}
}
func TestAnaphoraResolverUsesTokenBoundariesAcrossPunctuation(t *testing.T) {
r := AnaphoraResolver{}
for _, text := range []string{
"что это?",
"вернуть его, наверное",
"а он — большой?",
"расскажи о ней.",
} {
if _, ok := r.Resolve(text); !ok {
t.Errorf("Resolve(%q) missed a punctuated pronoun", text)
}
}
for _, text := range []string{"этология", "нейросеть", "онлайн"} {
if ref, ok := r.Resolve(text); ok {
t.Errorf("Resolve(%q) = %q; substring is not a pronoun token", text, ref)
}
}
}
func TestParseCalendarDate(t *testing.T) {
now := time.Date(2026, 7, 6, 14, 30, 0, 0, time.UTC)
cases := []struct {