Укрепить семантическую арбитрацию follow-up после жирного прогона

This commit is contained in:
2026-05-08 21:57:41 +03:00
parent ba23b056b8
commit a15cbb3fcb
18 changed files with 898 additions and 37 deletions
@@ -1724,6 +1724,13 @@ function resolveUnicodeAddressIntentBridge(text) {
]).has(byAnchorToken);
const hasMoneyCue = /(?:деньг|денег|выручк|доход|оборот|заработ|прин[её]с|чек|ликвидн|revenue|turnover|money)/iu.test(normalized);
const hasRankingCue = /(?:топ|ранк|сам(?:ый|ая|ое|ые)|больше\s+всего|наибольш|крупн|жирн|max|top|rank)/iu.test(normalized);
const hasSelectedObjectProfitabilityCue = /(?:\u043f\u043e\s+\u0432\u044b\u0431\u0440\u0430\u043d\u043d(?:\u043e\u043c\u0443|\u043e\u0439)\s+(?:\u043e\u0431\u044a\u0435\u043a\u0442\u0443|\u043f\u043e\u0437\u0438\u0446\u0438\u0438)|selected\s+object)/iu.test(normalized) &&
(/(?:\u0437\u0430\u0440\u0430\u0431\u043e\u0442|\u043f\u0440\u0438\u0431\u044b\u043b|\u043c\u0430\u0440\u0436|profit|margin)/iu.test(normalized) ||
(/(?:\u043f\u0440\u043e\u0434\u0430\u0436|sale)/iu.test(normalized) &&
/(?:\u0437\u0430\u043a\u0443\u043f|\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|purchase|document)/iu.test(normalized)));
if (hasSelectedObjectProfitabilityCue) {
return unicodeBridgeResolution("inventory_profitability_for_item", "high", "unicode_selected_object_profitability_bridge_signal_detected");
}
const hasInventoryPurchaseToSaleDocumentChainCue = /(?:закупк[а-яё]*[\s\S]{0,80}склад[\s\S]{0,80}продаж|путь\s+товар[а-яё]*[\s\S]{0,80}закуп|purchase\s*->\s*(?:warehouse|stock)\s*->\s*sale|->\s*(?:склад|warehouse|stock)\s*->\s*(?:продаж|sale))/iu.test(normalized) && /(?:товар|позици|номенклатур|sku|item|product)/iu.test(normalized);
if (hasInventoryPurchaseToSaleDocumentChainCue) {
return unicodeBridgeResolution("inventory_purchase_to_sale_chain", "high", "unicode_inventory_purchase_to_sale_chain_bridge_signal_detected");
@@ -1745,6 +1752,11 @@ function resolveUnicodeAddressIntentBridge(text) {
if (!hasContractCue && hasHighestValueCustomerCue) {
return unicodeBridgeResolution("customer_revenue_and_payments", "high", "unicode_customer_revenue_bridge_signal_detected");
}
const hasCustomerConcentrationCue = /(?:\u043a\u0440\u0443\u043f\u043d\w*|\u043e\u0441\u043d\u043e\u0432\u043d\w*|\u0433\u043b\u0430\u0432\u043d\w*|\u0442\u043e\u043f|top|largest|main|key|concentration|\u043a\u043e\u043d\u0446\u0435\u043d\u0442\u0440\u0430\u0446\w*|\u0437\u0430\u0432\u0438\u0441\w*|\u043e\u0434\u043d(?:\u043e\u0433\u043e|\u043e\u043c\u0443)\s+(?:\u043f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b|\u043a\u043b\u0438\u0435\u043d\u0442))/iu.test(normalized) &&
/(?:\u043a\u043b\u0438\u0435\u043d\u0442|\u043f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b|\u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a|\u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442|customer|client|buyer|counterparty)/iu.test(normalized);
if (!hasContractCue && hasCustomerConcentrationCue) {
return unicodeBridgeResolution("customer_revenue_and_payments", "high", "unicode_customer_concentration_bridge_signal_detected");
}
if (hasOrganizationLevelEarningsOverviewBridgeSignal(normalized)) {
return unicodeBridgeResolution("unknown", "high", "unicode_business_overview_earnings_deferred_to_discovery");
}
@@ -522,6 +522,9 @@ function shouldRestoreInventoryRootFrame(userMessage, intent, extractedFilters,
return hasTemporalPatch;
}
function hasSelectedObjectInventorySignal(text) {
if (/(?:по\s+выбранному\s+объекту|по\s+этой\s+позиции|по\s+этому\s+товару|по\s+ней|по\s+нему|по\s+ним|for\s+selected\s+object|selected\s+object)/iu.test(String(text ?? ""))) {
return true;
}
return /(?:по\s+выбранному\s+объекту|по\s+этой\s+позиции|по\s+этому\s+товару|по\s+ней|по\s+нему|по\s+ним|for\s+selected\s+object|selected\s+object)/iu.test(String(text ?? ""));
}
function hasSelectedObjectInlineSnapshotMetadata(text) {
@@ -590,6 +593,12 @@ function hasAddressFollowupContextSignal(text) {
if (/(?:по\s+выбранному\s+объекту|по\s+этой\s+позиции|по\s+этому\s+товару|по\s+ней|по\s+нему|по\s+ним|for\s+selected\s+object|selected\s+object)/iu.test(normalized)) {
return true;
}
if (/(?:по\s+выбранному\s+объекту|по\s+этой\s+позиции|по\s+этому\s+товару|по\s+ней|по\s+нему|по\s+ним|for\s+selected\s+object|selected\s+object)/iu.test(normalized)) {
return true;
}
if (/(?:^|\s)(?:и|а\s+еще|а\s+ещё|еще|ещё|также|а\s+теперь|теперь|по\s+этому|по\s+тому|это\s+же|в\s+этом|тот\s+же|also|same|that|then|now)/iu.test(normalized)) {
return true;
}
if (hasAllTimeHint(normalized)) {
return true;
}
@@ -1201,7 +1210,17 @@ function deriveIntentWithFollowupContext(detectedIntent, userMessage, followupCo
followupContext.current_frame_kind === "inventory_drilldown";
const inventorySelectedObjectFollowup = inventoryLineageActive &&
(hasSelectedObjectInventorySignal(normalizedMessage) || (previousIsInventoryFamily && hasFollowupSignal));
const previousCounterpartyLaneActive = hasPreviousCounterparty &&
(followupContext.previous_anchor_type === "counterparty" ||
sourceIntent === "list_documents_by_counterparty" ||
sourceIntent === "list_contracts_by_counterparty" ||
sourceIntent === "bank_operations_by_counterparty" ||
sourceIntent === "customer_revenue_and_payments" ||
sourceIntent === "supplier_payouts_profile" ||
sourceIntent === "counterparty_activity_lifecycle" ||
sourceIntent === "open_items_by_counterparty_or_contract");
const hasExplicitInventoryItemReference = /(?:товар|номенклатур|позици|склад|остат|sku|item|product|товар|номенклатур|позици|склад|остат)/iu.test(normalizedMessage) || hasSelectedObjectInlineSnapshotMetadata(normalizedMessage);
const staleInventoryLineageCanYieldToCounterparty = previousCounterpartyLaneActive && !hasExplicitInventoryItemReference;
const inventoryPurchaseDateVatBridge = inventorySelectedObjectFollowup && hasInventoryPurchaseDateVatBridgeCue(normalizedMessage);
if (inventoryPurchaseDateVatBridge &&
(detectedIntent.intent === "unknown" ||
@@ -1236,14 +1255,20 @@ function deriveIntentWithFollowupContext(detectedIntent, userMessage, followupCo
reasons: [...detectedIntent.reasons, "intent_adjusted_to_vat_followup_context"]
};
}
if (!inventoryLineageActive &&
if ((!inventoryLineageActive || staleInventoryLineageCanYieldToCounterparty) &&
hasAnyPartyAnchor &&
!hasExplicitInventoryItemReference &&
detectedIntent.intent === "inventory_purchase_documents_for_item") {
(detectedIntent.intent === "inventory_purchase_documents_for_item" ||
(staleInventoryLineageCanYieldToCounterparty && hasInventoryPurchaseDocumentsFollowupCue(normalizedMessage)))) {
return {
intent: hasPreviousContract && !hasPreviousCounterparty ? "list_documents_by_contract" : "list_documents_by_counterparty",
confidence: "low",
reasons: [...detectedIntent.reasons, "intent_adjusted_from_non_inventory_followup_context"]
reasons: [
...detectedIntent.reasons,
staleInventoryLineageCanYieldToCounterparty
? "intent_adjusted_from_stale_inventory_context_to_counterparty_documents"
: "intent_adjusted_from_non_inventory_followup_context"
]
};
}
const allowOpenItemsFollowupFallback = detectedIntent.intent === "unknown" && !isVatFollowup;
@@ -111,10 +111,11 @@ function isDetectedIntentAlignedWithTurnMeaning(detectedIntent, turnMeaning) {
askedAction === "age_or_activity_duration");
}
if (normalizedIntent === "supplier_payouts_profile") {
return askedDomain === "counterparty_value" && askedAction === "payout";
return (askedDomain === "counterparty_value" || askedDomain === "counterparty") && askedAction === "payout";
}
if (normalizedIntent === "customer_revenue_and_payments") {
return askedDomain === "counterparty_value" && (askedAction === "turnover" || askedAction === "counterparty_value_or_turnover");
return ((askedDomain === "counterparty_value" || askedDomain === "counterparty") &&
(askedAction === "turnover" || askedAction === "counterparty_value_or_turnover"));
}
if (normalizedIntent === "receivables_confirmed_as_of_date") {
return askedDomain === "receivables" || askedAction === "confirmed_snapshot";
@@ -137,6 +138,13 @@ function isDetectedIntentAlignedWithTurnMeaning(detectedIntent, turnMeaning) {
if (normalizedIntent === "inventory_on_hand_as_of_date" || normalizedIntent === "inventory_aging_by_purchase_date") {
return askedDomain === "inventory" && askedAction === "confirmed_snapshot";
}
if (normalizedIntent === "inventory_purchase_provenance_for_item" ||
normalizedIntent === "inventory_purchase_documents_for_item" ||
normalizedIntent === "inventory_sale_trace_for_item" ||
normalizedIntent === "inventory_profitability_for_item" ||
normalizedIntent === "inventory_purchase_to_sale_chain") {
return askedDomain === "inventory";
}
return false;
}
function readDiscoveryTurnMeaning(entryPoint) {
@@ -147,6 +155,34 @@ function readDiscoveryDataNeedGraph(entryPoint) {
const turnInput = toRecordObject(entryPoint?.turn_input);
return toRecordObject(turnInput?.data_need_graph);
}
function isMetadataDiscoveryTurn(entryPoint) {
const turnMeaning = readDiscoveryTurnMeaning(entryPoint);
const graph = readDiscoveryDataNeedGraph(entryPoint);
const bridge = toRecordObject(entryPoint?.bridge);
const pilot = toRecordObject(bridge?.pilot);
const reasonCodes = Array.isArray(entryPoint?.reason_codes) ? entryPoint.reason_codes : [];
return Boolean(toNonEmptyString(turnMeaning?.asked_domain_family) === "metadata" ||
toNonEmptyString(turnMeaning?.unsupported_but_understood_family) === "1c_metadata_surface" ||
toNonEmptyString(graph?.business_fact_family) === "schema_surface" ||
toNonEmptyString(pilot?.pilot_scope) === "metadata_inspection_v1" ||
reasonCodes.some((reason) => toNonEmptyString(reason) === "mcp_discovery_metadata_signal_detected"));
}
function isInventoryExactAddressIntent(intent) {
return /^(?:inventory_purchase_provenance_for_item|inventory_purchase_documents_for_item|inventory_sale_trace_for_item|inventory_profitability_for_item|inventory_purchase_to_sale_chain|inventory_aging_by_purchase_date|inventory_on_hand_as_of_date)$/u.test(String(intent ?? ""));
}
function hasMetadataDiscoveryPriority(input, entryPoint) {
if (!isDiscoveryReadyAddressCandidate(input, entryPoint)) {
return false;
}
if (!hasEffectivelyFactualAddressReply(input)) {
return false;
}
if (!isMetadataDiscoveryTurn(entryPoint)) {
return false;
}
const detectedIntent = toNonEmptyString(input.addressRuntimeMeta?.detected_intent);
return !isInventoryExactAddressIntent(detectedIntent);
}
function isOpenScopeValueFlowWithoutSubject(entryPoint) {
const graph = readDiscoveryDataNeedGraph(entryPoint);
const businessFactFamily = toNonEmptyString(graph?.business_fact_family);
@@ -224,6 +260,26 @@ function hasValueFlowActionConflictWithDiscoveryTurnMeaning(input, entryPoint) {
}
return false;
}
function hasEvidenceLaneConflictWithDiscoveryTurnMeaning(input, entryPoint) {
if (!isDiscoveryReadyAddressCandidate(input, entryPoint)) {
return false;
}
if (!hasEffectivelyFactualAddressReply(input)) {
return false;
}
const turnMeaning = readDiscoveryTurnMeaning(entryPoint);
const askedDomain = toNonEmptyString(turnMeaning?.asked_domain_family);
const askedAction = toNonEmptyString(turnMeaning?.asked_action_family);
const detectedIntent = toNonEmptyString(input.addressRuntimeMeta?.detected_intent);
if (!detectedIntent) {
return false;
}
const asksForMovements = askedDomain === "movements" || askedAction === "list_movements";
const asksForDocuments = askedDomain === "documents" || askedAction === "list_documents";
const detectedDocumentsLane = detectedIntent === "list_documents_by_counterparty" || detectedIntent === "list_documents_by_contract";
const detectedCashLane = detectedIntent === "bank_operations_by_counterparty" || detectedIntent === "bank_operations_by_contract";
return (asksForMovements && detectedDocumentsLane) || (asksForDocuments && detectedCashLane);
}
function hasExactMatchedFactualAddressReply(input, entryPoint) {
if (!isDiscoveryReadyAddressCandidate(input, entryPoint)) {
return false;
@@ -234,9 +290,15 @@ function hasExactMatchedFactualAddressReply(input, entryPoint) {
if (hasOpenScopeValueFlowDiscoveryPriority(input, entryPoint)) {
return false;
}
if (hasMetadataDiscoveryPriority(input, entryPoint)) {
return false;
}
if (hasValueFlowActionConflictWithDiscoveryTurnMeaning(input, entryPoint)) {
return false;
}
if (hasEvidenceLaneConflictWithDiscoveryTurnMeaning(input, entryPoint)) {
return false;
}
const mcpCallStatus = toNonEmptyString(input.addressRuntimeMeta?.mcp_call_status);
const truthMode = toNonEmptyString(input.addressRuntimeMeta?.truth_mode);
const selectedRecipe = toNonEmptyString(input.addressRuntimeMeta?.selected_recipe);
@@ -267,6 +329,12 @@ function hasRuntimeAdjustedExactReply(input, entryPoint) {
if (!hasEffectivelyFactualAddressReply(input)) {
return false;
}
if (hasMetadataDiscoveryPriority(input, entryPoint)) {
return false;
}
if (hasEvidenceLaneConflictWithDiscoveryTurnMeaning(input, entryPoint)) {
return false;
}
const truthGateStatus = toNonEmptyString(input.addressRuntimeMeta?.truth_gate_contract_status);
const truthAnswerPolicy = toRecordObject(input.addressRuntimeMeta?.assistant_truth_answer_policy_v1);
const truthGate = toRecordObject(truthAnswerPolicy?.truth_gate);
@@ -293,6 +361,9 @@ function hasAlignedFactualAddressReply(input, entryPoint) {
if (!hasEffectivelyFactualAddressReply(input)) {
return false;
}
if (hasMetadataDiscoveryPriority(input, entryPoint)) {
return false;
}
if (hasSemanticConflictWithDiscoveryTurnMeaning(input, entryPoint)) {
return false;
}
@@ -323,6 +394,9 @@ function hasSemanticConflictWithDiscoveryTurnMeaning(input, entryPoint) {
if (needsOpenScopeValueFlowOrganizationClarification(entryPoint)) {
return true;
}
if (hasMetadataDiscoveryPriority(input, entryPoint)) {
return true;
}
if (detectedIntent === "customer_revenue_and_payments" &&
isOpenScopeValueFlowWithoutSubject(entryPoint)) {
return true;
@@ -336,6 +410,9 @@ function hasMatchedFactualAddressContinuationTarget(input, entryPoint) {
if (hasSemanticConflictWithDiscoveryTurnMeaning(input, entryPoint)) {
return false;
}
if (hasMetadataDiscoveryPriority(input, entryPoint)) {
return false;
}
const detectedIntent = toNonEmptyString(input.addressRuntimeMeta?.detected_intent);
const dialogContinuationContract = toRecordObject(input.addressRuntimeMeta?.dialogContinuationContract) ??
toRecordObject(input.addressRuntimeMeta?.dialog_continuation_contract_v2);
@@ -373,6 +450,9 @@ function hasFullConfirmedFactualAddressReply(input, entryPoint) {
if (hasSemanticConflictWithDiscoveryTurnMeaning(input, entryPoint)) {
return false;
}
if (hasMetadataDiscoveryPriority(input, entryPoint)) {
return false;
}
const truthGateStatus = toNonEmptyString(input.addressRuntimeMeta?.truth_gate_contract_status);
if (truthGateStatus === "full_confirmed") {
return true;
@@ -403,7 +483,9 @@ function applyAssistantMcpDiscoveryResponsePolicy(input) {
const exactMatchedFactualAddressReply = hasExactMatchedFactualAddressReply(input, entryPoint);
const runtimeAdjustedExactReply = hasRuntimeAdjustedExactReply(input, entryPoint);
const openScopeValueFlowDiscoveryPriority = hasOpenScopeValueFlowDiscoveryPriority(input, entryPoint);
const metadataDiscoveryPriority = hasMetadataDiscoveryPriority(input, entryPoint);
const valueFlowActionConflictWithDiscoveryTurnMeaning = hasValueFlowActionConflictWithDiscoveryTurnMeaning(input, entryPoint);
const evidenceLaneConflictWithDiscoveryTurnMeaning = hasEvidenceLaneConflictWithDiscoveryTurnMeaning(input, entryPoint);
if (!entryPoint) {
pushReason(reasonCodes, "mcp_discovery_response_policy_no_entry_point");
}
@@ -428,9 +510,15 @@ function applyAssistantMcpDiscoveryResponsePolicy(input) {
if (valueFlowActionConflictWithDiscoveryTurnMeaning) {
pushReason(reasonCodes, "mcp_discovery_response_policy_value_flow_action_conflict_allows_candidate_override");
}
if (evidenceLaneConflictWithDiscoveryTurnMeaning) {
pushReason(reasonCodes, "mcp_discovery_response_policy_evidence_lane_conflict_allows_candidate_override");
}
if (openScopeValueFlowDiscoveryPriority) {
pushReason(reasonCodes, "mcp_discovery_response_policy_open_scope_value_flow_candidate_priority");
}
if (metadataDiscoveryPriority) {
pushReason(reasonCodes, "mcp_discovery_response_policy_metadata_candidate_priority");
}
if (matchedFactualAddressContinuationTarget) {
pushReason(reasonCodes, "mcp_discovery_response_policy_keep_factual_address_continuation_target");
}
@@ -105,6 +105,23 @@ function isGarbageSemanticAnchorCandidate(value) {
}
const compact = (0, addressTextRepair_1.normalizeRussianComparableText)(text);
if (new Set([
"для",
"по",
"ему",
"нему",
"ней",
"этой",
"этому",
"этим",
"этими",
"данным",
"данными",
"документам",
"документами",
"движение",
"движения",
"движениям",
"операциям",
"данным",
"этим",
"этими",
@@ -20,6 +20,45 @@ function hasImplicitHistoricalCapabilityMetaSignal(samples) {
return samples.some((sample) => /(?:историческ|история|архив|раньше|ретро|старые\s+данные)/iu.test(sample) &&
/(?:мож(?:ешь|ем|но)|уме(?:ешь|ете))/iu.test(sample));
}
function normalizedSampleText(value) {
return String(value ?? "")
.toLowerCase()
.replace(/\s+/g, " ")
.replace(/\u0451/gu, "\u0435")
.trim();
}
function hasSchemaDataScopeMetaSignal(samples) {
return samples.some((sample) => {
const text = normalizedSampleText(sample);
if (!text) {
return false;
}
const hasOneCOrSchemaCue = /(?:\b1\s*[cс]\b|1с|metadata|schema|схем|структур|метаданн)/iu.test(text);
const hasSchemaObjectCue = /(?:справочник|справочники|регистр|регистры|объект(?:ы|ов)?|пол[ея]|связ[ьи]|реквизит|таблиц|раздел(?:ы|ов)?|catalog|register|object|field|relation|link)/iu.test(text);
const hasDirectSchemaQuestion = /(?:какие\s+(?:справочник|справочники|регистры|объекты|поля|связи|реквизиты)|где\s+(?:лежат|хранятся).*(?:данные|поля)|что\s+есть\s+в\s+1с\s+по)/iu.test(text);
const hasDocumentSchemaQuestion = /(?:какие\s+(?:поля|связи|реквизиты).{0,80}(?:документ|реализац|поступлен)|(?:документ|реализац|поступлен).{0,80}(?:поля|связи|реквизиты))/iu.test(text);
return (hasOneCOrSchemaCue && hasSchemaObjectCue) || hasDirectSchemaQuestion || hasDocumentSchemaQuestion;
});
}
function hasBusinessBoundaryQuestionSignal(samples) {
return samples.some((sample) => {
const text = normalizedSampleText(sample);
if (!text) {
return false;
}
const hasClassificationCue = /(?:можно\s+ли\s+считать|это\s+можно\s+считать|как\s+считать|классифиц|объясни\s+аккуратно|это\s+уже|это\s+пока|can\s+this\s+be\s+treated)/iu.test(text);
const hasBusinessObjectCue = /(?:просроч|открыт\w*\s+задолж|долг|дебитор|кредитор|ликвид|резерв|неликвид|склад|прибыл|марж|оборот|контрагент|покупател|поставщик|overdue|debt|receivable|payable|stock|profit|margin)/iu.test(text);
return hasClassificationCue && hasBusinessObjectCue;
});
}
function hasContextIntegrityInspectionSignal(samples) {
return samples.some((sample) => {
const text = normalizedSampleText(sample);
return Boolean(text &&
/(?:проверь\s+себя|не\s+смешал|не\s+перепутал|правильно\s+ли\s+контур|объясни\s+контур|self[-\s]?check)/iu.test(text) &&
/(?:контрагент|организац|компан|контур|scope|counterparty|organization|company)/iu.test(text));
});
}
function createAssistantMetaFollowupPolicy(deps) {
function resolveMetaSignalSet(input) {
const samples = collectMessageSamples(input);
@@ -31,12 +70,17 @@ function createAssistantMetaFollowupPolicy(deps) {
answerInspectionFollowupSignal: false
};
}
const dataScopeMetaQuery = hasSignalAcrossSamples(samples, deps.hasAssistantDataScopeMetaQuestionSignal) ||
hasSchemaDataScopeMetaSignal(samples);
const businessBoundaryQuestion = hasBusinessBoundaryQuestionSignal(samples);
return {
dataScopeMetaQuery: hasSignalAcrossSamples(samples, deps.hasAssistantDataScopeMetaQuestionSignal),
capabilityMetaQuery: hasSignalAcrossSamples(samples, deps.shouldHandleAsAssistantCapabilityMetaQuery) ||
hasImplicitHistoricalCapabilityMetaSignal(samples),
dataScopeMetaQuery,
capabilityMetaQuery: !businessBoundaryQuestion &&
(hasSignalAcrossSamples(samples, deps.shouldHandleAsAssistantCapabilityMetaQuery) ||
hasImplicitHistoricalCapabilityMetaSignal(samples)),
metaAnswerFollowupSignal: hasSignalAcrossSamples(samples, deps.hasMetaAnswerFollowupSignal),
answerInspectionFollowupSignal: hasSignalAcrossSamples(samples, deps.hasAnswerInspectionFollowupSignal)
answerInspectionFollowupSignal: hasSignalAcrossSamples(samples, deps.hasAnswerInspectionFollowupSignal) ||
hasContextIntegrityInspectionSignal(samples)
};
}
function resolveHardMetaMode(input) {
@@ -3,11 +3,32 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAssistantTurnMeaningPolicy = createAssistantTurnMeaningPolicy;
const SUPPORTED_ADDRESS_INTENTS = new Set([
"period_coverage_profile",
"document_type_and_account_section_profile",
"counterparty_population_and_roles",
"counterparty_activity_lifecycle",
"receivables_confirmed_as_of_date",
"payables_confirmed_as_of_date",
"list_documents_by_counterparty",
"bank_operations_by_counterparty",
"list_contracts_by_counterparty",
"customer_revenue_and_payments",
"supplier_payouts_profile",
"open_contracts_confirmed_as_of_date",
"list_open_contracts",
"open_items_by_counterparty_or_contract",
"list_payables_counterparties",
"list_receivables_counterparties",
"inventory_on_hand_as_of_date",
"inventory_purchase_provenance_for_item",
"inventory_purchase_documents_for_item",
"inventory_supplier_stock_overlap_as_of_date",
"inventory_sale_trace_for_item",
"inventory_profitability_for_item",
"inventory_purchase_to_sale_chain",
"inventory_aging_by_purchase_date",
"contract_usage_overview",
"contract_usage_and_value",
"vat_liability_confirmed_for_tax_period",
"vat_payable_confirmed_as_of_date",
"vat_payable_forecast"
@@ -115,6 +136,17 @@ function detectCounterpartyTurnoverFamily(text) {
function hasExplicitCounterpartyValueObject(text) {
return /(?:\u043a\u043b\u0438\u0435\u043d\u0442|\u043f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b|\u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a|\u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442|\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a|\u0434\u043e\u0433\u043e\u0432\u043e\u0440|\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442|\u0442\u043e\u0432\u0430\u0440|\u043d\u043e\u043c\u0435\u043d\u043a\u043b\u0430\u0442\u0443\u0440|\u0441\u0434\u0435\u043b\u043a|customer|client|counterparty|supplier|vendor|contract|item|product|deal)/iu.test(text);
}
function hasSelectedObjectInventoryExactSignal(text) {
const normalized = String(text ?? "");
if (!normalized) {
return false;
}
const hasSelectedObjectCue = /(?:\u043f\u043e\s+\u0432\u044b\u0431\u0440\u0430\u043d\u043d(?:\u043e\u043c\u0443|\u043e\u0439)\s+(?:\u043e\u0431\u044a\u0435\u043a\u0442\u0443|\u043f\u043e\u0437\u0438\u0446\u0438\u0438)|selected\s+object|\u043f\u043e\s+\u044d\u0442(?:\u043e\u0439|\u043e\u043c\u0443)\s+(?:\u043f\u043e\u0437\u0438\u0446\u0438\u0438|\u0442\u043e\u0432\u0430\u0440\u0443))/iu.test(normalized);
if (!hasSelectedObjectCue) {
return false;
}
return /(?:\u0437\u0430\u0440\u0430\u0431\u043e\u0442|\u043f\u0440\u0438\u0431\u044b\u043b|\u043c\u0430\u0440\u0436|\u043f\u0440\u043e\u0434\u0430\u0436|\u043f\u0440\u043e\u0434\u0430\u043b|\u0437\u0430\u043a\u0443\u043f|\u043f\u043e\u043a\u0443\u043f|\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|\u0446\u0435\u043f\u043e\u0447|profit|margin|sale|purchase|document)/iu.test(normalized);
}
function hasOrganizationLevelEarningsOverviewSignal(text) {
const normalized = String(text ?? "");
if (!normalized || hasExplicitCounterpartyValueObject(normalized)) {
@@ -138,6 +170,25 @@ function hasOrganizationLevelDebtDueDateOverviewSignal(text) {
const hasCompanyScopeCue = /(?:\u0443\s+\u043d\u0430\u0441|\u043d\u0430\u0448\w*|\u043f\u043e\s+\u043a\u043e\u043c\u043f\u0430\u043d|\u043a\u043e\u043c\u043f\u0430\u043d|\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446|\u0431\u0438\u0437\u043d\u0435\u0441|\u0432\s+\u0446\u0435\u043b\u043e\u043c|\u043e\u0431\u0449\w*|\u043a\u0430\u043a\w*|\u043f\u043e\u043a\u0430\u0436|\u0434\u0430\u0439|\u0441\u0440\u0435\u0437|\u0430\u043d\u0430\u043b\u0438\u0437|(?:19|20)\d{2}|company|business|organization|overall|our|we|us|show|give|analysis)/iu.test(normalized);
return hasDueDateDebtCue && hasCompanyScopeCue;
}
function hasOrganizationLevelDebtPositionOverviewSignal(text) {
const normalized = String(text ?? "");
if (!normalized) {
return false;
}
const hasReceivablesCue = /(?:\u0434\u0435\u0431\u0438\u0442\u043e\u0440\w*|\u043a\u0442\u043e\s+\u043d\u0430\u043c\s+\u0434\u043e\u043b\u0436|\u043d\u0430\u043c\s+\u0434\u043e\u043b\u0436\w*|receivables?|accounts\s+receivable)/iu.test(normalized);
const hasPayablesCue = /(?:\u043a\u0440\u0435\u0434\u0438\u0442\u043e\u0440\w*|\u043a\u043e\u043c\u0443\s+\u043c\u044b\s+\u0434\u043e\u043b\u0436|\u043c\u044b\s+\u0434\u043e\u043b\u0436\w*|payables?|accounts\s+payable)/iu.test(normalized);
const hasOverviewCue = /(?:\u0441\u0440\u0435\u0437|\u043f\u043e\u0437\u0438\u0446\w*|\u0431\u0430\u043b\u0430\u043d\u0441|\u0441\u0430\u043b\u044c\u0434\u043e|\u043d\u0435\u0442\u0442\u043e|\u043d\u0430\s+\u0441\u0435\u0433\u043e\u0434\u043d|\u043d\u0430\s+\u0434\u0430\u0442\u0443|\u0443\s+\u043d\u0430\u0441|\u043f\u043e\s+\u043a\u043e\u043c\u043f\u0430\u043d|\u043a\u043e\u043c\u043f\u0430\u043d|\u0431\u0438\u0437\u043d\u0435\u0441|\u043e\u0431\u0437\u043e\u0440|\u0430\u043d\u0430\u043b\u0438\u0437|as\s+of|overview|balance|net|company|business)/iu.test(normalized);
return hasReceivablesCue && hasPayablesCue && hasOverviewCue;
}
function hasDebtClassificationFollowupSignal(text) {
const normalized = String(text ?? "");
if (!normalized) {
return false;
}
const hasClassificationCue = /(?:\u043c\u043e\u0436\u043d\u043e\s+\u043b\u0438\s+\u0441\u0447\u0438\u0442\u0430\u0442\u044c|\u044d\u0442\u043e\s+\u043c\u043e\u0436\u043d\u043e\s+\u0441\u0447\u0438\u0442\u0430\u0442\u044c|\u044d\u0442\u043e\s+\u0441\u0447\u0438\u0442\u0430\u0442\u044c|\u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446|\u0447\u0442\u043e\s+\u044d\u0442\u043e|can\s+this\s+be\s+treated)/iu.test(normalized);
const hasDebtCue = /(?:\u043f\u0440\u043e\u0441\u0440\u043e\u0447|\u043e\u0442\u043a\u0440\u044b\u0442\w*\s+\u0437\u0430\u0434\u043e\u043b\u0436|\u0434\u043e\u043b\u0433|\u0434\u0435\u0431\u0438\u0442\u043e\u0440|\u043a\u0440\u0435\u0434\u0438\u0442\u043e\u0440|overdue|open\s+debt|receivable|payable)/iu.test(normalized);
return hasClassificationCue && hasDebtCue;
}
function hasOrganizationLevelInventoryReserveLiquidationOverviewSignal(text) {
const normalized = String(text ?? "");
if (!normalized) {
@@ -201,6 +252,16 @@ function detectBroadBusinessEvaluation(text) {
family: "broad_business_evaluation"
};
}
if (hasOrganizationLevelDebtPositionOverviewSignal(normalized)) {
return {
family: "broad_business_evaluation"
};
}
if (hasDebtClassificationFollowupSignal(normalized)) {
return {
family: "broad_business_evaluation"
};
}
if (hasOrganizationLevelInventoryReserveLiquidationOverviewSignal(normalized)) {
return {
family: "broad_business_evaluation"
@@ -239,7 +300,8 @@ function createAssistantTurnMeaningPolicy(deps = {}) {
const joinedText = fallbackCompactWhitespace(`${rawText} ${effectiveText}`);
const supportedIntent = detectSupportedIntent(joinedText, deps);
const counterpartyTurnover = detectCounterpartyTurnoverFamily(joinedText);
const broadBusinessEvaluation = detectBroadBusinessEvaluation(joinedText);
const selectedObjectInventoryExact = hasSelectedObjectInventoryExactSignal(joinedText);
const broadBusinessEvaluation = selectedObjectInventoryExact ? null : detectBroadBusinessEvaluation(joinedText);
const llmIntent = toNonEmptyString(input?.llmPreDecomposeMeta?.predecomposeContract?.intent, deps);
const explicitIntentCandidate = broadBusinessEvaluation?.family
? null
@@ -287,17 +349,20 @@ function createAssistantTurnMeaningPolicy(deps = {}) {
? "confirmed_snapshot"
: broadBusinessEvaluation?.family
? "broad_evaluation"
: explicitIntentCandidate === "vat_liability_confirmed_for_tax_period"
? "confirmed_tax_period"
: explicitIntentCandidate === "vat_payable_confirmed_as_of_date"
? "confirmed_snapshot"
: explicitIntentCandidate === "vat_payable_forecast"
? "forecast"
: explicitIntentCandidate === "list_documents_by_counterparty"
? "list_documents"
: counterpartyTurnover?.family
? "counterparty_value_or_turnover"
: null;
: explicitIntentCandidate === "customer_revenue_and_payments" ||
explicitIntentCandidate === "supplier_payouts_profile"
? "counterparty_value_or_turnover"
: explicitIntentCandidate === "vat_liability_confirmed_for_tax_period"
? "confirmed_tax_period"
: explicitIntentCandidate === "vat_payable_confirmed_as_of_date"
? "confirmed_snapshot"
: explicitIntentCandidate === "vat_payable_forecast"
? "forecast"
: explicitIntentCandidate === "list_documents_by_counterparty"
? "list_documents"
: counterpartyTurnover?.family
? "counterparty_value_or_turnover"
: null;
const staleReplayForbidden = Boolean(unsupportedFamily || broadBusinessEvaluation?.family || (counterpartyTurnover?.entity && !explicitIntentCandidate));
return {
schema_version: "assistant_turn_meaning_v1",