АРЧ - Ассистент: отделить reference-срез от execution-окна в ответах по lifecycle follow-up
This commit is contained in:
@@ -29,7 +29,14 @@ const DISPLAY_ENTITY_TYPE_BY_INTENT: Partial<Record<AddressIntent, AddressFocusO
|
||||
list_documents_by_contract: "document_ref",
|
||||
bank_operations_by_counterparty: "document_ref",
|
||||
bank_operations_by_contract: "document_ref",
|
||||
open_items_by_counterparty_or_contract: "counterparty"
|
||||
open_items_by_counterparty_or_contract: "counterparty",
|
||||
inventory_on_hand_as_of_date: "item",
|
||||
inventory_purchase_provenance_for_item: "item",
|
||||
inventory_purchase_documents_for_item: "item",
|
||||
inventory_supplier_stock_overlap_as_of_date: "item",
|
||||
inventory_sale_trace_for_item: "item",
|
||||
inventory_purchase_to_sale_chain: "item",
|
||||
inventory_aging_by_purchase_date: "item"
|
||||
};
|
||||
|
||||
const RESULT_SET_TYPE_BY_INTENT: Partial<Record<AddressIntent, AddressResultSetType>> = {
|
||||
@@ -48,6 +55,13 @@ const RESULT_SET_TYPE_BY_INTENT: Partial<Record<AddressIntent, AddressResultSetT
|
||||
bank_operations_by_counterparty: "bank_operations_list",
|
||||
bank_operations_by_contract: "bank_operations_list",
|
||||
open_items_by_counterparty_or_contract: "open_items_list",
|
||||
inventory_on_hand_as_of_date: "inventory_snapshot",
|
||||
inventory_purchase_provenance_for_item: "inventory_trace",
|
||||
inventory_purchase_documents_for_item: "inventory_trace",
|
||||
inventory_supplier_stock_overlap_as_of_date: "inventory_trace",
|
||||
inventory_sale_trace_for_item: "inventory_trace",
|
||||
inventory_purchase_to_sale_chain: "inventory_trace",
|
||||
inventory_aging_by_purchase_date: "inventory_trace",
|
||||
period_coverage_profile: "profile_summary",
|
||||
document_type_and_account_section_profile: "profile_summary",
|
||||
counterparty_population_and_roles: "profile_summary",
|
||||
@@ -76,7 +90,15 @@ function toAddressFocusObjectType(value: unknown): AddressFocusObjectType {
|
||||
if (!normalized) {
|
||||
return "unknown";
|
||||
}
|
||||
if (normalized === "counterparty" || normalized === "contract" || normalized === "document_ref" || normalized === "account") {
|
||||
if (
|
||||
normalized === "counterparty" ||
|
||||
normalized === "contract" ||
|
||||
normalized === "document_ref" ||
|
||||
normalized === "account" ||
|
||||
normalized === "item" ||
|
||||
normalized === "organization" ||
|
||||
normalized === "warehouse"
|
||||
) {
|
||||
return normalized;
|
||||
}
|
||||
return "unknown";
|
||||
@@ -149,6 +171,44 @@ function extractEntityRefsFromAssistantReply(
|
||||
return Array.from(dedup.values());
|
||||
}
|
||||
|
||||
function extractOrganizationsFromAssistantReply(replyText: string, limit: number = 10): string[] {
|
||||
const dedup = new Map<string, string>();
|
||||
const lines = String(replyText ?? "").split(/\r?\n/);
|
||||
for (const line of lines) {
|
||||
const match = line.match(/(?:^|\|)\s*организац(?:ия|ии)\s*:\s*([^|]+)/iu);
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
const organization = toNonEmptyString(match[1]);
|
||||
if (!organization) {
|
||||
continue;
|
||||
}
|
||||
const key = organization.toLowerCase();
|
||||
if (!dedup.has(key)) {
|
||||
dedup.set(key, organization);
|
||||
}
|
||||
if (dedup.size >= limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Array.from(dedup.values());
|
||||
}
|
||||
|
||||
function resolveDerivedOrganizationScope(
|
||||
debug: Record<string, unknown>,
|
||||
filters: Record<string, unknown>,
|
||||
replyText: string
|
||||
): string | null {
|
||||
const rootFrameContext = toObject(debug.address_root_frame_context) ?? {};
|
||||
const candidates = [
|
||||
toNonEmptyString(filters.organization),
|
||||
toNonEmptyString(rootFrameContext.organization),
|
||||
...extractOrganizationsFromAssistantReply(replyText)
|
||||
].filter((value): value is string => Boolean(value));
|
||||
const dedup = Array.from(new Map(candidates.map((value) => [value.toLowerCase(), value])).values());
|
||||
return dedup.length === 1 ? dedup[0] : null;
|
||||
}
|
||||
|
||||
function cloneFocusObject(value: AddressFocusObject | null): AddressFocusObject | null {
|
||||
if (!value) {
|
||||
return null;
|
||||
@@ -392,6 +452,14 @@ export function evolveAddressNavigationStateWithAssistantItem(
|
||||
const resultSetId = `rs-${item.message_id}`;
|
||||
const routeId = toNonEmptyString(debug.selected_recipe);
|
||||
const filters = normalizeFilters(debug.extracted_filters);
|
||||
const derivedOrganizationScope = resolveDerivedOrganizationScope(debug, filters, item.text);
|
||||
const filtersWithDerivedScope =
|
||||
derivedOrganizationScope && !toNonEmptyString(filters.organization)
|
||||
? {
|
||||
...filters,
|
||||
organization: derivedOrganizationScope
|
||||
}
|
||||
: filters;
|
||||
const sourceRefs = routeId ? [routeId] : [];
|
||||
const entityRefs = extractEntityRefsFromAssistantReply(item.text, intent);
|
||||
const resultSet: AddressResultSet = {
|
||||
@@ -399,7 +467,7 @@ export function evolveAddressNavigationStateWithAssistantItem(
|
||||
type: inferResultSetType(intent),
|
||||
intent,
|
||||
route_id: routeId,
|
||||
filters,
|
||||
filters: filtersWithDerivedScope,
|
||||
source_refs: sourceRefs,
|
||||
entity_refs: entityRefs,
|
||||
created_from_turn: turnIndex,
|
||||
@@ -418,11 +486,11 @@ export function evolveAddressNavigationStateWithAssistantItem(
|
||||
created_at: createdAt
|
||||
};
|
||||
const normalizedDateScope = {
|
||||
as_of_date: toNonEmptyString(filters.as_of_date),
|
||||
period_from: toNonEmptyString(filters.period_from),
|
||||
period_to: toNonEmptyString(filters.period_to)
|
||||
as_of_date: toNonEmptyString(filtersWithDerivedScope.as_of_date),
|
||||
period_from: toNonEmptyString(filtersWithDerivedScope.period_from),
|
||||
period_to: toNonEmptyString(filtersWithDerivedScope.period_to)
|
||||
};
|
||||
const organizationScope = toNonEmptyString(filters.organization);
|
||||
const organizationScope = toNonEmptyString(filtersWithDerivedScope.organization);
|
||||
const nextResultSets = capResultSets(
|
||||
[...state.result_sets.filter((itemSet) => itemSet.result_set_id !== resultSetId), resultSet].sort(
|
||||
(left, right) => left.created_from_turn - right.created_from_turn
|
||||
|
||||
Reference in New Issue
Block a user