Continue travel tasks from departure location #332
@@ -532,6 +532,9 @@ func main() {
|
||||
if continuation := interactiondomain.ContinueLocalSearch(effectiveTaskMessage, conversationHistory); continuation != "" {
|
||||
continuationMessage = continuation
|
||||
effectiveTaskMessage = continuation
|
||||
} else if continuation := interactiondomain.ContinueTravelOrigin(effectiveTaskMessage, conversationHistory); continuation != "" {
|
||||
continuationMessage = continuation
|
||||
effectiveTaskMessage = continuation
|
||||
}
|
||||
if request.ConversationID != "" && interactiondomain.IsRetryRequest(utterance.Content) {
|
||||
if len(conversationHistory) > 0 {
|
||||
|
||||
@@ -95,6 +95,16 @@ func TestContinueLocalSearch(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestContinueTravelOrigin(t *testing.T) {
|
||||
history := []interaction.HumanUtterance{{Content: "Как можно добраться до Сочи?"}}
|
||||
if got := ContinueTravelOrigin("я в Казани", history); got != "Как можно добраться до Сочи из Казани" {
|
||||
t.Fatalf("unexpected travel continuation: %q", got)
|
||||
}
|
||||
if got := ContinueTravelOrigin("я в Казани", nil); got != "" {
|
||||
t.Fatalf("location must not create a travel task without context: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTravelSearchClarification(t *testing.T) {
|
||||
if got := TravelSearchClarification("Найди билеты", nil); got == "" {
|
||||
t.Fatal("underspecified travel request must ask for missing route and date")
|
||||
@@ -112,6 +122,9 @@ func TestTravelSearchClarification(t *testing.T) {
|
||||
if got := TravelSearchClarification("Как можно добраться до Сочи?", nil); got != "Из какого города выезжать в Сочи? Подберу самолёт, поезд, автобус или машину." {
|
||||
t.Fatalf("general travel question should ask departure city, got %q", got)
|
||||
}
|
||||
if got := TravelSearchClarification("Как можно добраться до Сочи из Казани", nil); got != "" {
|
||||
t.Fatalf("complete general travel route must proceed, got %q", got)
|
||||
}
|
||||
contextHistory := []interaction.HumanUtterance{{Content: "Как можно добраться до Сочи?"}}
|
||||
if got := TravelSearchClarification("Найди билеты, какой ближайший самолёт", contextHistory); got != "Из какого города вылетать в Сочи и на какую дату?" {
|
||||
t.Fatalf("travel destination should be inherited from context, got %q", got)
|
||||
|
||||
@@ -92,6 +92,41 @@ func ContinueLocalSearch(message string, history []interaction.HumanUtterance) s
|
||||
return ""
|
||||
}
|
||||
|
||||
// ContinueTravelOrigin turns a short location answer into the previous travel
|
||||
// task. The original utterance remains history; only the effective task is
|
||||
// completed for routing and research.
|
||||
func ContinueTravelOrigin(message string, history []interaction.HumanUtterance) string {
|
||||
current := semanticTokens(StripAssistantVocative(message))
|
||||
if len(current) < 3 || len(current) > 6 || current[0] != "я" {
|
||||
return ""
|
||||
}
|
||||
location := ""
|
||||
for index, token := range current {
|
||||
if (token == "в" || token == "из") && index+1 < len(current) {
|
||||
location = capitalizeWord(current[index+1])
|
||||
break
|
||||
}
|
||||
}
|
||||
if location == "" {
|
||||
return ""
|
||||
}
|
||||
var latest *interaction.HumanUtterance
|
||||
for index := range history {
|
||||
candidate := history[index]
|
||||
if !travelContextCue(semanticTokens(candidate.Content)) {
|
||||
continue
|
||||
}
|
||||
if latest == nil || candidate.ReceivedAtUnixMillis > latest.ReceivedAtUnixMillis {
|
||||
latest = &candidate
|
||||
}
|
||||
}
|
||||
if latest == nil {
|
||||
return ""
|
||||
}
|
||||
previous := strings.TrimRight(strings.TrimSpace(StripAssistantVocative(latest.Content)), "?!.,;:")
|
||||
return strings.TrimSpace(previous + " из " + location)
|
||||
}
|
||||
|
||||
// TravelSearchClarification keeps an incomplete travel request in dialogue
|
||||
// instead of reducing it to an unrelated generic web search.
|
||||
func TravelSearchClarification(message string, history []interaction.HumanUtterance) string {
|
||||
@@ -125,6 +160,10 @@ func TravelSearchClarification(message string, history []interaction.HumanUttera
|
||||
if origin && destination && date {
|
||||
return ""
|
||||
}
|
||||
ticketRequest := containsStemInTokens(current, "билет", "рейс", "самолет", "самолёт", "вылет")
|
||||
if !ticketRequest && origin && destination {
|
||||
return ""
|
||||
}
|
||||
if !destination {
|
||||
if contextDestination := travelContextDestination(history); contextDestination != "" {
|
||||
destination = true
|
||||
@@ -137,7 +176,7 @@ func TravelSearchClarification(message string, history []interaction.HumanUttera
|
||||
}
|
||||
}
|
||||
if destination && !origin && !date {
|
||||
if !containsStemInTokens(current, "билет", "рейс", "самолет", "самолёт", "вылет") {
|
||||
if !ticketRequest {
|
||||
return "Из какого города выезжать в " + destinationLabel(current, history) + "? Подберу самолёт, поезд, автобус или машину."
|
||||
}
|
||||
return "Из какого города вылетать и на какую дату?"
|
||||
|
||||
Reference in New Issue
Block a user