ARCH: добавить open-scope totals по организации в MCP discovery
This commit is contained in:
+19
-1
@@ -85,11 +85,17 @@ function comparisonNeedFor(action) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function supportsOrganizationScopedOpenTotal(action) {
|
||||
return action === "turnover" || action === "payout";
|
||||
}
|
||||
function allowsOpenScopeWithoutSubject(input) {
|
||||
if (input.family !== "value_flow") {
|
||||
return false;
|
||||
}
|
||||
return Boolean(input.rankingNeed || input.comparisonNeed === "incoming_vs_outgoing");
|
||||
if (input.rankingNeed || input.comparisonNeed === "incoming_vs_outgoing") {
|
||||
return true;
|
||||
}
|
||||
return Boolean(input.organizationScope && supportsOrganizationScopedOpenTotal(input.action));
|
||||
}
|
||||
function rankingNeedFromRawUtterance(value) {
|
||||
const text = lower(value);
|
||||
@@ -147,6 +153,12 @@ function decompositionCandidatesFor(input) {
|
||||
pushUnique(result, "probe_coverage");
|
||||
return result;
|
||||
}
|
||||
if (input.openScopeWithoutSubject) {
|
||||
pushUnique(result, "collect_scoped_movements");
|
||||
pushUnique(result, input.aggregationNeed === "by_month" ? "aggregate_by_month" : "aggregate_checked_amounts");
|
||||
pushUnique(result, "probe_coverage");
|
||||
return result;
|
||||
}
|
||||
pushUnique(result, "resolve_entity_reference");
|
||||
if (input.action === "net_value_flow") {
|
||||
pushUnique(result, "collect_incoming_movements");
|
||||
@@ -204,6 +216,7 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
|
||||
const rawUtterance = lower(input.rawUtterance);
|
||||
const aggregationAxis = lower(turnMeaning?.asked_aggregation_axis);
|
||||
const explicitDateScope = toNonEmptyString(turnMeaning?.explicit_date_scope);
|
||||
const explicitOrganizationScope = toNonEmptyString(turnMeaning?.explicit_organization_scope);
|
||||
const subjectCandidates = (turnMeaning?.explicit_entity_candidates ?? [])
|
||||
.map((item) => toNonEmptyString(item))
|
||||
.filter((item) => Boolean(item));
|
||||
@@ -219,6 +232,8 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
|
||||
const openScopeWithoutSubject = subjectCandidates.length === 0 &&
|
||||
allowsOpenScopeWithoutSubject({
|
||||
family: businessFactFamily,
|
||||
action,
|
||||
organizationScope: explicitOrganizationScope,
|
||||
comparisonNeed,
|
||||
rankingNeed
|
||||
});
|
||||
@@ -261,6 +276,9 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
|
||||
if (comparisonNeed) {
|
||||
pushReason(reasonCodes, `data_need_graph_comparison_${comparisonNeed}`);
|
||||
}
|
||||
if (openScopeWithoutSubject && !rankingNeed && !comparisonNeed) {
|
||||
pushReason(reasonCodes, "data_need_graph_open_scope_total_without_subject");
|
||||
}
|
||||
if (clarificationGaps.length > 0) {
|
||||
pushReason(reasonCodes, "data_need_graph_has_clarification_gaps");
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ function recipeFor(input) {
|
||||
const graphAction = lower(dataNeedGraph?.action_family);
|
||||
const graphAggregation = lower(dataNeedGraph?.aggregation_need);
|
||||
const graphClarificationGaps = (dataNeedGraph?.clarification_gaps ?? []).map((item) => lower(item));
|
||||
const organizationScope = toNonEmptyString(meaning?.explicit_organization_scope);
|
||||
const combined = `${domain} ${action} ${unsupported}`.trim();
|
||||
const axes = [];
|
||||
const requestedAggregationAxis = aggregationAxis(meaning);
|
||||
@@ -132,6 +133,24 @@ function recipeFor(input) {
|
||||
: "planner_selected_top_ranked_value_flow_from_data_need_graph"
|
||||
};
|
||||
}
|
||||
if (!hasSubjectCandidates(dataNeedGraph) && organizationScope) {
|
||||
pushUnique(axes, "aggregate_axis");
|
||||
pushUnique(axes, "amount");
|
||||
pushUnique(axes, "coverage_target");
|
||||
if (requestedAggregationAxis === "month" || graphAggregation === "by_month") {
|
||||
pushUnique(axes, "calendar_month");
|
||||
}
|
||||
return {
|
||||
semanticDataNeed: "organization-scoped value-flow evidence",
|
||||
chainId: "value_flow",
|
||||
chainSummary: "Query scoped movements for the checked period and organization without a preselected counterparty, aggregate checked amounts, then probe coverage before answering a bounded total.",
|
||||
primitives: ["query_movements", "aggregate_by_axis", "probe_coverage"],
|
||||
axes,
|
||||
reason: requestedAggregationAxis === "month" || graphAggregation === "by_month"
|
||||
? "planner_selected_monthly_open_scope_value_flow_total_from_data_need_graph"
|
||||
: "planner_selected_open_scope_value_flow_total_from_data_need_graph"
|
||||
};
|
||||
}
|
||||
pushUnique(axes, "aggregate_axis");
|
||||
pushUnique(axes, "amount");
|
||||
pushUnique(axes, "coverage_target");
|
||||
|
||||
+17
-2
@@ -305,6 +305,14 @@ function hasBidirectionalValueFlowSignal(text) {
|
||||
function hasValueRankingSignal(text) {
|
||||
return /(?:кто\s+больше\s+всего.*ден[её]г|больше\s+всего.*ден[её]г|прин[её]с.*ден[её]г|сам(?:ый|ая|ое|ые).*(?:доходн|прибыльн)|most.*money|highest\s+(?:revenue|payment))/iu.test(text);
|
||||
}
|
||||
function hasOrganizationScopeSignal(text) {
|
||||
return /(?:\bооо\b|\bип\b|\bао\b|\bпао\b|\bзао\b|\bllc\b|\binc\b|\bcorp\b|\bcompany\b|\borganization\b|\borganisation\b|организац|компан)/iu.test(text);
|
||||
}
|
||||
function hasOrganizationScopeSignalUtf8(text) {
|
||||
return (/(?<!\p{L})(?:\u043e\u043e\u043e|\u0438\u043f|\u0430\u043e|\u043f\u0430\u043e|\u0437\u0430\u043e)(?!\p{L})/iu.test(text) ||
|
||||
/\b(?:llc|inc|corp|company|organization|organisation)\b/iu.test(text) ||
|
||||
/(?:\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446|\u043a\u043e\u043c\u043f\u0430\u043d)/iu.test(text));
|
||||
}
|
||||
function hasMonthlyAggregationSignal(text) {
|
||||
return /(?:\u043f\u043e\s+\u043c\u0435\u0441\u044f\u0446\u0430\u043c|\u043f\u043e\u043c\u0435\u0441\u044f\u0447\u043d\u043e|\u0435\u0436\u0435\u043c\u0435\u0441\u044f\u0447\u043d\u043e|month\s+by\s+month|by\s+month|monthly)/iu.test(text);
|
||||
}
|
||||
@@ -582,8 +590,12 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
||||
const explicitIntentCandidate = toNonEmptyString(assistantTurnMeaning?.explicit_intent_candidate);
|
||||
const assistantTurnMeaningDateScope = toNonEmptyString(assistantTurnMeaning?.explicit_date_scope);
|
||||
const assistantTurnMeaningOrganizationScope = toNonEmptyString(assistantTurnMeaning?.explicit_organization_scope);
|
||||
const rawOpenScopeValueFlowOrganizationSignal = Boolean(rawValueFlowSignal &&
|
||||
!rawBidirectionalValueFlowSignal &&
|
||||
hasOrganizationScopeSignalUtf8(rawText) &&
|
||||
(predecomposeEntities.organization ?? assistantTurnMeaningOrganizationScope));
|
||||
const predecomposeOrganizationMirrorsCounterparty = sameScopedName(predecomposeEntities.counterparty, predecomposeEntities.organization);
|
||||
const organizationMirrorsPredecomposeCounterparty = Boolean((rawBidirectionalValueFlowSignal || hasValueRankingSignal(rawText)) &&
|
||||
const organizationMirrorsPredecomposeCounterparty = Boolean((rawBidirectionalValueFlowSignal || hasValueRankingSignal(rawText) || rawOpenScopeValueFlowOrganizationSignal) &&
|
||||
(sameScopedName(predecomposeEntities.counterparty, assistantTurnMeaningOrganizationScope) ||
|
||||
predecomposeOrganizationMirrorsCounterparty));
|
||||
const normalizedPredecomposeCounterparty = organizationMirrorsPredecomposeCounterparty
|
||||
@@ -829,7 +841,10 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
||||
}
|
||||
const openScopeValueFlowWithoutCounterparty = valueFlowSignal && !normalizedPredecomposeCounterparty && !followupSeed.counterparty;
|
||||
const valueFlowOrganizationStaysScope = openScopeValueFlowWithoutCounterparty &&
|
||||
(bidirectionalValueFlowSignal || hasValueRankingSignal(rawText));
|
||||
Boolean(bidirectionalValueFlowSignal ||
|
||||
hasValueRankingSignal(rawText) ||
|
||||
rawOpenScopeValueFlowOrganizationSignal ||
|
||||
followupSeed.organization);
|
||||
if (openScopeValueFlowWithoutCounterparty && !valueFlowOrganizationStaysScope) {
|
||||
pushUnique(entityCandidates, predecomposeEntities.organization);
|
||||
pushUnique(entityCandidates, followupSeed.organization);
|
||||
|
||||
Reference in New Issue
Block a user