diff --git a/modules/interaction/domain/semantics_test.go b/modules/interaction/domain/semantics_test.go index 712aed2..da7bbfa 100644 --- a/modules/interaction/domain/semantics_test.go +++ b/modules/interaction/domain/semantics_test.go @@ -162,11 +162,18 @@ func TestTravelSearchQueryCarriesNearestFlightDate(t *testing.T) { func TestTravelResearchQueryUsesKnownOriginForDistance(t *testing.T) { history := []interaction.HumanUtterance{{Content: "я сейчас в Москве"}} got := TravelResearchQuery("сколько километров до Сочи?", history, time.Time{}) - if !strings.Contains(got, "точка отправления: Москве") || !strings.Contains(got, "расстояние по прямой и по дороге") { + if got != "расстояние между Москве и Сочи в километрах по прямой и по дороге" { t.Fatalf("distance query lost route context: %q", got) } } +func TestTravelRouteWithKnownOriginDoesNotAskForTicketDate(t *testing.T) { + history := []interaction.HumanUtterance{{Content: "я сейчас в Москве"}} + if got := TravelSearchClarification("как можно добраться до Сочи?", history); got != "" { + t.Fatalf("general route was incorrectly reduced to ticket clarification: %q", got) + } +} + func TestInterpretUtteranceDirectiveRecordsOutcomeWithoutExecution(t *testing.T) { result := interpretForTest(t, "Поменяй базу на УПО1.", activeFocus("upo", "УПО"), "") if result.Interpretation.SpeechAct != interaction.SpeechActDirective { diff --git a/modules/interaction/domain/travel.go b/modules/interaction/domain/travel.go index cc8a726..8e41179 100644 --- a/modules/interaction/domain/travel.go +++ b/modules/interaction/domain/travel.go @@ -27,11 +27,20 @@ func TravelSearchQuery(message string, now time.Time) string { func TravelResearchQuery(message string, history []interaction.HumanUtterance, now time.Time) string { query := TravelSearchQuery(message, now) tokens := semanticTokens(StripAssistantVocative(message)) - if containsStemInTokens(tokens, "расстоян", "километр", "добрат", "маршрут") { - if origin := travelContextOrigin(history); origin != "" && !containsStemInTokens(tokens, "из", "откуда", "от") { + if containsStemInTokens(tokens, "расстоян", "километр") { + origin := travelContextOrigin(history) + destination := travelContextDestinationFromTokens(tokens) + if origin != "" && destination != "" { + return "расстояние между " + origin + " и " + destination + " в километрах по прямой и по дороге" + } + if origin != "" && !containsStemInTokens(tokens, "из", "откуда", "от") { query += " точка отправления: " + origin } query += " расстояние по прямой и по дороге" + } else if containsStemInTokens(tokens, "добрат", "маршрут") { + if origin := travelContextOrigin(history); origin != "" && !containsStemInTokens(tokens, "из", "откуда", "от") { + query += " отправление из " + origin + } } return query } @@ -234,6 +243,9 @@ func TravelSearchClarification(message string, history []interaction.HumanUttera return "Из какого города вылетать?" } if destination && !date { + if !ticketRequest { + return "" + } return "На какую дату нужны билеты?" } return "Уточните маршрут и дату: откуда, куда и на какой день нужны билеты?" @@ -267,6 +279,18 @@ func destinationLabel(current []string, history []interaction.HumanUtterance) st return "пункт назначения" } +func travelContextDestinationFromTokens(tokens []string) string { + for index, token := range tokens { + if token != "до" && token != "в" && token != "к" { + continue + } + if index+1 < len(tokens) && len([]rune(tokens[index+1])) >= 3 { + return capitalizeWord(tokens[index+1]) + } + } + return "" +} + func travelContextDestination(history []interaction.HumanUtterance) string { for index := len(history) - 1; index >= 0; index-- { tokens := semanticTokens(history[index].Content)