Укрепить business overview и память по СВК
This commit is contained in:
@@ -4053,7 +4053,7 @@ function composeFactualReplyBody(
|
||||
|
||||
const lines = [
|
||||
directVatLine,
|
||||
"Расчет сделан по книгам продаж и покупок.",
|
||||
"Расчет сделан по подтвержденным строкам книг продаж и покупок.",
|
||||
"",
|
||||
"Что вошло в расчет:",
|
||||
...(organizationLabel ? [`- Организация: ${organizationLabel}.`] : []),
|
||||
@@ -4063,6 +4063,10 @@ function composeFactualReplyBody(
|
||||
`- НДС по книге покупок (вычеты): ${formatConfirmedMoney(purchaseVat)}.`,
|
||||
`- Нетто НДС (книга продаж - книга покупок): ${formatConfirmedMoney(netVat)}.`
|
||||
];
|
||||
lines.push(
|
||||
"",
|
||||
"Граница вывода: это подтвержденный баланс по найденным строкам книг продаж/покупок, но не полный налоговый вердикт и не сверка декларации; для финального вывода нужно отдельно проверить корректировки, применимость вычетов, закрытие периода и первичные документы."
|
||||
);
|
||||
|
||||
if (rows.length === 0) {
|
||||
lines.push(
|
||||
|
||||
@@ -483,9 +483,6 @@ function findRecentBusinessOverviewProofBundles(input: {
|
||||
counterpartyHint: string | null;
|
||||
toNonEmptyString: BuildAssistantAddressOrchestrationRuntimeInput["toNonEmptyString"];
|
||||
}): { valueBundle: Record<string, unknown> | null; documentBundle: Record<string, unknown> | null } | null {
|
||||
if (!input.counterpartyHint) {
|
||||
return null;
|
||||
}
|
||||
for (let index = input.sessionItems.length - 1; index >= 0; index -= 1) {
|
||||
const item = toRecordObject(input.sessionItems[index]);
|
||||
if (input.toNonEmptyString(item?.role) !== "assistant") {
|
||||
@@ -505,7 +502,7 @@ function findRecentBusinessOverviewProofBundles(input: {
|
||||
documentBundle,
|
||||
input.toNonEmptyString
|
||||
);
|
||||
if (sameEntityHint(input.counterpartyHint, bundleCounterparty)) {
|
||||
if (!input.counterpartyHint || sameEntityHint(input.counterpartyHint, bundleCounterparty)) {
|
||||
return { valueBundle, documentBundle };
|
||||
}
|
||||
}
|
||||
@@ -519,7 +516,7 @@ function findRecentBusinessOverviewProofBundles(input: {
|
||||
const parsedCounterparty =
|
||||
input.toNonEmptyString(parsedBundles.valueBundle?.counterparty) ??
|
||||
input.toNonEmptyString(parsedBundles.documentBundle?.counterparty);
|
||||
if (!sameEntityHint(input.counterpartyHint, parsedCounterparty)) {
|
||||
if (input.counterpartyHint && !sameEntityHint(input.counterpartyHint, parsedCounterparty)) {
|
||||
continue;
|
||||
}
|
||||
return parsedBundles;
|
||||
@@ -551,7 +548,7 @@ function mergeBusinessOverviewProofBundlesFromNavigationState(input: {
|
||||
const entities = toRecordObject(input.predecomposeContract?.entities);
|
||||
const hasCurrentOrganizationSelection = Boolean(input.toNonEmptyString(entities?.organization));
|
||||
const businessOverviewFollowup = isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString);
|
||||
if (!hasComparisonScopeProofCue(input.userMessage)) {
|
||||
if (!hasComparisonScopeProofCue(input.userMessage) && !hasCurrentOrganizationSelection) {
|
||||
return input.followupContext;
|
||||
}
|
||||
if (!businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||
@@ -597,13 +594,17 @@ function mergeBusinessOverviewProofBundlesFromNavigationState(input: {
|
||||
function mergeBusinessOverviewProofBundlesFromSessionItems(input: {
|
||||
followupContext: Record<string, unknown> | null;
|
||||
userMessage: string;
|
||||
predecomposeContract: Record<string, unknown> | null;
|
||||
sessionItems: unknown[];
|
||||
toNonEmptyString: BuildAssistantAddressOrchestrationRuntimeInput["toNonEmptyString"];
|
||||
}): Record<string, unknown> | null {
|
||||
if (!hasComparisonScopeProofCue(input.userMessage)) {
|
||||
const businessOverviewFollowup = isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString);
|
||||
const entities = toRecordObject(input.predecomposeContract?.entities);
|
||||
const hasCurrentOrganizationSelection = Boolean(input.toNonEmptyString(entities?.organization));
|
||||
if (!hasComparisonScopeProofCue(input.userMessage) && !businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||
return input.followupContext;
|
||||
}
|
||||
if (!isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString)) {
|
||||
if (!businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||
return input.followupContext;
|
||||
}
|
||||
const currentValueBundle = toRecordObject(input.followupContext?.previous_discovery_bidirectional_value_flow);
|
||||
@@ -622,8 +623,27 @@ function mergeBusinessOverviewProofBundlesFromSessionItems(input: {
|
||||
if (!proofBundles) {
|
||||
return input.followupContext;
|
||||
}
|
||||
const recoveredCounterparty =
|
||||
counterpartyHint ??
|
||||
input.toNonEmptyString(proofBundles.valueBundle?.counterparty) ??
|
||||
input.toNonEmptyString(proofBundles.documentBundle?.counterparty);
|
||||
return {
|
||||
...(input.followupContext ?? {}),
|
||||
previous_intent: input.toNonEmptyString(input.followupContext?.previous_intent) ?? "business_overview",
|
||||
target_intent: input.toNonEmptyString(input.followupContext?.target_intent) ?? "business_overview",
|
||||
previous_discovery_pilot_scope:
|
||||
input.toNonEmptyString(input.followupContext?.previous_discovery_pilot_scope) ??
|
||||
"business_overview_route_template_v1",
|
||||
previous_discovery_loop_selected_chain_id:
|
||||
input.toNonEmptyString(input.followupContext?.previous_discovery_loop_selected_chain_id) ?? "business_overview",
|
||||
previous_discovery_loop_asked_domain_family:
|
||||
input.toNonEmptyString(input.followupContext?.previous_discovery_loop_asked_domain_family) ?? "business_overview",
|
||||
previous_discovery_loop_asked_action_family:
|
||||
input.toNonEmptyString(input.followupContext?.previous_discovery_loop_asked_action_family) ?? "broad_evaluation",
|
||||
previous_discovery_loop_metadata_scope_hint:
|
||||
input.toNonEmptyString(input.followupContext?.previous_discovery_loop_metadata_scope_hint) ?? recoveredCounterparty ?? undefined,
|
||||
previous_anchor_type: input.toNonEmptyString(input.followupContext?.previous_anchor_type) ?? (recoveredCounterparty ? "counterparty" : undefined),
|
||||
previous_anchor_value: input.toNonEmptyString(input.followupContext?.previous_anchor_value) ?? recoveredCounterparty ?? undefined,
|
||||
previous_discovery_bidirectional_value_flow:
|
||||
currentValueBundle ?? proofBundles.valueBundle ?? undefined,
|
||||
previous_discovery_document_summary: currentDocumentBundle ?? proofBundles.documentBundle ?? undefined
|
||||
@@ -904,6 +924,7 @@ export async function buildAssistantAddressOrchestrationRuntime(
|
||||
const discoveryFollowupContextWithProofBundles = mergeBusinessOverviewProofBundlesFromSessionItems({
|
||||
followupContext: discoveryFollowupContext,
|
||||
userMessage: input.userMessage,
|
||||
predecomposeContract,
|
||||
sessionItems: input.sessionItems,
|
||||
toNonEmptyString: input.toNonEmptyString
|
||||
});
|
||||
|
||||
@@ -1137,7 +1137,7 @@ function buildCompactBusinessOverviewReply(
|
||||
|
||||
if (plainOrganizationClarificationSelection && (incomingAmount || outgoingAmount || netAmount)) {
|
||||
lines.push(
|
||||
`Коротко: по компании ${organizationScope} ${period} подтвержден company-level денежный срез: входящие ${incomingAmount ?? "0 руб."}, исходящие ${outgoingAmount ?? "0 руб."}, операционное нетто ${sentenceAmount(netAmount) ?? netAmount ?? "0 руб."}.`
|
||||
`по компании ${organizationScope} ${period} подтвержден company-level денежный срез: входящие ${incomingAmount ?? "0 руб."}, исходящие ${outgoingAmount ?? "0 руб."}, операционное нетто ${sentenceAmount(netAmount) ?? netAmount ?? "0 руб."}.`
|
||||
);
|
||||
if (previousCounterpartySummary) {
|
||||
lines.push(previousCounterpartySummary.line);
|
||||
@@ -1403,8 +1403,16 @@ function buildCompactBusinessOverviewReply(
|
||||
) {
|
||||
const subject = organizationScope ?? "компания";
|
||||
const periodWithoutPrefix = period.replace(/^за\s+/iu, "");
|
||||
const executiveFacts = [
|
||||
incomingAmount ? `входящие ${incomingAmount}` : null,
|
||||
outgoingAmount ? `исходящие ${outgoingAmount}` : null,
|
||||
netAmount ? `${netDirection} ${sentenceAmount(netAmount) ?? netAmount}` : null
|
||||
].filter((value): value is string => Boolean(value));
|
||||
lines.push(
|
||||
`Коротко: по ограниченному проверенному 1С-срезу ${subject} выглядит как бизнес с крупными контрактными денежными потоками и заметной зависимостью от нескольких крупных контрагентов, а не как равномерный поток мелких продаж; это не аудиторское заключение и не подтвержденная чистая прибыль.`
|
||||
`По подтвержденным строкам 1С ${subject} за ${periodWithoutPrefix}: ${executiveFacts.length > 0 ? executiveFacts.join(", ") : "денежные метрики не подтверждены"}; это ограниченный проверенный срез, не аудиторское заключение и не подтвержденная чистая прибыль.`
|
||||
);
|
||||
lines.push(
|
||||
"Интерпретация: по этому срезу видны крупные контрактные денежные потоки и заметная зависимость от нескольких крупных контрагентов, а не равномерный поток мелких продаж."
|
||||
);
|
||||
lines.push("Что видно в ограниченном денежном срезе:");
|
||||
if (incomingAmount) {
|
||||
|
||||
@@ -2779,11 +2779,14 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty ? [] : entityCandidates,
|
||||
business_overview_separate_entity_candidates: businessOverviewSeparateEntityCandidates,
|
||||
previous_counterparty_value_flow_bundle:
|
||||
businessOverviewSignal && followupSeed.previousBidirectionalValueFlow
|
||||
(businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty) &&
|
||||
followupSeed.previousBidirectionalValueFlow
|
||||
? followupSeed.previousBidirectionalValueFlow
|
||||
: undefined,
|
||||
previous_counterparty_document_bundle:
|
||||
businessOverviewSignal && followupSeed.previousDocumentSummary ? followupSeed.previousDocumentSummary : undefined,
|
||||
(businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty) && followupSeed.previousDocumentSummary
|
||||
? followupSeed.previousDocumentSummary
|
||||
: undefined,
|
||||
metadata_ambiguity_entity_sets:
|
||||
metadataAmbiguityLaneClarificationApplicable && followupSeed.metadataAmbiguityEntitySets.length > 0
|
||||
? followupSeed.metadataAmbiguityEntitySets
|
||||
|
||||
@@ -555,9 +555,13 @@ export function createAssistantTransitionPolicy(deps) {
|
||||
if (!text) {
|
||||
return null;
|
||||
}
|
||||
const match = text.match(
|
||||
const boundaryMatch = text.match(
|
||||
/Отдельно\s+по\s+контрагенту\s+([^:\n]+):\s*подтверждено\s+получили\s+([^,\n]+?руб\.?),\s*заплатили\s+([^,\n]+?руб\.?),\s*расчетное\s+нетто\s+в\s+нашу\s+сторону\s+([^.\n]+?руб\.?)/iu
|
||||
);
|
||||
const directMatch = text.match(
|
||||
/по\s+контрагенту\s+([^.\n]+?)\s+в\s+проверенном\s+окне[\s\S]{0,160}?получили\s+([^,\n]+?руб\.?),\s*заплатили\s+([^;\n]+?руб\.?);\s*расчетное\s+нетто\s+в\s+нашу\s+сторону:?\s*([^.\n]+?руб\.?)/iu
|
||||
);
|
||||
const match = boundaryMatch ?? directMatch;
|
||||
if (!match?.[1] || !match?.[2] || !match?.[3] || !match?.[4]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user