Починить проверку цепочки поставщик товар покупатель
This commit is contained in:
@@ -1372,6 +1372,8 @@ function extractInventorySupplierAnchor(text) {
|
||||
}
|
||||
const candidate = cleanupAnchorValue(cleanupAnchorValue(String(match[1]))
|
||||
.replace(/\s+(?:сейчас|на\s+склад(?:е|у|ом)?|на\s+дату|по\s+состоянию\s+на\s+дату|котор(?:ый|ые|ых)|куплен(?:ы|а|о)?|были|был|лежат|лежит|еще|ещё|организац\w*|компани\w*).*$/iu, "")
|
||||
.replace(/\s+к\s+покупател\p{L}*[\s\S]*$/iu, "")
|
||||
.replace(/\s+через\s+товар\p{L}*[\s\S]*$/iu, "")
|
||||
.replace(/\s*(?:->|=>|→)\s*(?:товар|позици|номенклатур|item|product|sku)[\s\S]*$/iu, ""));
|
||||
if (!candidate ||
|
||||
isLowQualityCounterpartyAnchorValue(candidate) ||
|
||||
|
||||
+93
-3
@@ -1576,6 +1576,45 @@ function isQuestionFragmentPartyAnchor(value) {
|
||||
return /(?:^| )(?:что|кто|какие|какой|сколько|сейчас)(?: |$)/iu.test(normalized) ||
|
||||
/(?:на складе|нам должен|кому мы должны|по этой компании|по этой же компании|по ней)/iu.test(normalized);
|
||||
}
|
||||
function extractInventoryDocumentaryChainBuyerAnchor(value) {
|
||||
const source = String(value ?? "");
|
||||
const patterns = [
|
||||
/(?:->|=>|→)\s*(?:покупател\p{L}*|buyer)\s+([^\r\n?]+?)(?=$|[?])/iu,
|
||||
/(?:^|[\s,.;:!?])(?:к\s+покупател\p{L}*|покупател\p{L}*|buyer)\s+(.+?)(?=\s+через\s+(?:товар|item|product|sku)\b|$|[?])/iu
|
||||
];
|
||||
for (const pattern of patterns) {
|
||||
const match = source.match(pattern);
|
||||
const candidate = String(match?.[1] ?? "")
|
||||
.replace(/\s*(?:->|=>|→).+$/u, "")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
if (candidate) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function trimInventoryDocumentaryChainSupplierAnchor(value) {
|
||||
const source = String(value ?? "").trim();
|
||||
if (!source) {
|
||||
return null;
|
||||
}
|
||||
const candidate = source
|
||||
.replace(/\s+к\s+покупател\p{L}*[\s\S]*$/iu, "")
|
||||
.replace(/\s+через\s+товар\p{L}*[\s\S]*$/iu, "")
|
||||
.replace(/\s*(?:->|=>|→)\s*(?:товар|позици|номенклатур|item|product|sku)[\s\S]*$/iu, "")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
return candidate && candidate !== source ? candidate : null;
|
||||
}
|
||||
function normalizeInventoryChainOrganizationFilterValue(value) {
|
||||
const normalized = (0, assistantOrganizationMatcher_1.normalizeOrganizationScopeValue)(value);
|
||||
const cleaned = String(normalized ?? "")
|
||||
.replace(/[\\"]/g, " ")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
return cleaned || null;
|
||||
}
|
||||
function applyPreExecutionOrganizationScopeGrounding(input) {
|
||||
const activeOrganization = (0, assistantOrganizationMatcher_1.normalizeOrganizationScopeValue)(input.activeOrganization ?? null);
|
||||
const candidateOrganizations = (0, assistantOrganizationMatcher_1.mergeKnownOrganizations)([
|
||||
@@ -2988,14 +3027,65 @@ class AddressQueryService {
|
||||
const knownOrganizations = (0, assistantOrganizationMatcher_1.mergeKnownOrganizations)(options.knownOrganizations ?? []);
|
||||
const activeOrganization = (0, assistantOrganizationMatcher_1.normalizeOrganizationScopeValue)(options.activeOrganization ?? null);
|
||||
const previousOrganizationFromContext = (0, assistantOrganizationMatcher_1.normalizeOrganizationScopeValue)(followupContext?.previous_filters?.organization ?? null);
|
||||
const chainCounterpartyAnchor = toNonEmptyFilterValue(filters.extracted_filters.counterparty);
|
||||
const chainOrganizationAnchor = toNonEmptyFilterValue(filters.extracted_filters.organization);
|
||||
let chainCounterpartyAnchor = toNonEmptyFilterValue(filters.extracted_filters.counterparty);
|
||||
let chainOrganizationAnchor = toNonEmptyFilterValue(filters.extracted_filters.organization);
|
||||
if (intent.intent === "inventory_purchase_to_sale_chain") {
|
||||
const trimmedChainCounterparty = trimInventoryDocumentaryChainSupplierAnchor(chainCounterpartyAnchor);
|
||||
if (trimmedChainCounterparty) {
|
||||
filters.extracted_filters.counterparty = trimmedChainCounterparty;
|
||||
chainCounterpartyAnchor = trimmedChainCounterparty;
|
||||
if (!filters.warnings.includes("inventory_chain_supplier_anchor_trimmed_for_verification")) {
|
||||
filters.warnings.push("inventory_chain_supplier_anchor_trimmed_for_verification");
|
||||
}
|
||||
if (!baseReasons.includes("inventory_chain_supplier_anchor_trimmed_for_verification")) {
|
||||
baseReasons.push("inventory_chain_supplier_anchor_trimmed_for_verification");
|
||||
}
|
||||
}
|
||||
const buyerAnchor = extractInventoryDocumentaryChainBuyerAnchor(options.rawUserMessage ?? userMessage);
|
||||
const organizationLooksLikeBuyer = Boolean(buyerAnchor) &&
|
||||
Boolean(chainOrganizationAnchor) &&
|
||||
sameOrganizationEntityReference(chainOrganizationAnchor, buyerAnchor);
|
||||
const trustedOrganization = knownOrganizations.length === 1
|
||||
? knownOrganizations[0]
|
||||
: previousOrganizationFromContext && !sameOrganizationEntityReference(previousOrganizationFromContext, buyerAnchor)
|
||||
? previousOrganizationFromContext
|
||||
: null;
|
||||
if (trustedOrganization &&
|
||||
(!chainOrganizationAnchor || organizationLooksLikeBuyer) &&
|
||||
!sameOrganizationEntityReference(trustedOrganization, chainCounterpartyAnchor)) {
|
||||
const restoredOrganizationForFilter = normalizeInventoryChainOrganizationFilterValue(trustedOrganization) ?? trustedOrganization;
|
||||
filters.extracted_filters.organization = restoredOrganizationForFilter;
|
||||
chainOrganizationAnchor = restoredOrganizationForFilter;
|
||||
const reason = knownOrganizations.length === 1
|
||||
? "organization_restored_from_known_scope_for_inventory_chain"
|
||||
: "organization_restored_from_inventory_chain_context";
|
||||
if (!filters.warnings.includes(reason)) {
|
||||
filters.warnings.push(reason);
|
||||
}
|
||||
if (!baseReasons.includes(reason)) {
|
||||
baseReasons.push(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intent.intent === "inventory_purchase_to_sale_chain") {
|
||||
const normalizedChainOrganization = normalizeInventoryChainOrganizationFilterValue(filters.extracted_filters.organization);
|
||||
if (normalizedChainOrganization && normalizedChainOrganization !== filters.extracted_filters.organization) {
|
||||
filters.extracted_filters.organization = normalizedChainOrganization;
|
||||
chainOrganizationAnchor = normalizedChainOrganization;
|
||||
if (!filters.warnings.includes("organization_scope_normalized_for_inventory_chain")) {
|
||||
filters.warnings.push("organization_scope_normalized_for_inventory_chain");
|
||||
}
|
||||
if (!baseReasons.includes("organization_scope_normalized_for_inventory_chain")) {
|
||||
baseReasons.push("organization_scope_normalized_for_inventory_chain");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intent.intent === "inventory_purchase_to_sale_chain" &&
|
||||
chainCounterpartyAnchor &&
|
||||
chainOrganizationAnchor &&
|
||||
sameOrganizationEntityReference(chainOrganizationAnchor, chainCounterpartyAnchor)) {
|
||||
delete filters.extracted_filters.organization;
|
||||
const restoredOrganization = activeOrganization ?? previousOrganizationFromContext;
|
||||
const restoredOrganization = normalizeInventoryChainOrganizationFilterValue(activeOrganization ?? previousOrganizationFromContext);
|
||||
if (restoredOrganization && !sameOrganizationEntityReference(restoredOrganization, chainCounterpartyAnchor)) {
|
||||
filters.extracted_filters.organization = restoredOrganization;
|
||||
if (!filters.warnings.includes("organization_restored_from_inventory_chain_context")) {
|
||||
|
||||
+7
-1
@@ -114,7 +114,10 @@ function applyAddressLlmSemanticHintsToExtraction(extraction, semanticHintsInput
|
||||
}
|
||||
semanticFrame.selected_object_scope_detected = true;
|
||||
}
|
||||
if (semanticHints.scope_target_kind === "organization" && scopeTargetText) {
|
||||
const protectsInventoryDocumentaryChainSupplierAnchor = warnings.includes("supplier_anchor_derived_for_inventory_documentary_chain");
|
||||
if (semanticHints.scope_target_kind === "organization" &&
|
||||
scopeTargetText &&
|
||||
!protectsInventoryDocumentaryChainSupplierAnchor) {
|
||||
extractedFilters.organization = scopeTargetText;
|
||||
pushWarning(warnings, "organization_from_llm_semantics");
|
||||
if (toNonEmptyString(extractedFilters.warehouse)) {
|
||||
@@ -125,6 +128,9 @@ function applyAddressLlmSemanticHintsToExtraction(extraction, semanticHintsInput
|
||||
semanticFrame.anchor_kind = "organization";
|
||||
semanticFrame.anchor_value = scopeTargetText;
|
||||
}
|
||||
else if (semanticHints.scope_target_kind === "organization" && scopeTargetText) {
|
||||
pushWarning(warnings, "organization_llm_semantics_ignored_for_inventory_documentary_chain");
|
||||
}
|
||||
if (semanticHints.scope_target_kind === "warehouse" && scopeTargetText) {
|
||||
extractedFilters.warehouse = scopeTargetText;
|
||||
pushWarning(warnings, "warehouse_from_llm_semantics");
|
||||
|
||||
Reference in New Issue
Block a user