Ask for location before proximity search #320

Merged
m merged 2 commits from codex/chat-semantic-inventory into main 2026-08-25 02:49:14 +00:00
3 changed files with 31 additions and 0 deletions
+4
View File
@@ -705,6 +705,10 @@ func main() {
parts := interactiondomain.IndependentRequestParts(effectiveTaskMessage)
replies := make([]string, 0, len(parts))
for index, part := range parts {
if clarification := interactiondomain.LocalSearchClarification(part); clarification != "" {
replies = append(replies, "По запросу «"+part+"»: "+clarification)
continue
}
researchCtx, cancelResearch := context.WithTimeout(r.Context(), 8*time.Second)
result, researchErr := researchClient.SearchWeb(researchCtx, epistemics.WebSearchRequest{
Plan: epistemics.ResearchPlan{ID: epistemics.ResearchPlanID(fmt.Sprintf("plan:%s:%d", planID, index)), Question: part, SourceClasses: []string{"web-search"}, FreshnessPolicy: "current"},
@@ -76,6 +76,15 @@ func TestIndependentRequestParts(t *testing.T) {
}
}
func TestLocalSearchClarification(t *testing.T) {
if got := LocalSearchClarification("найди ближайший ресторан"); got == "" {
t.Fatal("proximity search without place must ask for location")
}
if got := LocalSearchClarification("найди ближайший ресторан в Сочи"); got != "" {
t.Fatalf("explicit place must proceed, got %q", got)
}
}
func TestTravelSearchClarification(t *testing.T) {
if got := TravelSearchClarification("Найди билеты", nil); got == "" {
t.Fatal("underspecified travel request must ask for missing route and date")
+18
View File
@@ -47,6 +47,24 @@ func IndependentRequestParts(message string) []string {
return result
}
// LocalSearchClarification prevents a proximity search from silently using a
// default city when the user did not provide a place.
func LocalSearchClarification(message string) string {
tokens := semanticTokens(StripAssistantVocative(message))
if !containsStemInTokens(tokens, "ресторан", "кафе") || !containsStemInTokens(tokens, "ближ", "рядом") {
return ""
}
for index, token := range tokens {
if token != "в" && token != "на" && token != "около" && !containsStem(token, "район", "город") {
continue
}
if index+1 < len(tokens) || containsStem(token, "район", "город") {
return ""
}
}
return "В каком городе или районе искать ресторан?"
}
// 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 {