9e1958e7b0
router.WeekdayIndex reads the lexicon and asks the dictionary about the case. Four private lists go away: the habit declension map, the weekday block of the day-plan refusal, the weekday and part-of-day entries of the weather guard, and the stem list in ruwords.go. The stem list was the real defect. mentionsUnknownDay matched sred, pyatnits and subbot with strings.Contains, so sredi, sredstvo and sredniy all read as Wednesday and a question carrying one was answered with onlyNearDaysReply instead of a date. It matches whole tokens now. The weather guard was a third copy of three closed sets that already exist. It kept the rooms of the house, which are its own, and asks the lexicon for the weekdays, the parts of the day and the words that follow v without naming a place. Questions phrased v srede, v utra and v obshchem reached the geocoder as cities before. Full suite green under -race.
73 lines
2.8 KiB
Go
73 lines
2.8 KiB
Go
package router
|
|
|
|
import "time"
|
|
|
|
// Habit queries — "что я обычно делаю по вторникам?" (Vikunja #254).
|
|
//
|
|
// Deterministic matching, like the calendar and plan matchers: the LLM router
|
|
// classifies the intent, but WHICH weekday was asked about is a lookup, not a
|
|
// generation. A model that answers "по вторникам" for a question about Thursday
|
|
// gives a confidently wrong account of the owner's own life.
|
|
|
|
// HabitQuery — a parsed "what do I usually do" question. Weekday is set only
|
|
// when the utterance names one; otherwise the answer covers the whole week.
|
|
// Weekend is set for "по выходным", which names two days rather than one.
|
|
type HabitQuery struct {
|
|
Weekday time.Weekday
|
|
HasWeekday bool
|
|
Weekend bool
|
|
}
|
|
|
|
// habitMarkers — the words that make a question about habit rather than about
|
|
// today. Without one of these, "что я делаю" is a question about right now, and
|
|
// the recall path owns it.
|
|
var habitMarkers = []string{
|
|
"обычно", "обычное", "чаще", "постоянно", "привычки", "привычка", "привычках",
|
|
"регулярно", "каждый", "каждую", "каждое", "usually", "habits", "habit",
|
|
"typically", "normally",
|
|
}
|
|
|
|
// The weekday a habit question names comes from WeekdayIndex, not from a map
|
|
// here. This file used to keep its own declension table, which had "воскресеньях"
|
|
// and no "средах" — a list of forms is finished by whoever last thought of one,
|
|
// and a dictionary is not (V-581).
|
|
|
|
// weekendWords — the weekend as one unit. "что я обычно делаю по выходным?"
|
|
// has a habit marker and names days, but no weekday name is in it, so it used
|
|
// to fall through to the whole-week profile and answer about Tuesdays too.
|
|
var weekendWords = map[string]bool{
|
|
"выходным": true, "выходные": true, "выходных": true, "выходной": true,
|
|
"weekend": true, "weekends": true,
|
|
}
|
|
|
|
// ParseHabitQuery reports whether an utterance asks what the owner usually
|
|
// does, and on which weekday if it names one.
|
|
//
|
|
// A habit marker is required. "что я делаю в среду?" without one is a question
|
|
// about this coming Wednesday — the calendar's job — and answering it with a
|
|
// statistical average would be answering a different question.
|
|
func ParseHabitQuery(text string) (HabitQuery, bool) {
|
|
toks := planTokens(text)
|
|
marked := false
|
|
for _, t := range toks {
|
|
for _, m := range habitMarkers {
|
|
if t == m {
|
|
marked = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if !marked {
|
|
return HabitQuery{}, false
|
|
}
|
|
for _, t := range toks {
|
|
if wd, ok := WeekdayIndex(t); ok {
|
|
return HabitQuery{Weekday: wd, HasWeekday: true}, true
|
|
}
|
|
if weekendWords[t] {
|
|
return HabitQuery{Weekend: true}, true
|
|
}
|
|
}
|
|
return HabitQuery{}, true
|
|
}
|