Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbecadcec2 | ||
|
|
1c89b30512 | ||
|
|
75a8533939 | ||
|
|
515a98c470 | ||
|
|
d3ad1fd5bb | ||
|
|
e1802aef12 |
@@ -811,9 +811,13 @@ func main() {
|
||||
continue
|
||||
}
|
||||
learnedLexicon := interactiondomain.TaskLexiconFromHistory(conversationHistory)
|
||||
searchQuery := interactiondomain.SearchQueryWithLexicon(part, learnedLexicon)
|
||||
// Preserve the original utterance for semantic route compilation
|
||||
// before removing a search imperative. Distance and route skills
|
||||
// need the user's relation words (for example "до") to bind a
|
||||
// remembered current location to the requested destination.
|
||||
searchQuery := interactiondomain.TravelResearchQuery(part, conversationHistory, now)
|
||||
searchQuery = interactiondomain.SearchQueryWithLexicon(searchQuery, learnedLexicon)
|
||||
searchQuery = interactiondomain.TimeDifferenceResearchQuery(searchQuery)
|
||||
searchQuery = interactiondomain.TravelResearchQuery(searchQuery, conversationHistory, now)
|
||||
// The research capability may try its configured source and a
|
||||
// source-recovery fallback. Its caller must leave enough budget for
|
||||
// both attempts and evidence evaluation.
|
||||
@@ -995,7 +999,13 @@ func main() {
|
||||
ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
||||
})
|
||||
cancelReview()
|
||||
stableSemanticReply := mediaAttempted || identityReply != "" || memoryInstructionReply != "" || creativeReply != "" || (creativeFallbackReply != "" && !cognitiveAvailable) || semantic.InformationRequestKind != "" || locationReply != "" || deterministicSpeechAct == interaction.SpeechActConversational || deterministicSpeechAct == interaction.SpeechActConfirmation || deterministicSpeechAct == interaction.SpeechActRejection
|
||||
// A source-backed research result is owned by the research capability,
|
||||
// but its wording is not canonical state. Let the cognitive editor turn
|
||||
// it into a useful human answer while reviewPreservesResearchEvidence
|
||||
// still requires the source evidence to remain present. Information
|
||||
// requests without research (identity, channel state and so on) remain
|
||||
// stable semantic replies and cannot be rewritten here.
|
||||
stableSemanticReply := mediaAttempted || identityReply != "" || memoryInstructionReply != "" || creativeReply != "" || (creativeFallbackReply != "" && !cognitiveAvailable) || (semantic.InformationRequestKind != "" && !(researchAttempted && researchBacked)) || locationReply != "" || deterministicSpeechAct == interaction.SpeechActConversational || deterministicSpeechAct == interaction.SpeechActConfirmation || deterministicSpeechAct == interaction.SpeechActRejection
|
||||
if reviewErr != nil {
|
||||
log.Printf("cognitive response review unavailable: %v", reviewErr)
|
||||
} else if reviewMayReplacePlanningReply(stableSemanticReply, stableKnowledgeReply, researchAttempted, researchBacked, reviewedReply, planningReply) {
|
||||
@@ -1843,6 +1853,9 @@ func researchFindingMatchesIntent(query string, finding epistemics.ResearchFindi
|
||||
if ticketSearchQuery(query) && !ticketFindingMatchesDestination(query, finding) {
|
||||
return false
|
||||
}
|
||||
if distanceResearchQuery(query) && !containsDistanceEvidence(finding.Excerpt.Text) {
|
||||
return false
|
||||
}
|
||||
if !nearestFlightQuery(query) {
|
||||
return true
|
||||
}
|
||||
@@ -1872,6 +1885,15 @@ func researchFindingMatchesIntent(query string, finding epistemics.ResearchFindi
|
||||
return true
|
||||
}
|
||||
|
||||
func distanceResearchQuery(query string) bool {
|
||||
lower := strings.ToLower(query)
|
||||
return strings.Contains(lower, "расстоян") || strings.Contains(lower, "километр")
|
||||
}
|
||||
|
||||
func containsDistanceEvidence(value string) bool {
|
||||
return regexp.MustCompile(`(?i)\b\d[\d\s]*\s*(?:км|километр)`).MatchString(value)
|
||||
}
|
||||
|
||||
func ticketSearchQuery(query string) bool {
|
||||
return interactiondomain.TicketSearchDestination(query) != ""
|
||||
}
|
||||
|
||||
@@ -70,6 +70,18 @@ func TestTicketReplyRejectsGenericCategoryPageWithoutDestination(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDistanceReplyRejectsCalculatorPageWithoutDistance(t *testing.T) {
|
||||
query := "расстояние между Москве и Сочи в километрах по прямой и по дороге"
|
||||
calculator := epistemics.ResearchFinding{Source: epistemics.Source{Title: "Расчет расстояний"}, Excerpt: epistemics.SourceExcerpt{Text: "Калькулятор рассчитывает точное расстояние между городами."}}
|
||||
if researchFindingMatchesIntent(query, calculator) {
|
||||
t.Fatal("distance calculator landing page was presented without a measured distance")
|
||||
}
|
||||
measured := epistemics.ResearchFinding{Source: epistemics.Source{Title: "Маршрут"}, Excerpt: epistemics.SourceExcerpt{Text: "Расстояние по дороге составляет 1 620 км."}}
|
||||
if !researchFindingMatchesIntent(query, measured) {
|
||||
t.Fatal("measured distance evidence was rejected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResearchReplyRejectsGenericLandingPageForConcreteIdentifier(t *testing.T) {
|
||||
result := epistemics.ResearchResult{Findings: []epistemics.ResearchFinding{{
|
||||
State: epistemics.FindingSupported,
|
||||
@@ -101,6 +113,15 @@ func TestResearchIdentifiersExcludeSearchDate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResearchQueryKeepsDistanceRelationBeforeSearchNormalization(t *testing.T) {
|
||||
history := []interaction.HumanUtterance{{Content: "я сейчас в Москве"}}
|
||||
query := interactiondomain.TravelResearchQuery("сколько километров до Сочи?", history, time.Time{})
|
||||
query = interactiondomain.SearchQueryWithLexicon(query, interactiondomain.TaskLexicon{})
|
||||
if query != "расстояние между Москве и Сочи в километрах по прямой и по дороге" {
|
||||
t.Fatalf("distance query lost remembered origin: %q", query)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResponseReviewPreservesAttemptedResearchOutcome(t *testing.T) {
|
||||
if reviewMayReplacePlanningReply(false, false, true, false, "Уточните аэропорт.", "Пока не смог получить проверяемый ответ.") {
|
||||
t.Fatal("review replaced an honest unbacked research outcome")
|
||||
@@ -117,6 +138,11 @@ func TestResponseReviewPreservesAttemptedResearchOutcome(t *testing.T) {
|
||||
if !reviewMayReplacePlanningReply(true, true, false, false, "Санкт-Петербург — город в России.", "Меня зовут Домовой. Санкт-Петербург — город в России.") {
|
||||
t.Fatal("stable-knowledge draft must be eligible for semantic quality review")
|
||||
}
|
||||
// The caller must not mark a source-backed research result as immutable
|
||||
// semantic state: it may be rewritten, but only with its evidence retained.
|
||||
if !reviewMayReplacePlanningReply(false, false, true, true, "Из Москвы в Сочи можно добраться самолётом или поездом. Источник: https://example.test", "Сырые результаты. Источник: https://example.test") {
|
||||
t.Fatal("source-backed research draft must be eligible for human-facing review")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBearerTokenRequiresBearerScheme(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user