Merge task/467 so the sweep tail can reach the three mechanisms (V-528)
attentionq.go, repair.go and internal/router/complaint.go carry the last
hand-written Russian patterns of the V-522 sweep, and they live on task/467.
internal/lexicon, internal/morph and cmd/mavend/topics.go live here. One of
the two had to move.
Four conflicts, and one of them is a real collision rather than a mechanical
one. Both branches wrote the narrative stage 0 rule. This side had
NarrativeQueryGrammars, plural, with the rest-of-day rule beside it and the
verb alternation built from the lexicon; task/467 had NarrativeQueryGrammar,
singular, which extracts the topic into Slots.Text, refuses a bare "расскажи",
and excludes the shapes that are chat ("расскажи о себе", "историю на ночь").
Resolved by keeping this side's container and this side's lexicon-built
pattern, and taking every behaviour only the other side had: the topic slot,
the empty-topic refusal, chatNarrativeTopics, and its wiring position after
TaskCaptureGrammar so "запиши" still beats "расскажи".
The rest: queryFeeds keeps task/467's conditional claim (V-474 supersedes the
unconditional one), rank.go keeps Spoken and drops pluralTasksRU because
say.CountWord is the one copy of Russian count agreement, and vendor/ was
re-vendored — the merged modules.txt claimed replaces for nexus and praxis
that neither go.mod has.
Routing fixture 58/82, unchanged from both sides.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+76
-11
@@ -199,6 +199,20 @@ func AgendaQueryGrammars() []Grammar {
|
||||
Pattern: regexp.MustCompile(`(?i)(^|\s)(план|дел)[а-я]*\s+(на|в|во|по)\s+` + dayWordPattern + `(\s|[?!.]|$)`),
|
||||
Build: agendaQueryBuild,
|
||||
},
|
||||
{
|
||||
// "что дальше?" — the rest of the day, with no possessive and no
|
||||
// plan word for the rules above to anchor on, so neither claimed
|
||||
// it and the model called it a fact (Vikunja #498). The predicate
|
||||
// for the same utterance already exists as IsRestOfDayQuery, one
|
||||
// layer down in the query chain; this is what gets the turn there.
|
||||
//
|
||||
// "и что там дальше" and "что потом дальше" are the same question,
|
||||
// and "what's next" splits into two tokens, hence the optional
|
||||
// middles rather than plain adjacency.
|
||||
Name: "rest-of-day-query",
|
||||
Pattern: regexp.MustCompile(`(?i)^\s*(и\s+)?(что|чего|what'?s?)\s+(там\s+|ещё\s+|еще\s+|потом\s+|у\s+меня\s+)?(дальше|next)(\s|[?!.]|$)`),
|
||||
Build: agendaQueryBuild,
|
||||
},
|
||||
{
|
||||
// A named event with no calendar word at all: "когда планёрка?",
|
||||
// "во сколько созвон". He is asking when something on his calendar
|
||||
@@ -211,6 +225,11 @@ func AgendaQueryGrammars() []Grammar {
|
||||
}
|
||||
}
|
||||
|
||||
// chatNarrativeTopics — the things "расскажи X" asks for that are not
|
||||
// questions about the world. She is being asked to entertain or to describe
|
||||
// herself, and the query chain has no source for either.
|
||||
var chatNarrativeTopics = regexp.MustCompile(`(?i)(анекдот|шутк|сказк|истори[юи]\s+на\s+ночь|о\s+себе|про\s+себя|о\s+нас|про\s+нас)`)
|
||||
|
||||
// NarrativeQueryGrammars — stage-0 grammars for the two question shapes that
|
||||
// carry no question mark and no interrogative, and so reached the resident
|
||||
// model with nothing deterministic in front of them (Vikunja #498).
|
||||
@@ -255,15 +274,27 @@ var entertainmentNouns = []string{
|
||||
"joke", "jokes", "story",
|
||||
}
|
||||
|
||||
// narrativeQueryBuild — the narrative shape is a query unless he also said one
|
||||
// of the capture verbs, or asked for entertainment. "расскажи и запиши" is him
|
||||
// asking for a note, and stage 0 must not take either off the cascade.
|
||||
// narrativeQueryBuild — the narrative shape is a query carrying its topic,
|
||||
// unless he also said one of the capture verbs, asked for entertainment, or
|
||||
// asked about her. "расскажи и запиши" is him asking for a note, and stage 0
|
||||
// must not take either off the cascade.
|
||||
//
|
||||
// The topic goes into Slots.Text rather than the whole utterance: the query
|
||||
// chain looks things up by it, and "расскажи мне про Ватерлоо" is a question
|
||||
// about Ватерлоо.
|
||||
func narrativeQueryBuild(m []string) (Decision, bool) {
|
||||
rest := ""
|
||||
if len(m) > 3 {
|
||||
rest = m[3]
|
||||
topic := strings.TrimSpace(m[2])
|
||||
// "расскажи" with nothing after it is a conversational opener, and there is
|
||||
// no topic to look up.
|
||||
if topic == "" {
|
||||
return Decision{}, false
|
||||
}
|
||||
for _, t := range planTokens(rest) {
|
||||
// Against the whole utterance, not the topic: "о себе" has its preposition
|
||||
// eaten by the pattern, leaving a bare "себе".
|
||||
if chatNarrativeTopics.MatchString(m[0]) {
|
||||
return Decision{}, false
|
||||
}
|
||||
for _, t := range planTokens(topic) {
|
||||
for _, v := range captureVerbs {
|
||||
if t == v {
|
||||
return Decision{}, false
|
||||
@@ -275,7 +306,12 @@ func narrativeQueryBuild(m []string) (Decision, bool) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return agendaQueryBuild(m)
|
||||
return Decision{
|
||||
Stage: 0,
|
||||
Intent: IntentQuery,
|
||||
Confidence: 1.0,
|
||||
Slots: Slots{Text: topic},
|
||||
}, true
|
||||
}
|
||||
|
||||
// narrativeQueryPattern — "расскажи про X", built from the lexicon rather than
|
||||
@@ -285,9 +321,36 @@ func narrativeQueryBuild(m []string) (Decision, bool) {
|
||||
//
|
||||
// Anchored at the start, which was the point of the old literal and still is:
|
||||
// "запиши что мне рассказали" is a capture, and a narrative verb buried
|
||||
// mid-utterance is not the shape.
|
||||
// mid-utterance is not the shape. The dative and the preposition are eaten so
|
||||
// the topic slot comes out clean: "расскажи мне про Ватерлоо" leaves
|
||||
// "Ватерлоо".
|
||||
var narrativeQueryPattern = regexp.MustCompile(
|
||||
`(?i)^\s*(` + strings.Join(lexicon.NarrativeRequests(), "|") + `)(\s+(.*))?$`)
|
||||
`(?is)^\s*(` + strings.Join(lexicon.NarrativeRequests(), "|") +
|
||||
`)(?:\s+(?:мне|нам|us|me))?(?:\s+(?:про|о|об|about))?(\s+.+)$`)
|
||||
|
||||
// FeedQueryGrammar — stage-0 rule for "что нового в лентах?", routed to
|
||||
// IntentQuery so it reaches queryFeeds.
|
||||
//
|
||||
// Same shape of defect as the agenda grammars: the model calls it system, and
|
||||
// replySystem has no feeds arm, so the documented utterance of task 258 step 1
|
||||
// answered "пока не умею отвечать на этот вопрос." while the same question
|
||||
// worded with "новостях" worked (Vikunja #474).
|
||||
//
|
||||
// An ask word at the front and a feed noun after it are both required, which
|
||||
// is the same pair ParseFeedQuery wants. "что нового?" on its own is a greeting
|
||||
// — the most common opener in the language — and vagueNouns in feeds.go exists
|
||||
// to keep it out of the feed reader; routing it to query here would put it
|
||||
// back. "у меня новая лента в инстаграме" carries the noun without the ask and
|
||||
// stays the statement it is.
|
||||
func FeedQueryGrammar() Grammar {
|
||||
return Grammar{
|
||||
Name: "feed-query",
|
||||
// (\s|[?!.]|$) rather than \b, which is ASCII-only and never fires next
|
||||
// to a Cyrillic letter.
|
||||
Pattern: regexp.MustCompile(`(?i)^\s*(что|какие|расскажи|покажи|почитай|прочитай)\s+.*(лент|новостн)[а-я]*(\s|[?!.]|$)`),
|
||||
Build: agendaQueryBuild,
|
||||
}
|
||||
}
|
||||
|
||||
// dayWordPattern — the day words an agenda question can name. Weekdays appear
|
||||
// in the accusative and prepositional forms the questions actually use ("в
|
||||
@@ -345,7 +408,9 @@ func isCyrillic(s string) bool {
|
||||
return s != ""
|
||||
}
|
||||
|
||||
// agendaQueryBuild — shared Build for the agenda grammars. Confidence 1.0 on
|
||||
// agendaQueryBuild — shared Build for the agenda grammars and the feed one,
|
||||
// which all do the same single thing: keep the utterance out of IntentSystem
|
||||
// and let the query chain decide who answers it. Confidence 1.0 on
|
||||
// the intent only: the utterance travels intact and the query chain's own
|
||||
// matchers decide the rest.
|
||||
func agendaQueryBuild(m []string) (Decision, bool) {
|
||||
|
||||
Reference in New Issue
Block a user