NODEDC_1C/llm_normalizer/backend/tests/assistantWave17RunRegressio...

109 lines
4.9 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 { AddressQueryService } from "../src/services/addressQueryService";
import { resolveAssistantOrchestrationDecision, resolveLivingAssistantModeDecision } from "../src/services/assistantService";
describe("wave17 run regressions (2026-04-11 real runs)", () => {
it("keeps real run 17:51 data-heavy prompts in address lane", () => {
const realRunPrompts = [
"Где у нас накопились авансы к отгрузкам, которые уже давно пора закрыть или хотя бы перепроверить, чтобы не подозревать худшее?",
"Какие контрагенты у нас на этом моменте могут быть причислены к тем, кто вообще не платит уже несколько месяцев?",
"В каких случаях мы видим зависшие отгрузки, которые уже давно пора закрыть - это грозит проблемами в отчетности."
];
for (const prompt of realRunPrompts) {
const decision = resolveAssistantOrchestrationDecision({
rawUserMessage: prompt,
effectiveAddressUserMessage: prompt,
followupContext: null,
llmPreDecomposeMeta: null,
useMock: false
});
expect(decision.runAddressLane).toBe(true);
expect(["address_mode_classifier_detected", "address_signal_detected", "address_intent_resolver_detected"]).toContain(
decision.toolGateReason
);
expect(decision.livingMode).toBe("address_data");
expect(decision.livingReason).toBe("address_lane_triggered");
}
});
it("keeps short follow-up style prompts out of chat drift when predecompose says unsupported", () => {
const shortFollowups = ["без воды?", "и коротко?", "прям сейчас?"];
for (const prompt of shortFollowups) {
const decision = resolveLivingAssistantModeDecision({
userMessage: prompt,
addressLaneTriggered: false,
useMock: false,
predecomposeMode: "unsupported",
predecomposeModeConfidence: "low"
});
expect(decision.mode).toBe("deep_analysis");
expect(decision.reason).toBe("predecompose_unsupported_mode_fallback_to_deep");
}
});
it("routes data-scope slang wording to chat mode", () => {
const decision = resolveLivingAssistantModeDecision({
userMessage: "по каким конторам можем общаться?",
addressLaneTriggered: false,
useMock: false,
predecomposeMode: "unsupported",
predecomposeModeConfidence: "low"
});
expect(decision.mode).toBe("chat");
expect(decision.reason).toBe("assistant_data_scope_query_detected");
});
it("keeps open-contracts request in address lane even with stale deep followup context", () => {
const decision = resolveAssistantOrchestrationDecision({
rawUserMessage: "Покажи незакрытые договоры на 2020-12-31",
effectiveAddressUserMessage: "Покажи незакрытые договоры на 2020-12-31",
followupContext: {
previous_question_id: "msg-prev",
last_user_message: "почему так по закрытию месяца",
active_domain: "month_close_costs_20_44",
active_requirement_ids: ["R1"],
uncovered_requirement_ids: ["R1"],
referenced_requirement_ids: ["R1"]
} as any,
llmPreDecomposeMeta: {
applied: true,
llmCanonicalCandidateDetected: true,
reason: "normalized_fragment_applied",
predecomposeContract: {
mode: "address_query",
mode_confidence: "high",
intent: "list_open_contracts",
intent_confidence: "medium"
}
} as any,
useMock: false
});
expect(decision.runAddressLane).toBe(true);
expect(decision.livingMode).toBe("address_data");
expect(decision.livingReason).toBe("address_lane_triggered");
expect(decision.orchestrationContract?.deep_analysis_signal_fallback_to_deep).toBe(false);
});
it("uses soft unsupported aggregate replies instead of rigid old template", async () => {
const service = new AddressQueryService();
const prompts = ["какой самый доходный год?", "какие обороты по альтернативе за 2020 год"];
for (const prompt of prompts) {
const result = await service.tryHandle(prompt);
const reply = String(result?.reply_text ?? "");
expect(result?.handled).toBe(true);
expect(result?.reply_type).toBe("partial_coverage");
expect(result?.debug.limited_reason_category).toBe("unsupported");
expect(reply).toContain("Что могу сделать сейчас:");
expect(reply).not.toMatch(/Сейчас этот тип вопроса вне поддерживаемого контура адресного режима/iu);
}
});
});