Route independent chat actions separately #319
@@ -702,13 +702,25 @@ func main() {
|
||||
researchBacked := false
|
||||
if hasChatRoute(routePlan, chatRouteResearch) && semantic.Interpretation.Clarification != interaction.ClarificationRequired {
|
||||
if planID, idErr := ids.New(); idErr == nil {
|
||||
researchCtx, cancelResearch := context.WithTimeout(r.Context(), 8*time.Second)
|
||||
result, researchErr := researchClient.SearchWeb(researchCtx, epistemics.WebSearchRequest{
|
||||
Plan: epistemics.ResearchPlan{ID: epistemics.ResearchPlanID("plan:" + planID), Question: effectiveTaskMessage, SourceClasses: []string{"web-search"}, FreshnessPolicy: "current"},
|
||||
PropositionKey: "question:" + string(utterance.ID), Query: effectiveTaskMessage,
|
||||
})
|
||||
cancelResearch()
|
||||
planningReply, researchBacked = renderResearchReply(result, researchErr)
|
||||
parts := interactiondomain.IndependentRequestParts(effectiveTaskMessage)
|
||||
replies := make([]string, 0, len(parts))
|
||||
for index, part := range parts {
|
||||
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"},
|
||||
PropositionKey: fmt.Sprintf("question:%s:%d", utterance.ID, index), Query: part,
|
||||
})
|
||||
cancelResearch()
|
||||
reply, backed := renderResearchReply(result, researchErr)
|
||||
if backed {
|
||||
researchBacked = true
|
||||
}
|
||||
if len(parts) > 1 {
|
||||
reply = "По запросу «" + part + "»: " + reply
|
||||
}
|
||||
replies = append(replies, reply)
|
||||
}
|
||||
planningReply = strings.Join(replies, "\n\n")
|
||||
if researchBacked {
|
||||
semantic.Reply = planningReply
|
||||
}
|
||||
|
||||
@@ -69,6 +69,13 @@ func TestStripAssistantVocative(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndependentRequestParts(t *testing.T) {
|
||||
parts := IndependentRequestParts("Дед, узнай погоду в Сочи и найди ресторан")
|
||||
if len(parts) != 2 || parts[0] != "узнай погоду в Сочи" || parts[1] != "найди ресторан" {
|
||||
t.Fatalf("unexpected request parts: %#v", parts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTravelSearchClarification(t *testing.T) {
|
||||
if got := TravelSearchClarification("Найди билеты", nil); got == "" {
|
||||
t.Fatal("underspecified travel request must ask for missing route and date")
|
||||
|
||||
@@ -25,6 +25,28 @@ func StripAssistantVocative(message string) string {
|
||||
return trimmed
|
||||
}
|
||||
|
||||
// IndependentRequestParts keeps separate user actions visible to the
|
||||
// orchestrator. It is intentionally limited to the ordinary coordinating
|
||||
// conjunction; the cognitive route remains responsible for ambiguous prose.
|
||||
func IndependentRequestParts(message string) []string {
|
||||
cleaned := StripAssistantVocative(message)
|
||||
parts := strings.Split(cleaned, " и ")
|
||||
if len(parts) < 2 {
|
||||
return []string{cleaned}
|
||||
}
|
||||
result := make([]string, 0, len(parts))
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part != "" {
|
||||
result = append(result, part)
|
||||
}
|
||||
}
|
||||
if len(result) < 2 {
|
||||
return []string{cleaned}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
||||
Reference in New Issue
Block a user