3d8224fb04
"сеть какая-то медленная" and "интернет не работает" were written as `self` rows at confidence 1.00. Recall reads a self row back later as if it were still true, and that is the class of row that outranked live search in #470 — so a slow afternoon becomes a standing belief about his network. IsTransientComplaint is the same shape as IsQuestionShaped: deterministic, offline, and off by default in the two cases where losing a real capture would cost more than keeping a complaint. An explicit "запомни ..." wins, because he asked. A first-person marker wins, because "я сломал руку" is durable and the test is meant for sentences about things. She answers the turn as chat instead of storing it. actionChat now has the same nil-phraser floor the other model callers have. The second defect filed here — a reply body of literally "{" — was closed by the errBrokenJSON path in V-397 and needs nothing further.
80 lines
3.0 KiB
Go
80 lines
3.0 KiB
Go
package router
|
|
|
|
import "strings"
|
|
|
|
// transientStems — the states a thing is in for an afternoon. Compared as
|
|
// prefixes because Russian inflects the ending: "медленн" covers "медленная",
|
|
// "медленный" and "медленно" without listing them.
|
|
var transientStems = []string{
|
|
"медленн", "тормоз", "лаг", "завис", "виснет", "глюч", "барахл",
|
|
"отвал", "падает", "упал", "сдох", "греется", "перегре",
|
|
"slow", "laggy", "stuck", "frozen", "flaky", "broken", "down",
|
|
}
|
|
|
|
// brokenVerbs — what "не ..." is denying when the sentence is a complaint.
|
|
// "не работает", "не грузит", "не открывается". Prefixes again.
|
|
var brokenVerbs = []string{
|
|
"работ", "пашет", "груз", "открыва", "включа", "коннект", "подключ",
|
|
"work", "load", "connect", "respond",
|
|
}
|
|
|
|
// selfMarkers — the words that make a sentence about him rather than about a
|
|
// thing. Their presence turns the test off, because losing a fact he meant to
|
|
// store is worse than keeping a complaint: "я сломал руку" is durable, and
|
|
// "интернет не работает" is not.
|
|
var selfMarkers = []string{"я", "мне", "меня", "мной", "i", "me", "my"}
|
|
|
|
// IsTransientComplaint reports whether text observes a passing state of some
|
|
// thing rather than recording a fact.
|
|
//
|
|
// It exists because "сеть какая-то медленная" and "интернет не работает" were
|
|
// written to the fact store as `self` rows at confidence 1.00 (Vikunja #481),
|
|
// where recall reads them back later as if they were still true. A complaint
|
|
// describes a moment; the fact store describes him.
|
|
//
|
|
// Deterministic, offline, and shaped exactly like IsQuestionShaped: an
|
|
// explicit capture verb wins over everything, because "запомни что интернет
|
|
// не работает" is an instruction and not a passing remark. A first-person
|
|
// marker also turns it off — the test is meant to catch a sentence about a
|
|
// thing, and it errs toward storing.
|
|
func IsTransientComplaint(text string) bool {
|
|
t := strings.TrimSpace(text)
|
|
if t == "" {
|
|
return false
|
|
}
|
|
toks := planTokens(strings.ToLower(t))
|
|
for _, v := range captureVerbs {
|
|
if hasTok(toks, v) {
|
|
return false
|
|
}
|
|
}
|
|
for _, m := range selfMarkers {
|
|
if hasTok(toks, m) {
|
|
return false
|
|
}
|
|
}
|
|
for _, tok := range toks {
|
|
for _, stem := range transientStems {
|
|
if strings.HasPrefix(tok, stem) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
// "не" plus a verb of working, in either order of the two tokens that
|
|
// follow it — "не работает" and "не очень работает" both deny the same
|
|
// thing.
|
|
for i, tok := range toks {
|
|
if tok != "не" && tok != "not" && tok != "isn" {
|
|
continue
|
|
}
|
|
for j := i + 1; j < len(toks) && j <= i+2; j++ {
|
|
for _, v := range brokenVerbs {
|
|
if strings.HasPrefix(toks[j], v) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|