ARCH: усилить metadata ambiguity choice sets в lane arbitration
This commit is contained in:
parent
d9454fcdef
commit
c328c52c9b
|
|
@ -228,9 +228,22 @@ function collectFollowupDiscoverySeed(followupContext) {
|
|||
dateScope,
|
||||
metadataRouteFamily: toNonEmptyString(followupContext?.previous_discovery_metadata_route_family),
|
||||
metadataSelectedEntitySet: toNonEmptyString(followupContext?.previous_discovery_metadata_selected_entity_set),
|
||||
metadataAmbiguityDetected: followupContext?.previous_discovery_metadata_ambiguity_detected === true
|
||||
metadataAmbiguityDetected: followupContext?.previous_discovery_metadata_ambiguity_detected === true,
|
||||
metadataAmbiguityEntitySets: collectEntityCandidates(followupContext?.previous_discovery_metadata_ambiguity_entity_sets)
|
||||
};
|
||||
}
|
||||
function metadataEntitySetsSuggestDocumentLane(values) {
|
||||
return values.some((value) => /(?:документ|document|invoice|waybill|накладн|счет[- ]?фактур|акт)/iu.test(value));
|
||||
}
|
||||
function metadataEntitySetsSuggestMovementLane(values) {
|
||||
return values.some((value) => /(?:регистр|register|movement|движени|операц|проводк|bank)/iu.test(value));
|
||||
}
|
||||
function metadataAmbiguityCollapsesToDocumentLane(values) {
|
||||
return values.length > 0 && metadataEntitySetsSuggestDocumentLane(values) && !metadataEntitySetsSuggestMovementLane(values);
|
||||
}
|
||||
function metadataAmbiguityCollapsesToMovementLane(values) {
|
||||
return values.length > 0 && metadataEntitySetsSuggestMovementLane(values) && !metadataEntitySetsSuggestDocumentLane(values);
|
||||
}
|
||||
function hasLifecycleSignal(text) {
|
||||
return /(?:сколько\s+лет|как\s+давно|давно\s+ли|возраст|перв(?:ая|ый)\s+актив|когда\s+начал|когда\s+появ|lifecycle|activity\s+duration|business\s+age|how\s+long)/iu.test(text);
|
||||
}
|
||||
|
|
@ -257,10 +270,10 @@ function hasMetadataObjectHint(text) {
|
|||
return /(?:\u0440\u0435\u0433\u0438\u0441\u0442\u0440(?:\u044b)?|\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u044b)?|\u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a(?:\u0438)?|\u043f\u043e\u043b(?:\u0435|\u044f)|registers?|documents?|catalogs?|fields?)/iu.test(text);
|
||||
}
|
||||
function hasDocumentEvidenceFollowupSignal(text) {
|
||||
return /(?:\u043f\u043e\s+\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u0430\u043c|\u044b)?|\u0434\u0430\u0432\u0430\u0439\s+\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u044b)?|\u0438\u0449\u0438\s+\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u044b)?|\u043f\u043e\u043a\u0430\u0436\u0438\s+\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u044b)?|document(?:s)?\s+(?:then|next)?|(?:then|next)\s+documents?|go\s+to\s+documents?)/iu.test(text);
|
||||
return /(?:\u043f\u043e\s+\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u0430\u043c|\u044b)?|\u0434\u0430\u0432\u0430\u0439\s+\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u044b)?|\u0438\u0449\u0438\s+\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u044b)?|\u043f\u043e\u043a\u0430\u0436\u0438\s+\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442(?:\u044b)?|(?:\u043f\u043e\u043a\u0430\u0436\u0438|\u043a\u0430\u043a\u0438\u0435|\u0441\u043f\u0438\u0441\u043e\u043a|\u0434\u0430\u0439|\u0438\u0449\u0438)\s+(?:\u0441\u0447(?:[еe]т|\u0435\u0442)[-\u2011 ]?\u0444\u0430\u043a\u0442\u0443\u0440(?:\u044b|\u0430)?|\u043d\u0430\u043a\u043b\u0430\u0434\u043d(?:\u044b\u0435|\u0430\u044f)?|\u0430\u043a\u0442(?:\u044b)?|\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446(?:\u0438\u0438|\u0438\u044e)|invoice(?:s)?|bill(?:s)?|waybill(?:s)?)|document(?:s)?\s+(?:then|next)?|(?:then|next)\s+documents?|go\s+to\s+documents?)/iu.test(text);
|
||||
}
|
||||
function hasMovementEvidenceFollowupSignal(text) {
|
||||
return /(?:\u043f\u043e\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f\u043c|\u0438\u044f)?|\u0434\u0430\u0432\u0430\u0439\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|\u0438\u0449\u0438\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|\u043f\u043e\u043a\u0430\u0436\u0438\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|\u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a(?:\u0438\u0435|\u0438\u0439)\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|movement(?:s)?\s+(?:then|next)?|(?:then|next)\s+movements?|go\s+to\s+movements?)/iu.test(text);
|
||||
return /(?:\u043f\u043e\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f\u043c|\u0438\u044f)?|\u0434\u0430\u0432\u0430\u0439\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|\u0438\u0449\u0438\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|\u043f\u043e\u043a\u0430\u0436\u0438\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|\u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a(?:\u0438\u0435|\u0438\u0439)\s+\u0434\u0432\u0438\u0436\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|(?:\u043f\u043e\u043a\u0430\u0436\u0438|\u043a\u0430\u043a\u0438\u0435|\u0441\u043f\u0438\u0441\u043e\u043a|\u0434\u0430\u0439|\u0438\u0449\u0438)\s+(?:\u043f\u043b\u0430\u0442[еe]\u0436(?:\u0438|\u0438)?|\u043e\u043f\u0435\u0440\u0430\u0446(?:\u0438\u0438|\u0438\u044e)|\u043f\u0440\u043e\u0432\u043e\u0434\u043a(?:\u0438|\u0430)|\u0441\u043f\u0438\u0441\u0430\u043d(?:\u0438\u044f|\u0438\u0435)|\u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d(?:\u0438\u044f|\u0438\u0435)|payment(?:s)?|transaction(?:s)?|operation(?:s)?|posting(?:s)?|bank\s+operation(?:s)?)|movement(?:s)?\s+(?:then|next)?|(?:then|next)\s+movements?|go\s+to\s+movements?)/iu.test(text);
|
||||
}
|
||||
function hasMetadataDownstreamContinuationSignal(text) {
|
||||
return /(?:\u0434\u0430\u0432\u0430\u0439\s+\u0434\u0430\u043b\u044c\u0448\u0435|\u0438\u0434(?:\u0435|\u0451)\u043c\s+\u0434\u0430\u043b\u044c\u0448\u0435|\u043f\u043e\u0448\u043b(?:\u0438|\u0451\u043c)\s+\u0434\u0430\u043b\u044c\u0448\u0435|\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0439|\u0438\u0449\u0438\s+\u0434\u0430\u043b\u044c\u0448\u0435|\u0438\u0449\u0438\s+\u0434\u0430\u043d\u043d\u044b\u0435|\u043f\u043e\u043a\u0430\u0436\u0438\s+\u0434\u0430\u043d\u043d\u044b\u0435|\u043f\u043e\u043a\u0430\u0436\u0438\s+\u0441\u0442\u0440\u043e\u043a\u0438|\u0433\u043b\u0443\u0431\u0436\u0435|\u0447\u0442\u043e\s+\u0434\u0430\u043b\u044c\u0448\u0435|continue|go\s+ahead|go\s+deeper|look\s+deeper|drill\s+down|show\s+(?:data|rows))/iu.test(text);
|
||||
|
|
@ -351,6 +364,8 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
|||
const monthlyAggregationSignal = hasMonthlyAggregationSignal(rawText);
|
||||
const explicitDateScopeLiteralDetected = hasExplicitDateScopeLiteral(rawText);
|
||||
const rawDateScope = collectDateScopeFromRawText(rawText);
|
||||
const metadataDocumentHintSignal = hasDocumentEvidenceFollowupSignal(rawText);
|
||||
const metadataMovementHintSignal = hasMovementEvidenceFollowupSignal(rawText);
|
||||
const rawDomain = toNonEmptyString(assistantTurnMeaning?.asked_domain_family);
|
||||
const rawAction = toNonEmptyString(assistantTurnMeaning?.asked_action_family);
|
||||
const rawAggregationAxis = toNonEmptyString(assistantTurnMeaning?.asked_aggregation_axis);
|
||||
|
|
@ -373,26 +388,28 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
|||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
hasDocumentEvidenceFollowupSignal(rawText));
|
||||
metadataDocumentHintSignal);
|
||||
const metadataAmbiguityResolvedDocumentFollowupApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
(followupSeed.metadataAmbiguityEntitySets.length === 0 ||
|
||||
metadataEntitySetsSuggestDocumentLane(followupSeed.metadataAmbiguityEntitySets)) &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
hasDocumentEvidenceFollowupSignal(rawText));
|
||||
metadataDocumentHintSignal);
|
||||
const metadataGroundedMovementFollowupApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataRouteFamily === "movement_evidence" &&
|
||||
!followupSeed.metadataAmbiguityDetected &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
hasMovementEvidenceFollowupSignal(rawText));
|
||||
metadataMovementHintSignal);
|
||||
const metadataAmbiguityResolvedMovementFollowupApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
(followupSeed.metadataAmbiguityEntitySets.length === 0 ||
|
||||
metadataEntitySetsSuggestMovementLane(followupSeed.metadataAmbiguityEntitySets)) &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
hasMovementEvidenceFollowupSignal(rawText));
|
||||
metadataMovementHintSignal);
|
||||
const metadataGroundedLaneContinuationApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
(followupSeed.metadataRouteFamily === "document_evidence" ||
|
||||
followupSeed.metadataRouteFamily === "movement_evidence") &&
|
||||
|
|
@ -401,15 +418,37 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
|||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
!hasDocumentEvidenceFollowupSignal(rawText) &&
|
||||
!hasMovementEvidenceFollowupSignal(rawText) &&
|
||||
!metadataDocumentHintSignal &&
|
||||
!metadataMovementHintSignal &&
|
||||
hasMetadataDownstreamContinuationSignal(rawText));
|
||||
const metadataAmbiguityCollapsedDocumentLaneContinuationApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
metadataAmbiguityCollapsesToDocumentLane(followupSeed.metadataAmbiguityEntitySets) &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
!metadataDocumentHintSignal &&
|
||||
!metadataMovementHintSignal &&
|
||||
hasMetadataDownstreamContinuationSignal(rawText));
|
||||
const metadataAmbiguityCollapsedMovementLaneContinuationApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
metadataAmbiguityCollapsesToMovementLane(followupSeed.metadataAmbiguityEntitySets) &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
!metadataDocumentHintSignal &&
|
||||
!metadataMovementHintSignal &&
|
||||
hasMetadataDownstreamContinuationSignal(rawText));
|
||||
const metadataGroundedDocumentLaneApplicable = metadataGroundedDocumentFollowupApplicable ||
|
||||
metadataAmbiguityResolvedDocumentFollowupApplicable ||
|
||||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence");
|
||||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence") ||
|
||||
metadataAmbiguityCollapsedDocumentLaneContinuationApplicable;
|
||||
const metadataGroundedMovementLaneApplicable = metadataGroundedMovementFollowupApplicable ||
|
||||
metadataAmbiguityResolvedMovementFollowupApplicable ||
|
||||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence");
|
||||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence") ||
|
||||
metadataAmbiguityCollapsedMovementLaneContinuationApplicable;
|
||||
const effectiveMetadataFollowupSeedApplicable = metadataFollowupSeedApplicable &&
|
||||
!metadataGroundedDocumentLaneApplicable &&
|
||||
!metadataGroundedMovementLaneApplicable;
|
||||
|
|
@ -437,7 +476,9 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
|||
const lifecycleSignal = rawLifecycleSignal || seededDomain === "counterparty_lifecycle";
|
||||
const bidirectionalValueFlowSignal = !lifecycleSignal &&
|
||||
(rawBidirectionalValueFlowSignal || seededAction === "net_value_flow");
|
||||
const valueFlowSignal = !lifecycleSignal && (rawValueFlowSignal || seededDomain === "counterparty_value");
|
||||
const valueFlowSignal = !lifecycleSignal &&
|
||||
!metadataGroundedMovementLaneApplicable &&
|
||||
(rawValueFlowSignal || seededDomain === "counterparty_value");
|
||||
const payoutSignal = valueFlowSignal &&
|
||||
!bidirectionalValueFlowSignal &&
|
||||
(rawPayoutSignal || seededAction === "payout");
|
||||
|
|
@ -616,6 +657,12 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
|||
if (metadataGroundedLaneContinuationApplicable) {
|
||||
pushReason(reasonCodes, "mcp_discovery_metadata_grounded_lane_continuation");
|
||||
}
|
||||
if (metadataAmbiguityCollapsedDocumentLaneContinuationApplicable) {
|
||||
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_collapsed_to_document_lane");
|
||||
}
|
||||
if (metadataAmbiguityCollapsedMovementLaneContinuationApplicable) {
|
||||
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_collapsed_to_movement_lane");
|
||||
}
|
||||
if (unsupported) {
|
||||
pushReason(reasonCodes, "mcp_discovery_unsupported_but_understood_turn");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,6 +192,17 @@ export function readAssistantMcpDiscoveryMetadataAmbiguityDetected(
|
|||
return readAssistantMcpDiscoveryDerivedMetadataSurface(debug)?.ambiguity_detected === true;
|
||||
}
|
||||
|
||||
export function readAssistantMcpDiscoveryMetadataAmbiguityEntitySets(
|
||||
debug: Record<string, unknown> | null,
|
||||
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
||||
): string[] {
|
||||
const values = readAssistantMcpDiscoveryDerivedMetadataSurface(debug)?.ambiguity_entity_sets;
|
||||
if (!Array.isArray(values)) {
|
||||
return [];
|
||||
}
|
||||
return values.map((item) => toNonEmptyString(item)).filter((item): item is string => Boolean(item));
|
||||
}
|
||||
|
||||
function mapAssistantMcpDiscoveryPilotScopeToAddressIntent(
|
||||
pilotScope: string | null,
|
||||
actionFamily: string | null
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ function collectFollowupDiscoverySeed(followupContext: Record<string, unknown> |
|
|||
metadataRouteFamily: string | null;
|
||||
metadataSelectedEntitySet: string | null;
|
||||
metadataAmbiguityDetected: boolean;
|
||||
metadataAmbiguityEntitySets: string[];
|
||||
} {
|
||||
const previousFilters = toRecordObject(followupContext?.previous_filters);
|
||||
const rootFilters = toRecordObject(followupContext?.root_filters);
|
||||
|
|
@ -302,10 +303,29 @@ function collectFollowupDiscoverySeed(followupContext: Record<string, unknown> |
|
|||
dateScope,
|
||||
metadataRouteFamily: toNonEmptyString(followupContext?.previous_discovery_metadata_route_family),
|
||||
metadataSelectedEntitySet: toNonEmptyString(followupContext?.previous_discovery_metadata_selected_entity_set),
|
||||
metadataAmbiguityDetected: followupContext?.previous_discovery_metadata_ambiguity_detected === true
|
||||
metadataAmbiguityDetected: followupContext?.previous_discovery_metadata_ambiguity_detected === true,
|
||||
metadataAmbiguityEntitySets: collectEntityCandidates(followupContext?.previous_discovery_metadata_ambiguity_entity_sets)
|
||||
};
|
||||
}
|
||||
|
||||
function metadataEntitySetsSuggestDocumentLane(values: string[]): boolean {
|
||||
return values.some((value) => /(?:документ|document|invoice|waybill|накладн|счет[- ]?фактур|акт)/iu.test(value));
|
||||
}
|
||||
|
||||
function metadataEntitySetsSuggestMovementLane(values: string[]): boolean {
|
||||
return values.some((value) =>
|
||||
/(?:регистр|register|movement|движени|операц|проводк|bank)/iu.test(value)
|
||||
);
|
||||
}
|
||||
|
||||
function metadataAmbiguityCollapsesToDocumentLane(values: string[]): boolean {
|
||||
return values.length > 0 && metadataEntitySetsSuggestDocumentLane(values) && !metadataEntitySetsSuggestMovementLane(values);
|
||||
}
|
||||
|
||||
function metadataAmbiguityCollapsesToMovementLane(values: string[]): boolean {
|
||||
return values.length > 0 && metadataEntitySetsSuggestMovementLane(values) && !metadataEntitySetsSuggestDocumentLane(values);
|
||||
}
|
||||
|
||||
function hasLifecycleSignal(text: string): boolean {
|
||||
return /(?:сколько\s+лет|как\s+давно|давно\s+ли|возраст|перв(?:ая|ый)\s+актив|когда\s+начал|когда\s+появ|lifecycle|activity\s+duration|business\s+age|how\s+long)/iu.test(
|
||||
text
|
||||
|
|
@ -520,6 +540,8 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
|||
const metadataAmbiguityResolvedDocumentFollowupApplicable = Boolean(
|
||||
followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
(followupSeed.metadataAmbiguityEntitySets.length === 0 ||
|
||||
metadataEntitySetsSuggestDocumentLane(followupSeed.metadataAmbiguityEntitySets)) &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
|
|
@ -536,6 +558,8 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
|||
const metadataAmbiguityResolvedMovementFollowupApplicable = Boolean(
|
||||
followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
(followupSeed.metadataAmbiguityEntitySets.length === 0 ||
|
||||
metadataEntitySetsSuggestMovementLane(followupSeed.metadataAmbiguityEntitySets)) &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
metadataMovementHintSignal
|
||||
|
|
@ -553,14 +577,40 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
|||
!metadataMovementHintSignal &&
|
||||
hasMetadataDownstreamContinuationSignal(rawText)
|
||||
);
|
||||
const metadataAmbiguityCollapsedDocumentLaneContinuationApplicable = Boolean(
|
||||
followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
metadataAmbiguityCollapsesToDocumentLane(followupSeed.metadataAmbiguityEntitySets) &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
!metadataDocumentHintSignal &&
|
||||
!metadataMovementHintSignal &&
|
||||
hasMetadataDownstreamContinuationSignal(rawText)
|
||||
);
|
||||
const metadataAmbiguityCollapsedMovementLaneContinuationApplicable = Boolean(
|
||||
followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
metadataAmbiguityCollapsesToMovementLane(followupSeed.metadataAmbiguityEntitySets) &&
|
||||
followupSeed.counterparty &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
!metadataDocumentHintSignal &&
|
||||
!metadataMovementHintSignal &&
|
||||
hasMetadataDownstreamContinuationSignal(rawText)
|
||||
);
|
||||
const metadataGroundedDocumentLaneApplicable =
|
||||
metadataGroundedDocumentFollowupApplicable ||
|
||||
metadataAmbiguityResolvedDocumentFollowupApplicable ||
|
||||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence");
|
||||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence") ||
|
||||
metadataAmbiguityCollapsedDocumentLaneContinuationApplicable;
|
||||
const metadataGroundedMovementLaneApplicable =
|
||||
metadataGroundedMovementFollowupApplicable ||
|
||||
metadataAmbiguityResolvedMovementFollowupApplicable ||
|
||||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence");
|
||||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence") ||
|
||||
metadataAmbiguityCollapsedMovementLaneContinuationApplicable;
|
||||
const effectiveMetadataFollowupSeedApplicable =
|
||||
metadataFollowupSeedApplicable &&
|
||||
!metadataGroundedDocumentLaneApplicable &&
|
||||
|
|
@ -784,6 +834,12 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
|||
if (metadataGroundedLaneContinuationApplicable) {
|
||||
pushReason(reasonCodes, "mcp_discovery_metadata_grounded_lane_continuation");
|
||||
}
|
||||
if (metadataAmbiguityCollapsedDocumentLaneContinuationApplicable) {
|
||||
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_collapsed_to_document_lane");
|
||||
}
|
||||
if (metadataAmbiguityCollapsedMovementLaneContinuationApplicable) {
|
||||
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_collapsed_to_movement_lane");
|
||||
}
|
||||
if (unsupported) {
|
||||
pushReason(reasonCodes, "mcp_discovery_unsupported_but_understood_turn");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
readAddressDebugFilters,
|
||||
readAddressDebugItem,
|
||||
readAssistantMcpDiscoveryMetadataAmbiguityDetected,
|
||||
readAssistantMcpDiscoveryMetadataAmbiguityEntitySets,
|
||||
readAssistantMcpDiscoveryMetadataRouteFamily,
|
||||
readAssistantMcpDiscoveryMetadataSelectedEntitySet,
|
||||
readAddressDebugTemporalScope,
|
||||
|
|
@ -621,6 +622,10 @@ export function createAssistantTransitionPolicy(deps) {
|
|||
const sourceDiscoveryMetadataAmbiguityDetected = readAssistantMcpDiscoveryMetadataAmbiguityDetected(
|
||||
carryoverSourceDebug
|
||||
);
|
||||
const sourceDiscoveryMetadataAmbiguityEntitySets = readAssistantMcpDiscoveryMetadataAmbiguityEntitySets(
|
||||
carryoverSourceDebug,
|
||||
deps.toNonEmptyString
|
||||
);
|
||||
const llmExplicitIntent = deps.toNonEmptyString(llmPreDecomposeMeta?.predecomposeContract?.intent);
|
||||
const llmSelectedObjectScopeDetected =
|
||||
llmPreDecomposeMeta?.predecomposeContract?.semantics?.selected_object_scope_detected === true;
|
||||
|
|
@ -956,6 +961,8 @@ export function createAssistantTransitionPolicy(deps) {
|
|||
previous_discovery_metadata_route_family: sourceDiscoveryMetadataRouteFamily ?? undefined,
|
||||
previous_discovery_metadata_selected_entity_set: sourceDiscoveryMetadataSelectedEntitySet ?? undefined,
|
||||
previous_discovery_metadata_ambiguity_detected: sourceDiscoveryMetadataAmbiguityDetected || undefined,
|
||||
previous_discovery_metadata_ambiguity_entity_sets:
|
||||
sourceDiscoveryMetadataAmbiguityEntitySets.length > 0 ? sourceDiscoveryMetadataAmbiguityEntitySets : undefined,
|
||||
resolved_counterparty_from_display: resolvedCounterpartyFromDisplay || undefined,
|
||||
root_context_only: rootScopedPivot || undefined,
|
||||
root_intent: shouldAttachInventoryRootFrame ? inventoryRootFrame?.intent ?? undefined : undefined,
|
||||
|
|
|
|||
|
|
@ -367,6 +367,7 @@ describe("assistant MCP discovery turn input adapter", () => {
|
|||
followupContext: {
|
||||
previous_discovery_pilot_scope: "metadata_inspection_v1",
|
||||
previous_discovery_metadata_ambiguity_detected: true,
|
||||
previous_discovery_metadata_ambiguity_entity_sets: ["Документ", "РегистрНакопления"],
|
||||
previous_filters: {
|
||||
counterparty: "SVK",
|
||||
period_from: "2020-01-01",
|
||||
|
|
@ -398,6 +399,7 @@ describe("assistant MCP discovery turn input adapter", () => {
|
|||
followupContext: {
|
||||
previous_discovery_pilot_scope: "metadata_inspection_v1",
|
||||
previous_discovery_metadata_ambiguity_detected: true,
|
||||
previous_discovery_metadata_ambiguity_entity_sets: ["Документ", "РегистрНакопления"],
|
||||
previous_filters: {
|
||||
counterparty: "SVK",
|
||||
period_from: "2020-01-01",
|
||||
|
|
@ -429,6 +431,7 @@ describe("assistant MCP discovery turn input adapter", () => {
|
|||
followupContext: {
|
||||
previous_discovery_pilot_scope: "metadata_inspection_v1",
|
||||
previous_discovery_metadata_ambiguity_detected: true,
|
||||
previous_discovery_metadata_ambiguity_entity_sets: ["Документ", "РегистрНакопления"],
|
||||
previous_filters: {
|
||||
counterparty: "SVK",
|
||||
period_from: "2020-01-01",
|
||||
|
|
@ -459,6 +462,7 @@ describe("assistant MCP discovery turn input adapter", () => {
|
|||
followupContext: {
|
||||
previous_discovery_pilot_scope: "metadata_inspection_v1",
|
||||
previous_discovery_metadata_ambiguity_detected: true,
|
||||
previous_discovery_metadata_ambiguity_entity_sets: ["Документ", "РегистрНакопления"],
|
||||
previous_filters: {
|
||||
counterparty: "SVK",
|
||||
period_from: "2020-01-01",
|
||||
|
|
@ -484,6 +488,88 @@ describe("assistant MCP discovery turn input adapter", () => {
|
|||
expect(result.reason_codes).not.toContain("mcp_discovery_value_flow_signal_detected");
|
||||
});
|
||||
|
||||
it("does not resolve metadata ambiguity into movement lane when confirmed ambiguity sets contain documents only", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "по движениям",
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "metadata_inspection_v1",
|
||||
previous_discovery_metadata_ambiguity_detected: true,
|
||||
previous_discovery_metadata_ambiguity_entity_sets: ["Документ"],
|
||||
previous_filters: {
|
||||
counterparty: "SVK",
|
||||
period_from: "2020-01-01",
|
||||
period_to: "2020-12-31"
|
||||
},
|
||||
previous_anchor_type: "counterparty",
|
||||
previous_anchor_value: "SVK"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.reason_codes).not.toContain("mcp_discovery_metadata_ambiguity_resolved_to_movement_lane");
|
||||
});
|
||||
|
||||
it("continues from ambiguous metadata into document lane when ambiguity choice set collapses to documents on a generic downstream follow-up", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "continue with data",
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "metadata_inspection_v1",
|
||||
previous_discovery_metadata_ambiguity_detected: true,
|
||||
previous_discovery_metadata_ambiguity_entity_sets: ["Документ", "invoice"],
|
||||
previous_filters: {
|
||||
counterparty: "SVK",
|
||||
period_from: "2020-01-01",
|
||||
period_to: "2020-12-31"
|
||||
},
|
||||
previous_anchor_type: "counterparty",
|
||||
previous_anchor_value: "SVK"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.semantic_data_need).toBe("document evidence");
|
||||
expect(result.turn_meaning_ref).toMatchObject({
|
||||
asked_domain_family: "documents",
|
||||
asked_action_family: "list_documents",
|
||||
explicit_entity_candidates: ["SVK"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "document_evidence",
|
||||
stale_replay_forbidden: true
|
||||
});
|
||||
expect(result.reason_codes).toContain("mcp_discovery_metadata_ambiguity_collapsed_to_document_lane");
|
||||
});
|
||||
|
||||
it("continues from ambiguous metadata into movement lane when ambiguity choice set collapses to movements on a generic downstream follow-up", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "continue with data",
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "metadata_inspection_v1",
|
||||
previous_discovery_metadata_ambiguity_detected: true,
|
||||
previous_discovery_metadata_ambiguity_entity_sets: ["РегистрНакопления", "movement"],
|
||||
previous_filters: {
|
||||
counterparty: "SVK",
|
||||
period_from: "2020-01-01",
|
||||
period_to: "2020-12-31"
|
||||
},
|
||||
previous_anchor_type: "counterparty",
|
||||
previous_anchor_value: "SVK"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.semantic_data_need).toBe("movement evidence");
|
||||
expect(result.turn_meaning_ref).toMatchObject({
|
||||
asked_domain_family: "movements",
|
||||
asked_action_family: "list_movements",
|
||||
explicit_entity_candidates: ["SVK"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "movement_evidence",
|
||||
stale_replay_forbidden: true
|
||||
});
|
||||
expect(result.reason_codes).toContain("mcp_discovery_metadata_ambiguity_collapsed_to_movement_lane");
|
||||
});
|
||||
|
||||
it("switches the checked year on a short payout follow-up while keeping prior discovery counterparty", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "а теперь за 2021?",
|
||||
|
|
|
|||
|
|
@ -1169,6 +1169,64 @@ describe("assistantTransitionPolicy", () => {
|
|||
expect(carryover?.followupContext?.previous_discovery_metadata_selected_entity_set).toBe("Документ");
|
||||
expect(carryover?.followupContext?.previous_discovery_metadata_ambiguity_detected).toBeUndefined();
|
||||
});
|
||||
it("carries metadata ambiguity entity sets into follow-up context for downstream lane arbitration", () => {
|
||||
const policy = buildPolicy({
|
||||
findLastAddressAssistantItem: () => ({
|
||||
text: "metadata ambiguity",
|
||||
debug: {
|
||||
execution_lane: "living_chat",
|
||||
mcp_discovery_response_applied: true,
|
||||
assistant_mcp_discovery_entry_point_v1: {
|
||||
schema_version: "assistant_mcp_discovery_runtime_entry_point_v1",
|
||||
entry_status: "bridge_executed",
|
||||
turn_input: {
|
||||
turn_meaning_ref: {
|
||||
asked_domain_family: "metadata",
|
||||
asked_action_family: "inspect_documents",
|
||||
explicit_entity_candidates: ["SVK"],
|
||||
explicit_date_scope: "2020"
|
||||
}
|
||||
},
|
||||
bridge: {
|
||||
bridge_status: "answer_draft_ready",
|
||||
business_fact_answer_allowed: true,
|
||||
pilot: {
|
||||
pilot_scope: "metadata_inspection_v1",
|
||||
derived_metadata_surface: {
|
||||
selected_entity_set: null,
|
||||
downstream_route_family: null,
|
||||
ambiguity_detected: true,
|
||||
ambiguity_entity_sets: ["Документ", "РегистрНакопления"]
|
||||
}
|
||||
},
|
||||
answer_draft: {
|
||||
answer_mode: "confirmed_with_bounded_inference"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
hasAddressFollowupContextSignal: () => true,
|
||||
hasReferentialPointer: () => false,
|
||||
resolveAddressIntent: () => ({ intent: "unknown" }),
|
||||
resolveAddressIntentFamily: () => null,
|
||||
resolveAssistantTurnMeaning: () => null
|
||||
});
|
||||
|
||||
const carryover = policy.resolveAddressFollowupCarryoverContext(
|
||||
"по документам",
|
||||
[{ kind: "assistant", text: "metadata ambiguity" }],
|
||||
"по документам",
|
||||
{ predecomposeContract: { intent: "unknown" } },
|
||||
null
|
||||
);
|
||||
|
||||
expect(carryover?.followupContext?.previous_discovery_metadata_ambiguity_detected).toBe(true);
|
||||
expect(carryover?.followupContext?.previous_discovery_metadata_ambiguity_entity_sets).toEqual([
|
||||
"Документ",
|
||||
"РегистрНакопления"
|
||||
]);
|
||||
});
|
||||
it("switches to VAT tax-period intent while preserving carried period filters", () => {
|
||||
const policy = buildPolicy({
|
||||
findLastAddressAssistantItem: () => ({
|
||||
|
|
|
|||
Loading…
Reference in New Issue