Continue travel tasks from departure location #332

Merged
m merged 1 commits from codex/chat-semantic-inventory into main 2026-08-25 07:10:22 +00:00
3 changed files with 56 additions and 1 deletions
+3
View File
@@ -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)
+40 -1
View File
@@ -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 "Из какого города вылетать и на какую дату?"