NODEDC_1C/llm_normalizer/backend/tests/addressImplicitOrganization...

184 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { afterEach, describe, expect, it, vi } from "vitest";
const { executeAddressMcpQueryMock } = vi.hoisted(() => ({
executeAddressMcpQueryMock: vi.fn()
}));
vi.mock("../src/services/addressMcpClient", async () => {
const actual = await vi.importActual<typeof import("../src/services/addressMcpClient")>(
"../src/services/addressMcpClient"
);
return {
...actual,
executeAddressMcpQuery: executeAddressMcpQueryMock
};
});
import { AddressQueryService } from "../src/services/addressQueryService";
afterEach(() => {
executeAddressMcpQueryMock.mockReset();
vi.restoreAllMocks();
});
describe("implicit organization stock scope", () => {
it("uses llm semantic hints to ground informal organization wording without turning it into warehouse anchor", async () => {
executeAddressMcpQueryMock.mockResolvedValueOnce({
fetched_rows: 1,
matched_rows: 1,
raw_rows: [
{
Period: "2026-04-15T23:59:59Z",
Registrator: "Остатки товаров на складах",
AccountDt: "41.01",
AccountKt: "00.00",
Amount: 148261.67,
Quantity: 22,
SubcontoDt1: "Модуль прямоугольый 1400*110*750",
Warehouse: "Основной склад",
Organization: 'ООО "Альтернатива Плюс"'
}
],
rows: [],
error: null
});
const service = new AddressQueryService();
const result = await service.tryHandle("что на складе конторы альтернатива", {
llmSemanticHints: {
scope_target_kind: "organization",
scope_target_text: "Альтернатива",
date_scope_kind: "implicit_current",
self_scope_detected: false,
selected_object_scope_detected: false
}
});
expect(result?.handled).toBe(true);
expect(result?.reply_type).toBe("factual");
expect(result?.response_type).toBe("FACTUAL_LIST");
expect(result?.debug.detected_intent).toBe("inventory_on_hand_as_of_date");
expect(result?.debug.selected_recipe).toBe("address_inventory_on_hand_as_of_date_v1");
expect(result?.debug.mcp_call_status).toBe("matched_non_empty");
expect(result?.debug.extracted_filters?.organization).toBe("Альтернатива");
expect(result?.debug.extracted_filters?.warehouse).toBeUndefined();
expect(result?.debug.semantic_frame?.scope_kind).toBe("explicit_anchor");
expect(result?.debug.semantic_frame?.anchor_kind).toBe("organization");
expect(result?.debug.semantic_frame?.anchor_value).toBe("Альтернатива");
expect(result?.debug.as_of_date_basis).toBe("implicit_current_snapshot");
expect(String(result?.reply_text ?? "")).toContain("Модуль прямоугольый 1400*110*750");
});
it("re-grounds warehouse-like informal company wording to live organization candidate set", async () => {
executeAddressMcpQueryMock.mockResolvedValueOnce({
fetched_rows: 1,
matched_rows: 1,
raw_rows: [
{
Period: "2026-04-15T23:59:59Z",
Registrator: "Остатки товаров на складах",
AccountDt: "41.01",
AccountKt: "00.00",
Amount: 833.33,
Quantity: 1,
SubcontoDt1: "Четки Пост (84*117)",
Warehouse: "Основной склад",
Organization: "ООО КОТ ССЫТ ВО ДВОРЕ"
}
],
rows: [],
error: null
});
const service = new AddressQueryService();
const result = await service.tryHandle("что на складе конторы ссыт кот", {
activeOrganization: "ООО КОТ ССЫТ ВО ДВОРЕ",
knownOrganizations: ["ООО КОТ ССЫТ ВО ДВОРЕ", "ООО Альтернатива Плюс"]
});
expect(result?.handled).toBe(true);
expect(result?.reply_type).toBe("factual");
expect(result?.debug.extracted_filters?.organization).toBe("ООО КОТ ССЫТ ВО ДВОРЕ");
expect(result?.debug.extracted_filters?.warehouse).toBeUndefined();
expect(result?.debug.anchor_type).toBe("organization");
expect(result?.debug.reasons).toContain("warehouse_anchor_regrounded_to_organization_scope");
expect(result?.debug.reasons).toContain("organization_scope_live_grounding_recovered_rows");
expect(String(result?.reply_text ?? "")).toContain("Четки Пост (84*117)");
});
it("handles slang stock-state wording as current inventory snapshot for grounded organization scope", async () => {
executeAddressMcpQueryMock.mockResolvedValueOnce({
fetched_rows: 1,
matched_rows: 1,
raw_rows: [
{
Period: "2026-04-15T23:59:59Z",
Registrator: "Остатки товаров на складах",
AccountDt: "41.01",
AccountKt: "00.00",
Amount: 34490,
Quantity: 1,
SubcontoDt1: "Диван трехместный",
Warehouse: "Основной склад",
Organization: "ООО Альтернатива Плюс"
}
],
rows: [],
error: null
});
const service = new AddressQueryService();
const result = await service.tryHandle("чекни плиз чо там на складе альтернативы происходит", {
activeOrganization: "ООО Альтернатива Плюс",
knownOrganizations: ["ООО Альтернатива Плюс", "ООО Лайсвуд"]
});
expect(result?.handled).toBe(true);
expect(result?.reply_type).toBe("factual");
expect(result?.debug.detected_intent).toBe("inventory_on_hand_as_of_date");
expect(result?.debug.selected_recipe).toBe("address_inventory_on_hand_as_of_date_v1");
expect(result?.debug.extracted_filters?.organization).toBe("ООО Альтернатива Плюс");
expect(result?.debug.extracted_filters?.warehouse).toBeUndefined();
expect(result?.debug.as_of_date_basis).toBe("implicit_current_snapshot");
expect(String(result?.reply_text ?? "")).toContain("Диван трехместный");
});
it("handles short colloquial stock query as current inventory snapshot for grounded organization scope", async () => {
executeAddressMcpQueryMock.mockResolvedValueOnce({
fetched_rows: 1,
matched_rows: 1,
raw_rows: [
{
Period: "2026-04-15T23:59:59Z",
Registrator: "Остатки товаров на складах",
AccountDt: "41.01",
AccountKt: "00.00",
Amount: 6490,
Quantity: 1,
SubcontoDt1: "Пуф арий",
Warehouse: "Основной склад",
Organization: "ООО Альтернатива Плюс"
}
],
rows: [],
error: null
});
const service = new AddressQueryService();
const result = await service.tryHandle("че на складах альтернативы", {
activeOrganization: "ООО Альтернатива Плюс",
knownOrganizations: ["ООО Альтернатива Плюс", "ООО Лайсвуд"]
});
expect(result?.handled).toBe(true);
expect(result?.reply_type).toBe("factual");
expect(result?.debug.detected_intent).toBe("inventory_on_hand_as_of_date");
expect(result?.debug.selected_recipe).toBe("address_inventory_on_hand_as_of_date_v1");
expect(result?.debug.extracted_filters?.organization).toBe("ООО Альтернатива Плюс");
expect(result?.debug.extracted_filters?.warehouse).toBeUndefined();
expect(result?.debug.anchor_type).toBe("organization");
expect(result?.debug.as_of_date_basis).toBe("implicit_current_snapshot");
expect(String(result?.reply_text ?? "")).toContain("Пуф арий");
});
});