АРЧ АП11 - Исправить маршрутизацию selected-object и явных root-вопросов после складового контекста
This commit is contained in:
@@ -62,4 +62,53 @@ describe("inventory root frame regressions", () => {
|
||||
result?.intent.reasons.includes("inventory_selected_object_provenance_signal_detected")
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("does not restore inventory root when the follow-up is an explicit receivables root query", () => {
|
||||
const result = runAddressDecomposeStage("покажи кто нам должен денег на май 2017", {
|
||||
previous_intent: "inventory_sale_trace_for_item",
|
||||
previous_filters: {
|
||||
item: "Четки Пост (84*117)",
|
||||
as_of_date: "2020-05-31",
|
||||
period_from: "2020-05-01",
|
||||
period_to: "2020-05-31"
|
||||
},
|
||||
previous_anchor_type: "item",
|
||||
previous_anchor_value: "Четки Пост (84*117)",
|
||||
root_intent: "inventory_on_hand_as_of_date",
|
||||
root_filters: {
|
||||
period_from: "2020-05-01",
|
||||
period_to: "2020-05-31",
|
||||
as_of_date: "2020-05-31"
|
||||
},
|
||||
root_anchor_type: "unknown",
|
||||
root_anchor_value: null,
|
||||
current_frame_kind: "inventory_drilldown"
|
||||
});
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.intent.intent).toBe("receivables_confirmed_as_of_date");
|
||||
expect(result?.intent.reasons).not.toContain("intent_restored_to_inventory_root_frame");
|
||||
expect(result?.filters.extracted_filters.as_of_date).toBe("2017-05-31");
|
||||
});
|
||||
|
||||
it("keeps selected-object loose documents wording in the inventory document contour", () => {
|
||||
const result = runAddressDecomposeStage(
|
||||
'По выбранному объекту "Четки Пост (84*117)": меня четки интересуют покажи документы все по ним и все операции',
|
||||
{
|
||||
previous_intent: "inventory_on_hand_as_of_date",
|
||||
previous_filters: {
|
||||
as_of_date: "2020-05-31",
|
||||
period_from: "2020-05-01",
|
||||
period_to: "2020-05-31"
|
||||
},
|
||||
previous_anchor_type: "unknown",
|
||||
previous_anchor_value: null
|
||||
}
|
||||
);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.intent.intent).toBe("inventory_purchase_documents_for_item");
|
||||
expect(result?.intent.intent).not.toBe("bank_operations_by_counterparty");
|
||||
expect(result?.filters.extracted_filters.item).toBe("Четки Пост (84*117)");
|
||||
});
|
||||
});
|
||||
|
||||
+34
@@ -75,6 +75,40 @@ describe("inventory sale trace selected-object regressions", () => {
|
||||
expect(query).not.toContain('Номенклатура.Наименование = "Кромка"');
|
||||
});
|
||||
|
||||
it("routes selected-object delivery wording 'кому мы это поставили' into sale trace", async () => {
|
||||
executeAddressMcpQueryMock.mockResolvedValueOnce({
|
||||
fetched_rows: 1,
|
||||
matched_rows: 1,
|
||||
raw_rows: [saleRow],
|
||||
rows: [],
|
||||
error: null
|
||||
});
|
||||
|
||||
const service = new AddressQueryService();
|
||||
const result = await service.tryHandle(
|
||||
'По выбранному объекту "Кромка с клеем 33 дуб ниагара 137 м": кому мы это поставили',
|
||||
{
|
||||
followupContext: {
|
||||
previous_intent: "inventory_on_hand_as_of_date",
|
||||
previous_filters: {
|
||||
as_of_date: "2021-03-31",
|
||||
period_from: "2021-03-01",
|
||||
period_to: "2021-03-31",
|
||||
organization: "ООО \\Альтернатива Плюс\\"
|
||||
},
|
||||
previous_anchor_type: "unknown",
|
||||
previous_anchor_value: null
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
expect(result?.handled).toBe(true);
|
||||
expect(result?.response_type).toBe("FACTUAL_LIST");
|
||||
expect(result?.debug.detected_intent).toBe("inventory_sale_trace_for_item");
|
||||
expect(result?.debug.extracted_filters?.item).toBe("Кромка с клеем 33 дуб ниагара 137 м");
|
||||
expect(String(result?.reply_text ?? "")).toContain("ООО \\Покупатель\\");
|
||||
});
|
||||
|
||||
it("keeps the full selected item for canonical selected-object buyer wording", async () => {
|
||||
executeAddressMcpQueryMock.mockResolvedValueOnce({
|
||||
fetched_rows: 1,
|
||||
|
||||
@@ -314,4 +314,67 @@ describe("assistant address orchestration runtime adapter", () => {
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("prefers raw selected-object delivery wording over generic canonical drift intent", async () => {
|
||||
const resolveAddressFollowupCarryoverContext = vi.fn(() => ({
|
||||
followupContext: {
|
||||
previous_intent: "inventory_on_hand_as_of_date",
|
||||
previous_filters: {
|
||||
as_of_date: "2021-03-31",
|
||||
period_from: "2021-03-01",
|
||||
period_to: "2021-03-31"
|
||||
}
|
||||
}
|
||||
}));
|
||||
const resolveAssistantOrchestrationDecision = vi.fn(() => ({
|
||||
runAddressLane: true,
|
||||
livingMode: "address_data",
|
||||
livingReason: "address_lane_triggered",
|
||||
toolGateDecision: "run_address_lane",
|
||||
toolGateReason: "address_mode_classifier_detected",
|
||||
orchestrationContract: { schema_version: "assistant_orchestration_contract_v1" }
|
||||
}));
|
||||
const buildAddressLlmPredecomposeContractV1 = vi.fn(({ sourceMessage, canonicalMessage }: { sourceMessage: string; canonicalMessage: string }) => ({
|
||||
schema_version: "address_llm_predecompose_contract_v1",
|
||||
source_message: sourceMessage,
|
||||
canonical_message: canonicalMessage,
|
||||
mode: "address_query",
|
||||
intent: "unknown"
|
||||
}));
|
||||
|
||||
const rawMessage = 'По выбранному объекту "Кромка с клеем 33 дуб ниагара 137 м": кому мы это поставили';
|
||||
|
||||
const output = await buildAssistantAddressOrchestrationRuntime(
|
||||
buildInput({
|
||||
userMessage: rawMessage,
|
||||
runAddressLlmPreDecompose: vi.fn(async () => ({
|
||||
attempted: true,
|
||||
applied: true,
|
||||
effectiveMessage: "Покажи взаиморасчеты с контрагентом по выбранной позиции",
|
||||
reason: "normalized_fragment_applied",
|
||||
predecomposeContract: {
|
||||
mode: "address_query",
|
||||
intent: "bank_operations_by_counterparty",
|
||||
semantics: {
|
||||
selected_object_scope_detected: true
|
||||
}
|
||||
}
|
||||
})),
|
||||
buildAddressLlmPredecomposeContractV1,
|
||||
resolveAddressFollowupCarryoverContext,
|
||||
resolveAssistantOrchestrationDecision
|
||||
})
|
||||
);
|
||||
|
||||
expect(output.addressInputMessage).toBe(rawMessage);
|
||||
expect(output.addressPreDecompose.applied).toBe(false);
|
||||
expect(output.addressPreDecompose.reason).toBe("followup_raw_message_preferred_over_llm_rewrite");
|
||||
expect(resolveAddressFollowupCarryoverContext).toHaveBeenCalledTimes(2);
|
||||
expect(resolveAssistantOrchestrationDecision).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
rawUserMessage: rawMessage,
|
||||
effectiveAddressUserMessage: rawMessage
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user