package router import ( "strings" "github.com/kami/maven/internal/lexicon" ) // AmbiguousFragmentGrammar refuses an utterance which only points at context // that is not present. The statistical heads usually catch these, but a missed // refusal is the dangerous direction: "ну это" must not become a confident // chat answer, and "сделай это" must not become an act. // // This is a structural whole-utterance rule. Demonstratives inside a sentence // remain ordinary language: "это резервный ключ" names a subject and does not // match. Only filler plus unresolved-reference words can reach this lane. func AmbiguousFragmentGrammar() Grammar { return Grammar{Name: "ambiguous-fragment", Decide: ambiguousFragmentDecision} } func ambiguousFragmentDecision(utterance string) (Decision, bool) { if !thinReferenceFragment(utterance) { return Decision{}, false } return Decision{ Stage: 3, Intent: IntentChat, Confidence: 0, Clarify: true, }, true } // thinReferenceFragment reports whether every content word merely points at // something omitted. It requires at least one reference word so a politeness // utterance such as "пожалуйста" stays social rather than becoming a refusal. func thinReferenceFragment(utterance string) bool { tokens := planTokens(strings.TrimSpace(utterance)) if len(tokens) == 0 { return false } references := lexicon.UnresolvedReferences() hasReference := false for _, token := range tokens { if lexicon.IsFillerParticle(token) { continue } if hasExactWord(references, token) { hasReference = true continue } return false } return hasReference } func hasExactWord(words []string, token string) bool { for _, word := range words { if token == word { return true } } return false }