ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.12.23: декомпозиция deep-turn пайплайна ассистента в runtime-адаптеры
This commit is contained in:
@@ -667,6 +667,13 @@ function hasLifecycleSegmentationSignal(text: string): boolean {
|
||||
}
|
||||
|
||||
function hasCounterpartyActivityLifecycleSignal(text: string): boolean {
|
||||
const hasPaymentRiskLexeme =
|
||||
/(?:не\s+плат(?:ит|ят|ил|или)|без\s+оплат|оплат(?:ы|а)?\s+нет|нет\s+оплат|задерж(?:ива|к)|просроч|долг|задолж)/iu.test(
|
||||
text
|
||||
);
|
||||
if (hasPaymentRiskLexeme) {
|
||||
return false;
|
||||
}
|
||||
if ((hasDocumentSignal(text) || hasBankOperationSignal(text)) && !hasLifecycleSegmentationSignal(text)) {
|
||||
return false;
|
||||
}
|
||||
@@ -768,6 +775,10 @@ function hasCustomerRevenueAndPaymentsSignal(text: string): boolean {
|
||||
);
|
||||
const asksRevenueTotal = /(?:сколько|скока|скок).*(?:денег|выручк|доход|заработ|оборот)/iu.test(text);
|
||||
const asksOverallTurnover = /(?:общ(?:ий|ие|ая)\s+оборот|общ(?:ая|ий)\s+выручк|total\s+turnover|turnover\s+total)/iu.test(text);
|
||||
const asksMajorShare =
|
||||
/(?:основн(?:ую|ая|ые|ой)\s+част|больш(?:ую|ая|ие)\s+част|львин(?:ая|ую)\s+дол[яю]|ключев(?:ую|ая)\s+част)/iu.test(
|
||||
text
|
||||
);
|
||||
const asksValue =
|
||||
/(?:доходн|выручк|приход|поступлен|входящ|зачислен|оплат|плат(?:еж|ёж|ежн|ежей|ежа|ит|ят)|деньг|денег|заработ|оборот|чек|сделк|бюджет|занес|занёс|принес|принёс|revenue|inflow|deal|turnover)/iu.test(
|
||||
text
|
||||
@@ -797,6 +808,9 @@ function hasCustomerRevenueAndPaymentsSignal(text: string): boolean {
|
||||
if (asksCounterpartySource && asksValue) {
|
||||
return true;
|
||||
}
|
||||
if (!hasFuzzySupplierLexeme && (asksCustomerGroup || hasCounterpartyLexeme) && asksMajorShare && asksValue) {
|
||||
return true;
|
||||
}
|
||||
if (!hasFuzzySupplierLexeme && asksIncomingFlow && asksRankOrTop) {
|
||||
return true;
|
||||
}
|
||||
@@ -920,6 +934,71 @@ function hasOpenContractsListSignal(text: string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
function hasSupplierTailRiskSignal(text: string): boolean {
|
||||
const hasSupplier = /(?:поставщик|supplier|vendor)/iu.test(text);
|
||||
const hasTail = /(?:хвост|висят|незакрыт|задолж|долг|просроч)/iu.test(text);
|
||||
const hasRisk = /(?:систематич|регулярн|проблем|тревог|не\s+разов|больше\s+похож)/iu.test(text);
|
||||
const hasPeriodCue = /(?:на\s+конец\s+(?:месяц|период)|конец\s+месяц|пару\s+месяц|несколько\s+месяц)/iu.test(text);
|
||||
return hasSupplier && hasTail && (hasRisk || hasPeriodCue);
|
||||
}
|
||||
|
||||
function hasReceivablesLatencyRiskSignal(text: string): boolean {
|
||||
const hasBuyer = /(?:покупател|клиент|заказчик|customer|buyer)/iu.test(text);
|
||||
const hasCounterparty = /(?:контрагент|counterparty|partner)/iu.test(text);
|
||||
const hasPayment = /(?:оплат|платеж|платёж|payment)/iu.test(text);
|
||||
const hasShipment = /(?:отправк|отгруз|реализ|shipment|delivery)/iu.test(text);
|
||||
const hasDelay = /(?:длинн|долг|просроч|задерж|висят|тревог|too\s+long|late)/iu.test(text);
|
||||
const hasNonPayment = /(?:не\s+плат(?:ит|ят|ил|или)|без\s+оплат|оплат(?:ы|а)?\s+нет|нет\s+оплат|неоплач)/iu.test(text);
|
||||
const hasPeriodOrRiskCue = /(?:за\s+текущ|на\s+конец|тревог|просроч|задерж|долг|длинн)/iu.test(text);
|
||||
const hasBetweenShipmentAndPayment =
|
||||
/между[\s\S]{0,80}(?:отправк|отгруз|реализ)[\s\S]{0,80}(?:оплат|платеж|платёж|payment)/iu.test(text);
|
||||
if (hasBuyer && hasPayment && ((hasShipment && hasDelay) || hasBetweenShipmentAndPayment)) {
|
||||
return true;
|
||||
}
|
||||
return (hasBuyer || hasCounterparty) && hasNonPayment && hasPeriodOrRiskCue;
|
||||
}
|
||||
|
||||
function hasSettlementGapSignal(text: string): boolean {
|
||||
const hasPayment = /(?:платеж|платёж|оплат|списани|поступлен|payment)/iu.test(text);
|
||||
const hasDocument = /(?:док(?:и|умент|ументы|ументов)|docs?|documents?)/iu.test(text);
|
||||
const hasAdvance = /(?:аванс|предоплат)/iu.test(text);
|
||||
const hasNoDocumentForClosing =
|
||||
/(?:нет|без)\s+(?:док(?:и|умент|ументы|ументов)|закрывающ)/iu.test(text) &&
|
||||
/(?:закрыти|взаиморасч|акт)/iu.test(text);
|
||||
const hasNoDocumentForClosingReversed =
|
||||
/(?:док(?:и|умент|ументы|ументов)|закрывающ)[\s\S]{0,48}(?:нет|без)/iu.test(text) &&
|
||||
/(?:закрыти|взаиморасч|акт)/iu.test(text);
|
||||
const hasNoPayments =
|
||||
/(?:нет|без)\s+(?:оплат|платеж|платёж|payment)/iu.test(text) ||
|
||||
/(?:оплат|платеж|платёж|payment)\s+нет/iu.test(text);
|
||||
const hasDocsWithoutPayments = hasDocument && hasNoPayments;
|
||||
const hasPaymentsWithoutClosingDocs = hasPayment && (hasNoDocumentForClosing || hasNoDocumentForClosingReversed);
|
||||
const hasUnclosedAdvanceGap =
|
||||
hasAdvance &&
|
||||
(/(?:не\s+закрыт|незакрыт|долго\s+не\s+закрыт|давно\s+не\s+закрыт)/iu.test(text) ||
|
||||
hasNoDocumentForClosing ||
|
||||
hasNoDocumentForClosingReversed);
|
||||
return hasPaymentsWithoutClosingDocs || hasDocsWithoutPayments || hasUnclosedAdvanceGap;
|
||||
}
|
||||
|
||||
function hasReconciliationMismatchSignal(text: string): boolean {
|
||||
const hasCounterparty =
|
||||
/(?:контрагент|поставщик|клиент|покупател|customer|supplier|counterparty)/iu.test(text);
|
||||
const hasReconciliationLexeme = /(?:акт(?:а|ом|ах)?\s+свер(?:к|ок)|свер(?:к|ок))/iu.test(text);
|
||||
const hasMismatchLexeme =
|
||||
/(?:не\s+совпад|несовпад|расхожд|расход|не\s+сход|несход|разъех|разниц|не\s+бь[её]т)/iu.test(text);
|
||||
const hasBalanceLexeme = /(?:сальд|остат|баланс|saldo|balance)/iu.test(text);
|
||||
const hasLookupVerb = /(?:покажи|выведи|найд[иь]|show|list)/iu.test(text);
|
||||
const hasInterrogativeLookup = /(?:по\s+каким|у\s+кого|какие|какой|кто|где)/iu.test(text);
|
||||
return (
|
||||
hasCounterparty &&
|
||||
hasReconciliationLexeme &&
|
||||
hasMismatchLexeme &&
|
||||
hasBalanceLexeme &&
|
||||
(hasLookupVerb || hasInterrogativeLookup)
|
||||
);
|
||||
}
|
||||
|
||||
function isLikelyCounterpartyToken(rawToken: string): boolean {
|
||||
const token = String(rawToken ?? "").trim().toLowerCase();
|
||||
if (!token || token.length < 2) {
|
||||
@@ -1273,6 +1352,38 @@ export function resolveAddressIntent(userMessage: string): AddressIntentResoluti
|
||||
};
|
||||
}
|
||||
|
||||
if (hasSettlementGapSignal(text)) {
|
||||
return {
|
||||
intent: "list_open_contracts",
|
||||
confidence: "medium",
|
||||
reasons: ["settlement_gap_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasReconciliationMismatchSignal(text)) {
|
||||
return {
|
||||
intent: "list_open_contracts",
|
||||
confidence: "medium",
|
||||
reasons: ["reconciliation_mismatch_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasReceivablesLatencyRiskSignal(text)) {
|
||||
return {
|
||||
intent: "list_receivables_counterparties",
|
||||
confidence: "medium",
|
||||
reasons: ["receivables_payment_lag_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasSupplierTailRiskSignal(text)) {
|
||||
return {
|
||||
intent: "list_payables_counterparties",
|
||||
confidence: "medium",
|
||||
reasons: ["supplier_tail_risk_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasDocumentsFormingBalanceSignal(text) && hasDocumentsFormingBalanceAccountAnchor(text)) {
|
||||
return {
|
||||
intent: "documents_forming_balance",
|
||||
@@ -1299,7 +1410,9 @@ export function resolveAddressIntent(userMessage: string): AddressIntentResoluti
|
||||
|
||||
if (
|
||||
hasAny(text, OPEN_ITEMS_HINTS) &&
|
||||
(text.includes("контраг") || text.includes("договор") || text.includes("контракт") || text.includes("counterparty") || text.includes("contract"))
|
||||
/(?:контраг|договор|контракт|counterparty|contract|покупател|клиент|заказчик|customer|client|buyer|supplier|поставщик)/iu.test(
|
||||
text
|
||||
)
|
||||
) {
|
||||
return {
|
||||
intent: "open_items_by_counterparty_or_contract",
|
||||
|
||||
Reference in New Issue
Block a user