Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fe9802e5a | ||
|
|
0882df3ad2 |
@@ -533,7 +533,7 @@ func main() {
|
|||||||
log.Printf("interaction principal history loaded: %d utterances", len(recentUserHistory))
|
log.Printf("interaction principal history loaded: %d utterances", len(recentUserHistory))
|
||||||
}
|
}
|
||||||
conversationHistory = append(conversationHistory, recentUserHistory...)
|
conversationHistory = append(conversationHistory, recentUserHistory...)
|
||||||
personalMemory := interactiondomain.CompilePersonalMemory(conversationHistory)
|
gen2Context := interactiondomain.BuildGen2Context(conversationHistory)
|
||||||
if !creativeUserRequest && locationReply == "" {
|
if !creativeUserRequest && locationReply == "" {
|
||||||
if continuation := interactiondomain.ContinueLocalSearch(effectiveTaskMessage, conversationHistory); continuation != "" {
|
if continuation := interactiondomain.ContinueLocalSearch(effectiveTaskMessage, conversationHistory); continuation != "" {
|
||||||
continuationMessage = continuation
|
continuationMessage = continuation
|
||||||
@@ -829,7 +829,7 @@ func main() {
|
|||||||
reply, backed := renderResearchReply(searchQuery, result, researchErr)
|
reply, backed := renderResearchReply(searchQuery, result, researchErr)
|
||||||
if !backed && cognitiveAvailable {
|
if !backed && cognitiveAvailable {
|
||||||
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, part, personalMemory.ContextText(), cognitive.TaskMeaning{
|
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, part, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
||||||
})
|
})
|
||||||
cancelAnswer()
|
cancelAnswer()
|
||||||
@@ -869,7 +869,7 @@ func main() {
|
|||||||
canGenerateTextReply := shouldGenerateNonMutatingTextDirective(semantic, routePlan, helpPath, creativeRequest) && planningReply == deterministicReply
|
canGenerateTextReply := shouldGenerateNonMutatingTextDirective(semantic, routePlan, helpPath, creativeRequest) && planningReply == deterministicReply
|
||||||
if (planningReply == "" && needsCognition && semantic.Interpretation.SpeechAct == interaction.SpeechActQuestion || canGenerateTextReply) && !hasChatRoute(routePlan, chatRouteResearch) && !creativeRequest {
|
if (planningReply == "" && needsCognition && semantic.Interpretation.SpeechAct == interaction.SpeechActQuestion || canGenerateTextReply) && !hasChatRoute(routePlan, chatRouteResearch) && !creativeRequest {
|
||||||
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, effectiveTaskMessage, personalMemory.ContextText(), cognitive.TaskMeaning{
|
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, effectiveTaskMessage, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
||||||
})
|
})
|
||||||
cancelAnswer()
|
cancelAnswer()
|
||||||
@@ -992,7 +992,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
if strings.TrimSpace(planningReply) != "" {
|
if strings.TrimSpace(planningReply) != "" {
|
||||||
reviewContext, cancelReview := context.WithTimeout(r.Context(), 12*time.Second)
|
reviewContext, cancelReview := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
reviewedReply, reviewErr := cognitiveClient.ReviewResponse(reviewContext, session, utterance.Content, planningReply, personalMemory.ContextText(), cognitive.TaskMeaning{
|
reviewedReply, reviewErr := cognitiveClient.ReviewResponse(reviewContext, session, utterance.Content, planningReply, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct),
|
SpeechAct: string(semantic.Interpretation.SpeechAct),
|
||||||
CapabilityHints: toCapabilityKinds(semantic.CapabilityHints),
|
CapabilityHints: toCapabilityKinds(semantic.CapabilityHints),
|
||||||
RequestedOutcome: semantic.Interpretation.RequestedOutcome,
|
RequestedOutcome: semantic.Interpretation.RequestedOutcome,
|
||||||
|
|||||||
@@ -11,14 +11,24 @@ import (
|
|||||||
var ErrInvalidContextBudget = errors.New("context budget must be positive")
|
var ErrInvalidContextBudget = errors.New("context budget must be positive")
|
||||||
|
|
||||||
type ContextCandidate struct {
|
type ContextCandidate struct {
|
||||||
Excerpt ContextExcerpt
|
Excerpt ContextExcerpt
|
||||||
Relevance int
|
Relevance int
|
||||||
|
Lane string
|
||||||
|
ContextScopeRef string
|
||||||
|
FreshnessState string
|
||||||
|
Negative bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContextCompileInput struct {
|
type ContextCompileInput struct {
|
||||||
Candidates []ContextCandidate
|
Candidates []ContextCandidate
|
||||||
DataPolicy capability.DataPolicy
|
DataPolicy capability.DataPolicy
|
||||||
MaxBytes int
|
MaxBytes int
|
||||||
|
TaskRef string
|
||||||
|
FocusFrameRef string
|
||||||
|
ContextScopeRef string
|
||||||
|
FreshnessRequirement string
|
||||||
|
RiskClass string
|
||||||
|
TokenBudget int
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContextOmission struct {
|
type ContextOmission struct {
|
||||||
@@ -30,6 +40,24 @@ type ContextBundle struct {
|
|||||||
Excerpts []ContextExcerpt
|
Excerpts []ContextExcerpt
|
||||||
Omissions []ContextOmission
|
Omissions []ContextOmission
|
||||||
Bytes int
|
Bytes int
|
||||||
|
Trace ContextAssemblyTrace
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContextAssemblyTrace struct {
|
||||||
|
Included []ContextExcerptID
|
||||||
|
Excluded []ContextOmission
|
||||||
|
Coverage string
|
||||||
|
CompilerVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
type IterativeRetrievalRequest struct {
|
||||||
|
Query string
|
||||||
|
RemainingBytes int
|
||||||
|
Pass int
|
||||||
|
}
|
||||||
|
type IterativeRetrievalResponse struct {
|
||||||
|
Candidates []ContextCandidate
|
||||||
|
Exhausted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompileContext deterministically selects permitted, relevant excerpts for a
|
// CompileContext deterministically selects permitted, relevant excerpts for a
|
||||||
@@ -54,6 +82,10 @@ func CompileContext(input ContextCompileInput) (ContextBundle, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
seen[excerpt.ID] = struct{}{}
|
seen[excerpt.ID] = struct{}{}
|
||||||
|
if input.ContextScopeRef != "" && candidate.ContextScopeRef != input.ContextScopeRef {
|
||||||
|
bundle.Omissions = append(bundle.Omissions, ContextOmission{ID: excerpt.ID, Reason: "context_scope"})
|
||||||
|
continue
|
||||||
|
}
|
||||||
reason := permittedContextReason(excerpt, input.DataPolicy)
|
reason := permittedContextReason(excerpt, input.DataPolicy)
|
||||||
if reason != "" {
|
if reason != "" {
|
||||||
bundle.Omissions = append(bundle.Omissions, ContextOmission{ID: excerpt.ID, Reason: reason})
|
bundle.Omissions = append(bundle.Omissions, ContextOmission{ID: excerpt.ID, Reason: reason})
|
||||||
@@ -70,7 +102,11 @@ func CompileContext(input ContextCompileInput) (ContextBundle, error) {
|
|||||||
}
|
}
|
||||||
bundle.Excerpts = append(bundle.Excerpts, excerpt)
|
bundle.Excerpts = append(bundle.Excerpts, excerpt)
|
||||||
bundle.Bytes += bytes
|
bundle.Bytes += bytes
|
||||||
|
bundle.Trace.Included = append(bundle.Trace.Included, excerpt.ID)
|
||||||
}
|
}
|
||||||
|
bundle.Trace.Excluded = append([]ContextOmission(nil), bundle.Omissions...)
|
||||||
|
bundle.Trace.CompilerVersion = "context-compiler-v2-additive"
|
||||||
|
bundle.Trace.Coverage = "BOUNDED"
|
||||||
return bundle, nil
|
return bundle, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package cognitive_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/capability"
|
||||||
|
"git.cin.su/m/Assistant/contracts/cognitive"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestContextCompilerV2TraceAndBudgetRemainDeterministic(t *testing.T) {
|
||||||
|
b, err := cognitive.CompileContext(cognitive.ContextCompileInput{MaxBytes: 5, DataPolicy: capability.DataPolicyLocalOnly, TaskRef: "task", FocusFrameRef: "frame", ContextScopeRef: "company-a", Candidates: []cognitive.ContextCandidate{{Excerpt: cognitive.ContextExcerpt{ID: "a", Text: "123", Sensitivity: cognitive.SensitivityPrivateAllowed}, ContextScopeRef: "company-a", Relevance: 10}, {Excerpt: cognitive.ContextExcerpt{ID: "b", Text: "123456", Sensitivity: cognitive.SensitivityPrivateAllowed}, ContextScopeRef: "company-b", Relevance: 100}}})
|
||||||
|
if err != nil || len(b.Excerpts) != 1 || len(b.Trace.Excluded) != 1 {
|
||||||
|
t.Fatalf("bundle=%#v err=%v", b, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
{"task_file":"dev/tasks/GEN2-009-build-memory-retrieval-fabric-as-rebuildable-projections.json","task_id":"GEN2-009","task_revision":1}
|
{"task_file":"dev/tasks/GEN2-011-cut-personalmemory-v1-to-compatibility-fallback.json","task_id":"GEN2-011","task_revision":1}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import "git.cin.su/m/Assistant/contracts/interaction"
|
||||||
|
|
||||||
|
type ContextProjection struct {
|
||||||
|
Text string
|
||||||
|
Source string
|
||||||
|
UsedPersonalMemoryFallback bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildGen2Context is a read-side projection over canonical utterance history.
|
||||||
|
// PersonalMemory remains a compatibility fallback and is never written here.
|
||||||
|
func BuildGen2Context(history []interaction.HumanUtterance) ContextProjection {
|
||||||
|
text := CompilePersonalMemory(history).ContextText()
|
||||||
|
if text != "" {
|
||||||
|
return ContextProjection{Text: text, Source: "retrieval:interaction-utterances"}
|
||||||
|
}
|
||||||
|
return ContextProjection{Text: text, Source: "personal-memory-v1-fallback", UsedPersonalMemoryFallback: true}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/interaction"
|
||||||
|
"git.cin.su/m/Assistant/modules/interaction/domain"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGen2ContextUsesRetrievalProjectionAndKeepsV1Fallback(t *testing.T) {
|
||||||
|
got := domain.BuildGen2Context([]interaction.HumanUtterance{{ID: "u", Content: "Я сейчас в Москве", ReceivedAtUnixMillis: 1}})
|
||||||
|
if got.Source != "retrieval:interaction-utterances" || got.UsedPersonalMemoryFallback {
|
||||||
|
t.Fatalf("got %#v", got)
|
||||||
|
}
|
||||||
|
empty := domain.BuildGen2Context(nil)
|
||||||
|
if !empty.UsedPersonalMemoryFallback {
|
||||||
|
t.Fatalf("fallback missing: %#v", empty)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user