ОРРКЕСТРАЦИЯ - Усилить agent loop object-centric аудитом и добить pronoun follow-up по документам закупки
This commit is contained in:
@@ -1604,7 +1604,9 @@ function hasInventorySaleTraceSignal(text: string): boolean {
|
||||
}
|
||||
|
||||
function hasSelectedObjectInventoryCue(text: string): boolean {
|
||||
return /(?:по\s+выбранному\s+объекту|selected\s+object)/iu.test(text);
|
||||
return /(?:по\s+выбранному\s+объекту|по\s+этой\s+позиции|по\s+этому\s+товару|по\s+нему|по\s+ней|по\s+нему\s+же|по\s+ней\s+же|selected\s+object)/iu.test(
|
||||
text
|
||||
);
|
||||
}
|
||||
|
||||
function hasSelectedObjectInventoryProvenanceSignal(text: string): boolean {
|
||||
|
||||
@@ -4020,7 +4020,14 @@ export function composeFactualReply(
|
||||
const purchaseRows = rows.filter((row) => isInventoryPurchaseMovement(row));
|
||||
const summary = summarizeInventoryTraceRows(purchaseRows);
|
||||
const itemLabel = summary.item ?? "товар не определен";
|
||||
const directAnswerLine =
|
||||
summary.counterparties.length === 1
|
||||
? `По товару ${itemLabel} документы поступления связаны с поставщиком: ${summary.counterparties[0]}.`
|
||||
: summary.counterparties.length > 1
|
||||
? `По товару ${itemLabel} документы поступления ведут к нескольким поставщикам: ${summary.counterparties.slice(0, 4).join("; ")}.`
|
||||
: `По товару ${itemLabel} найдены документы поступления, но поставщик не материализован отдельным полем в текущем exact-контуре.`;
|
||||
const lines: string[] = [
|
||||
directAnswerLine,
|
||||
`Собран подтвержденный список документов поступления по товару ${itemLabel} до ${formatDateRu(asOfDate)}.`,
|
||||
"",
|
||||
"Блок 1. Статус результата",
|
||||
@@ -4105,7 +4112,14 @@ export function composeFactualReply(
|
||||
const summary = summarizeInventoryTraceRows(purchaseRows);
|
||||
const unresolvedRows = purchaseRows.filter((row) => extractInventoryCounterpartyCandidates(row).length === 0);
|
||||
const warehouseLabel = summary.warehouses[0] ?? "не указанного склада";
|
||||
const directAnswerLine =
|
||||
summary.counterparties.length === 1
|
||||
? `По складскому остатку ${warehouseLabel} выявлен поставщик: ${summary.counterparties[0]}.`
|
||||
: summary.counterparties.length > 1
|
||||
? `По складскому остатку ${warehouseLabel} найдено несколько поставщиков: ${summary.counterparties.slice(0, 6).join("; ")}.`
|
||||
: `По складскому остатку ${warehouseLabel} поставщик в текущем exact-контуре не материализован.`;
|
||||
const lines: string[] = [
|
||||
directAnswerLine,
|
||||
`Собран exact-срез supplier overlap для складского остатка до ${formatDateRu(asOfDate)}.`,
|
||||
"",
|
||||
"Блок 1. Статус результата",
|
||||
@@ -4201,7 +4215,14 @@ export function composeFactualReply(
|
||||
const saleRows = rows.filter((row) => isInventorySaleMovement(row));
|
||||
const summary = summarizeInventoryTraceRows(saleRows);
|
||||
const itemLabel = summary.item ?? "товар не определен";
|
||||
const directAnswerLine =
|
||||
summary.counterparties.length === 1
|
||||
? `По товару ${itemLabel} покупатель определен: ${summary.counterparties[0]}.`
|
||||
: summary.counterparties.length > 1
|
||||
? `По товару ${itemLabel} найдено несколько покупателей: ${summary.counterparties.slice(0, 4).join("; ")}.`
|
||||
: `По товару ${itemLabel} покупатель в текущем exact-контуре не материализован.`;
|
||||
const lines: string[] = [
|
||||
directAnswerLine,
|
||||
`Собран подтвержденный след выбытия по товару ${itemLabel} до ${formatDateRu(asOfDate)}.`,
|
||||
"",
|
||||
"Блок 1. Статус результата",
|
||||
@@ -4244,7 +4265,12 @@ export function composeFactualReply(
|
||||
const purchaseSummary = summarizeInventoryTraceRows(purchaseRows);
|
||||
const saleSummary = summarizeInventoryTraceRows(saleRows);
|
||||
const itemLabel = purchaseSummary.item ?? saleSummary.item ?? "товар не определен";
|
||||
const directAnswerLine =
|
||||
purchaseSummary.counterparties.length === 1 && saleSummary.counterparties.length === 1
|
||||
? `По товару ${itemLabel} цепочка поставки и продажи связана с поставщиком ${purchaseSummary.counterparties[0]} и покупателем ${saleSummary.counterparties[0]}.`
|
||||
: `По товару ${itemLabel} цепочка поставки и продажи подтверждена частично или разнообразно: детали идут следом.`;
|
||||
const lines: string[] = [
|
||||
directAnswerLine,
|
||||
`Собрана документальная цепочка по товару ${itemLabel} до ${formatDateRu(asOfDate)}.`,
|
||||
"",
|
||||
"Блок 1. Статус результата",
|
||||
|
||||
@@ -329,7 +329,7 @@ function hasInventorySupplierFollowupCue(text: string): boolean {
|
||||
}
|
||||
|
||||
function hasInventoryPurchaseDocumentsFollowupCue(text: string): boolean {
|
||||
return /(?:по\s+каким\s+документам\s+(?:это|его|этот\s+товар|эту\s+позицию)\s+купили|по\s+каким\s+документам\s+(?:был\s+)?куплен|какими\s+документами\s+(?:это|его|этот\s+товар|эту\s+позицию)\s+купили|какими\s+документами\s+(?:был\s+)?куплен|purchase\s+documents|documents\s+of\s+purchase|through\s+which\s+documents)/iu.test(
|
||||
return /(?:по\s+каким\s+документам\s+(?:это|его|этот\s+товар|эту\s+позицию)\s+купили|по\s+каким\s+документам\s+(?:был\s+)?куплен|какими\s+документами\s+(?:это|его|этот\s+товар|эту\s+позицию)\s+купили|какими\s+документами\s+(?:был\s+)?куплен|покажи\s+документы\s+по\s+(?:этой\s+позиции|этому\s+товару|ней|нему)|документы\s+по\s+(?:этой\s+позиции|этому\s+товару|ней|нему)|purchase\s+documents|documents\s+of\s+purchase|through\s+which\s+documents)/iu.test(
|
||||
String(text ?? "")
|
||||
);
|
||||
}
|
||||
@@ -424,6 +424,7 @@ function mergeFollowupFilters(
|
||||
const previousCounterparty = toNonEmptyString(previous.counterparty);
|
||||
const previousContract = toNonEmptyString(previous.contract);
|
||||
const previousAccount = toNonEmptyString(previous.account);
|
||||
const previousItem = toNonEmptyString(previous.item);
|
||||
const previousOrganization = toNonEmptyString(previous.organization);
|
||||
const previousAsOfDate = toNonEmptyString(previous.as_of_date);
|
||||
const previousPeriodFrom = toNonEmptyString(previous.period_from);
|
||||
@@ -554,6 +555,18 @@ function mergeFollowupFilters(
|
||||
merged.counterparty = inheritedCounterparty;
|
||||
reasons.push(currentCounterparty ? "counterparty_replaced_from_followup_context" : "counterparty_from_followup_context");
|
||||
}
|
||||
if (
|
||||
(intent === "inventory_purchase_provenance_for_item" ||
|
||||
intent === "inventory_purchase_documents_for_item" ||
|
||||
intent === "inventory_sale_trace_for_item" ||
|
||||
intent === "inventory_purchase_to_sale_chain" ||
|
||||
intent === "inventory_aging_by_purchase_date") &&
|
||||
!toNonEmptyString(merged.item) &&
|
||||
previousItem
|
||||
) {
|
||||
merged.item = previousItem;
|
||||
reasons.push("item_from_followup_context");
|
||||
}
|
||||
if (sameDateRequested) {
|
||||
const inheritedAsOfDate = previousAsOfDate ?? previousPeriodTo ?? previousPeriodFrom;
|
||||
if (inheritedAsOfDate && merged.as_of_date !== inheritedAsOfDate) {
|
||||
|
||||
Reference in New Issue
Block a user