NODEDC_1C/llm_normalizer/backend/tests/assistantMetaFollowupPolicy...

146 lines
6.4 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 { describe, expect, it } from "vitest";
import { createAssistantMetaFollowupPolicy } from "../src/services/assistantMetaFollowupPolicy";
const policy = createAssistantMetaFollowupPolicy({
hasAssistantDataScopeMetaQuestionSignal: (text: unknown) =>
/по какой компании|какая база/i.test(String(text ?? "")),
shouldHandleAsAssistantCapabilityMetaQuery: (text: unknown) =>
/что СС РјРѕР¶РµС€СЊ|что СС СѓРјРµРµС€СЊ/i.test(String(text ?? "")),
hasMetaAnswerFollowupSignal: (text: unknown) =>
/это норм|что думаешь/i.test(String(text ?? "")),
hasAnswerInspectionFollowupSignal: (text: unknown) =>
/это ошибка|у тебя написано кто контрагент/i.test(String(text ?? ""))
});
describe("assistantMetaFollowupPolicy", () => {
it("collects meta signals across message variants", () => {
const signals = policy.resolveMetaSignalSet({
rawUserMessage: "",
repairedRawUserMessage: "",
effectiveAddressUserMessage: "РїРѕ какой компании РјС РјРѕР¶РµРј работать?",
repairedEffectiveAddressUserMessage: ""
});
expect(signals.dataScopeMetaQuery).toBe(true);
expect(signals.capabilityMetaQuery).toBe(false);
expect(signals.metaAnswerFollowupSignal).toBe(false);
expect(signals.answerInspectionFollowupSignal).toBe(false);
});
it("treats historical capability phrasing as capability meta follow-up", () => {
const signals = policy.resolveMetaSignalSet({
rawUserMessage: "а исторические остатки тоже можешь?",
repairedRawUserMessage: "",
effectiveAddressUserMessage: "",
repairedEffectiveAddressUserMessage: ""
});
expect(signals.capabilityMetaQuery).toBe(true);
});
it("resolves hard meta mode with data retrieval guard", () => {
expect(
policy.resolveHardMetaMode({
dataScopeMetaQuery: true,
capabilityMetaQuery: false,
dataRetrievalSignal: false
})
).toBe("data_scope");
expect(
policy.resolveHardMetaMode({
dataScopeMetaQuery: false,
capabilityMetaQuery: true,
dataRetrievalSignal: true
})
).toBeNull();
});
it("detects 1C schema/catalog questions as data-scope meta even when base detector misses them", () => {
const signals = policy.resolveMetaSignalSet({
rawUserMessage:
"\u041a\u0430\u043a\u0438\u0435 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0438 1\u0421 \u0435\u0441\u0442\u044c \u043f\u043e \u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442\u0430\u043c?",
repairedRawUserMessage: "",
effectiveAddressUserMessage: "",
repairedEffectiveAddressUserMessage: ""
});
expect(signals.dataScopeMetaQuery).toBe(true);
expect(signals.capabilityMetaQuery).toBe(false);
});
it("detects document field/link questions as schema meta rather than fake counterparty documents", () => {
const signals = policy.resolveMetaSignalSet({
rawUserMessage:
"\u041a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u0438 \u0441\u0432\u044f\u0437\u0438 \u0441\u0442\u043e\u0438\u0442 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0443 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f?",
repairedRawUserMessage: "",
effectiveAddressUserMessage: "",
repairedEffectiveAddressUserMessage: ""
});
expect(signals.dataScopeMetaQuery).toBe(true);
expect(signals.capabilityMetaQuery).toBe(false);
});
it("does not turn debt classification wording into capability meta help", () => {
const noisyPolicy = createAssistantMetaFollowupPolicy({
hasAssistantDataScopeMetaQuestionSignal: () => false,
shouldHandleAsAssistantCapabilityMetaQuery: () => true,
hasMetaAnswerFollowupSignal: () => false,
hasAnswerInspectionFollowupSignal: () => false
});
const signals = noisyPolicy.resolveMetaSignalSet({
rawUserMessage:
"\u042d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0440\u043e\u0447\u043a\u043e\u0439 \u0438\u043b\u0438 \u043f\u043e\u043a\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u0437\u0430\u0434\u043e\u043b\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e?",
repairedRawUserMessage: "",
effectiveAddressUserMessage: "",
repairedEffectiveAddressUserMessage: ""
});
expect(signals.capabilityMetaQuery).toBe(false);
});
it("detects evaluative meta follow-up over grounded answer", () => {
const detected = policy.isMetaFollowupOverGroundedAnswer({
followupContext: { previous_intent: "vat_payable_forecast" },
hasPriorAddressAnswerContext: true,
metaAnswerFollowupSignal: true,
vatEvaluativeFollowupSignal: false,
dataScopeMetaQuery: false,
capabilityMetaQuery: false,
aggregateBusinessAnalyticsSignal: false,
dataRetrievalSignal: false,
strongDataSignal: false,
resolvedMode: "unsupported",
resolvedIntent: "unknown",
llmContractIntent: "unknown",
llmContractMode: "unsupported"
});
expect(detected).toBe(true);
});
it("detects answer inspection follow-up over grounded answer", () => {
const signals = policy.resolveMetaSignalSet({
rawUserMessage: "у тебя написано кто контрагент: рабочая станция - это ошибка?",
repairedRawUserMessage: "",
effectiveAddressUserMessage: "",
repairedEffectiveAddressUserMessage: ""
});
expect(signals.answerInspectionFollowupSignal).toBe(true);
const detected = policy.isAnswerInspectionFollowupOverGroundedAnswer({
followupContext: { previous_intent: "inventory_sale_trace_for_item", previous_anchor_type: "item" },
hasPriorAddressAnswerContext: true,
answerInspectionFollowupSignal: true,
dataScopeMetaQuery: false,
capabilityMetaQuery: false,
aggregateBusinessAnalyticsSignal: false
});
expect(detected).toBe(true);
});
});