Сжать бизнес-ответы по доходности и заработанным суммам
This commit is contained in:
@@ -637,7 +637,10 @@ describe("assistant living chat runtime adapter", () => {
|
||||
sessionItems: [
|
||||
{
|
||||
role: "assistant",
|
||||
text: "По товару Рабочая станция универсального специалиста покупатель определен: Комитет государственных услуг г. Москвы.\nДокументы выбытия:\n1. Реализация товаров и услуг | товар: Рабочая станция универсального специалиста | контрагент: Комитет государственных услуг г. Москвы",
|
||||
trace_id: "address-sale-trace",
|
||||
debug: {
|
||||
trace_id: "address-sale-trace",
|
||||
execution_lane: "address_query",
|
||||
answer_grounding_check: {
|
||||
status: "grounded"
|
||||
@@ -658,6 +661,8 @@ describe("assistant living chat runtime adapter", () => {
|
||||
|
||||
expect(output.handled).toBe(true);
|
||||
expect(output.chatText).toContain("Рабочая станция универсального специалиста");
|
||||
expect(output.chatText).toContain("Комитет государственных услуг г. Москвы");
|
||||
expect(output.chatText).not.toContain("Покупатель в доступных данных отдельно не выделен");
|
||||
expect(output.debug?.living_chat_response_source).toBe("deterministic_answer_inspection_contract");
|
||||
expect(executeLlmChat).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -264,7 +264,12 @@ describe("assistant MCP discovery answer adapter", () => {
|
||||
|
||||
expect(draft.answer_mode).toBe("confirmed_with_bounded_inference");
|
||||
expect(draft.headline).toContain("бизнес-обзор");
|
||||
expect(draft.headline).toContain("входящие поступления");
|
||||
expect(draft.headline).toContain("расчетное операционное нетто");
|
||||
expect(draft.headline).toContain("самый сильный год");
|
||||
expect(draft.confirmed_lines.join("\n")).toContain("Входящие поступления");
|
||||
expect(draft.confirmed_lines.join("\n")).toContain("Самый сильный год");
|
||||
expect(draft.confirmed_lines.join("\n")).toContain("2021");
|
||||
expect(draft.confirmed_lines.join("\n")).toContain("Самый крупный подтвержденный клиент");
|
||||
expect(draft.confirmed_lines.join("\n")).toContain("Самый крупный подтвержденный поставщик");
|
||||
expect(draft.confirmed_lines.join("\n")).toContain("Годовая раскладка операционного денежного потока");
|
||||
|
||||
@@ -44,6 +44,149 @@ describe("assistant MCP discovery response candidate", () => {
|
||||
expect(candidate.reply_text).not.toContain("primitive");
|
||||
});
|
||||
|
||||
it("uses a compact direct answer for business-overview top year questions", () => {
|
||||
const candidate = buildAssistantMcpDiscoveryResponseCandidate(
|
||||
entryPoint({
|
||||
turn_input: {
|
||||
adapter_status: "ready",
|
||||
data_need_graph: {
|
||||
business_fact_family: "business_overview",
|
||||
ranking_need: "top_desc",
|
||||
reason_codes: [
|
||||
"data_need_graph_family_business_overview",
|
||||
"data_need_graph_ranking_top_desc",
|
||||
"data_need_graph_business_overview_direct_money_answer"
|
||||
]
|
||||
}
|
||||
},
|
||||
bridge: {
|
||||
bridge_status: "answer_draft_ready",
|
||||
user_facing_response_allowed: true,
|
||||
business_fact_answer_allowed: true,
|
||||
requires_user_clarification: false,
|
||||
pilot: {
|
||||
pilot_scope: "business_overview_route_template_v1",
|
||||
derived_business_overview: {
|
||||
period_scope: null,
|
||||
incoming_customer_revenue: {
|
||||
total_amount_human_ru: "157 192 981,43 руб.",
|
||||
coverage_limited_by_probe_limit: true
|
||||
},
|
||||
outgoing_supplier_payout: {
|
||||
total_amount_human_ru: "35 439 044,74 руб.",
|
||||
coverage_limited_by_probe_limit: true
|
||||
},
|
||||
net_amount_human_ru: "121 753 936,69 руб.",
|
||||
net_direction: "net_incoming",
|
||||
top_customers: [],
|
||||
yearly_breakdown: [
|
||||
{
|
||||
year_bucket: "2014",
|
||||
incoming_total_amount: 11239150.41,
|
||||
incoming_total_amount_human_ru: "11 239 150,41 руб.",
|
||||
incoming_rows_with_amount: 4,
|
||||
net_amount: -634486.17,
|
||||
net_amount_human_ru: "634 486,17 руб.",
|
||||
net_direction: "net_outgoing"
|
||||
},
|
||||
{
|
||||
year_bucket: "2015",
|
||||
incoming_total_amount: 136723459.73,
|
||||
incoming_total_amount_human_ru: "136 723 459,73 руб.",
|
||||
incoming_rows_with_amount: 54,
|
||||
net_amount: 113158051.57,
|
||||
net_amount_human_ru: "113 158 051,57 руб.",
|
||||
net_direction: "net_incoming"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
answer_draft: {
|
||||
answer_mode: "confirmed_with_bounded_inference",
|
||||
headline: "Ограниченный бизнес-обзор с большим полотном.",
|
||||
confirmed_lines: ["Профиль операционной активности: лишняя широкая строка."],
|
||||
inference_lines: ["Сводный LLM-аудит: лишняя широкая строка."],
|
||||
unknown_lines: ["Прибыль и маржа не подтверждены."],
|
||||
limitation_lines: [],
|
||||
next_step_line: null
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
expect(candidate.reply_text).toContain("самый доходный год");
|
||||
expect(candidate.reply_text).toContain("2015");
|
||||
expect(candidate.reply_text).toContain("136 723 459,73 руб.");
|
||||
expect(candidate.reply_text).toContain("не как чистую бухгалтерскую прибыль");
|
||||
expect(candidate.reply_text).toContain("лимит выборки MCP");
|
||||
expect(candidate.reply_text).not.toContain("Что подтверждено:");
|
||||
expect(candidate.reply_text).not.toContain("Профиль операционной активности");
|
||||
});
|
||||
|
||||
it("uses a compact direct answer for business-overview earned-money totals", () => {
|
||||
const candidate = buildAssistantMcpDiscoveryResponseCandidate(
|
||||
entryPoint({
|
||||
turn_input: {
|
||||
adapter_status: "ready",
|
||||
data_need_graph: {
|
||||
business_fact_family: "business_overview",
|
||||
ranking_need: null,
|
||||
reason_codes: [
|
||||
"data_need_graph_family_business_overview",
|
||||
"data_need_graph_business_overview_direct_money_answer"
|
||||
]
|
||||
}
|
||||
},
|
||||
bridge: {
|
||||
bridge_status: "answer_draft_ready",
|
||||
user_facing_response_allowed: true,
|
||||
business_fact_answer_allowed: true,
|
||||
requires_user_clarification: false,
|
||||
pilot: {
|
||||
pilot_scope: "business_overview_route_template_v1",
|
||||
derived_business_overview: {
|
||||
period_scope: "2017",
|
||||
incoming_customer_revenue: {
|
||||
total_amount_human_ru: "16 932 063,96 руб.",
|
||||
coverage_limited_by_probe_limit: false
|
||||
},
|
||||
outgoing_supplier_payout: {
|
||||
total_amount_human_ru: "4 458 027,05 руб.",
|
||||
coverage_limited_by_probe_limit: true
|
||||
},
|
||||
net_amount_human_ru: "12 474 036,91 руб.",
|
||||
net_direction: "net_incoming",
|
||||
top_customers: [
|
||||
{
|
||||
axis_value: "ГКУ УКРиС",
|
||||
total_amount_human_ru: "11 536 836,23 руб."
|
||||
}
|
||||
],
|
||||
yearly_breakdown: []
|
||||
}
|
||||
},
|
||||
answer_draft: {
|
||||
answer_mode: "confirmed_with_bounded_inference",
|
||||
headline: "Ограниченный бизнес-обзор с большим полотном.",
|
||||
confirmed_lines: ["Складской срез на дату: лишняя широкая строка."],
|
||||
inference_lines: ["Риски и контуры внимания: лишняя широкая строка."],
|
||||
unknown_lines: [],
|
||||
limitation_lines: [],
|
||||
next_step_line: null
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
expect(candidate.reply_text).toContain("за 2017");
|
||||
expect(candidate.reply_text).toContain("получили 16 932 063,96 руб.");
|
||||
expect(candidate.reply_text).toContain("исходящие платежи/списания 4 458 027,05 руб.");
|
||||
expect(candidate.reply_text).toContain("12 474 036,91 руб.");
|
||||
expect(candidate.reply_text).toContain("денежный operating-flow proxy");
|
||||
expect(candidate.reply_text).not.toContain("Что можно сказать только как вывод:");
|
||||
expect(candidate.reply_text).not.toContain("Складской срез");
|
||||
});
|
||||
|
||||
it("localizes value-flow evidence without leaking pilot mechanics", () => {
|
||||
const candidate = buildAssistantMcpDiscoveryResponseCandidate(
|
||||
entryPoint({
|
||||
|
||||
@@ -1989,6 +1989,65 @@ describe("assistant MCP discovery turn input adapter", () => {
|
||||
expect(result.data_need_graph?.clarification_gaps).toEqual([]);
|
||||
expect(result.data_need_graph?.time_scope_need).toBe("all_time_scope");
|
||||
expect(result.data_need_graph?.reason_codes).toContain("data_need_graph_all_time_scope_hint");
|
||||
expect(result.data_need_graph?.reason_codes).toContain("data_need_graph_business_overview_direct_money_answer");
|
||||
});
|
||||
|
||||
it.skip("marks organization-level top-year wording as a direct business-overview money answer", () => {
|
||||
const orgName = "ООО Альтернатива Плюс";
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "какой у нас самый доходный год",
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "business_overview_route_template_v1",
|
||||
previous_filters: {
|
||||
organization: orgName
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.data_need_graph?.business_fact_family).toBe("business_overview");
|
||||
expect(result.data_need_graph?.ranking_need).toBe("top_desc");
|
||||
expect(result.data_need_graph?.reason_codes).toContain("data_need_graph_business_overview_direct_money_answer");
|
||||
});
|
||||
|
||||
it("marks UTF-8 organization-level top-year wording as a direct business-overview money answer", () => {
|
||||
const orgName = "\u041e\u041e\u041e \u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u041f\u043b\u044e\u0441";
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage:
|
||||
"\u043a\u0430\u043a\u043e\u0439 \u0443 \u043d\u0430\u0441 \u0441\u0430\u043c\u044b\u0439 \u0434\u043e\u0445\u043e\u0434\u043d\u044b\u0439 \u0433\u043e\u0434",
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "business_overview_route_template_v1",
|
||||
previous_filters: {
|
||||
organization: orgName
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.data_need_graph?.business_fact_family).toBe("business_overview");
|
||||
expect(result.data_need_graph?.ranking_need).toBe("top_desc");
|
||||
expect(result.data_need_graph?.reason_codes).toContain("data_need_graph_business_overview_direct_money_answer");
|
||||
});
|
||||
|
||||
it("marks explicit-period earned-money wording as a direct business-overview money answer", () => {
|
||||
const orgName = "ООО Альтернатива Плюс";
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "а за 2017 мы скок заработали?",
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "business_overview_route_template_v1",
|
||||
previous_filters: {
|
||||
organization: orgName
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.data_need_graph?.business_fact_family).toBe("business_overview");
|
||||
expect(result.turn_meaning_ref?.explicit_date_scope).toBe("2017");
|
||||
expect(result.data_need_graph?.reason_codes).toContain("data_need_graph_business_overview_direct_money_answer");
|
||||
});
|
||||
|
||||
it("routes organization-level profit and margin wording to business overview instead of exact value recipes", () => {
|
||||
|
||||
@@ -348,6 +348,26 @@ describe("assistantMemoryRecapPolicy", () => {
|
||||
|
||||
const reply = buildSelectedObjectAnswerInspectionReply({
|
||||
addressDebug: context.lastAnswerInspectionAddressDebug,
|
||||
sessionItems: [
|
||||
{
|
||||
role: "assistant",
|
||||
text: "По товару Рабочая станция покупатель определен: Комитет государственных услуг г. Москвы.\nДокументы выбытия:\n1. Реализация товаров и услуг | товар: Рабочая станция | контрагент: Комитет государственных услуг г. Москвы",
|
||||
trace_id: "address-sale-trace",
|
||||
debug: {
|
||||
trace_id: "address-sale-trace",
|
||||
execution_lane: "address_query",
|
||||
answer_grounding_check: {
|
||||
status: "grounded"
|
||||
},
|
||||
detected_intent: "inventory_sale_trace_for_item",
|
||||
extracted_filters: {
|
||||
item: "Рабочая станция",
|
||||
organization: "ООО Альтернатива Плюс",
|
||||
as_of_date: "2016-03-31"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
toNonEmptyString: (value: unknown) => {
|
||||
const text = String(value ?? "").trim();
|
||||
return text.length > 0 ? text : null;
|
||||
@@ -357,7 +377,8 @@ describe("assistantMemoryRecapPolicy", () => {
|
||||
expect(context.contextualAnswerInspectionFollowup).toBe(true);
|
||||
expect(reply).toContain("не контрагент");
|
||||
expect(reply).toContain("Рабочая станция");
|
||||
expect(reply).toContain("Покупатель");
|
||||
expect(reply).toContain("Комитет государственных услуг г. Москвы");
|
||||
expect(reply).not.toContain("Покупатель в доступных данных отдельно не выделен");
|
||||
});
|
||||
|
||||
it("builds deterministic recap summary from grounded MCP discovery counterparty context", () => {
|
||||
|
||||
Reference in New Issue
Block a user