АДРЕСНЫЙ РЕЖИМ - L0-стабилизация address: LLM-first + deterministic fallback + tool-gate + trace

This commit is contained in:
2026-04-01 22:34:58 +03:00
parent b2d32f869c
commit 2d95ce6332
2 changed files with 454 additions and 7 deletions
@@ -152,5 +152,67 @@ describe("assistant address llm pre-decompose candidate preference", () => {
expect(response.debug?.llm_decomposition_attempted).toBe(true);
expect(response.debug?.llm_decomposition_applied).toBe(true);
expect(response.debug?.llm_decomposition_effective_message).toBe("svk doki za 20 god pokezh");
expect(response.debug?.fallback_rule_hit).toBeNull();
expect(response.debug?.sanitized_user_message).toBeTypeOf("string");
expect(response.debug?.tool_gate_decision).toBe("run_address_lane");
});
it("applies deterministic fallback rule when llm fragment is unusable", async () => {
const calls: Array<{ message: string }> = [];
const addressQueryService = {
tryHandle: vi.fn(async (message: string) => {
calls.push({ message });
return buildAddressLaneResult(message);
})
} as any;
const normalizerService = {
normalize: vi.fn(async () => ({
trace_id: "norm-predecompose-2",
ok: true,
normalized: {
schema_version: "normalized_query_v2_0_2",
user_message_raw: "свк доки за 20год покеж плс",
message_in_scope: true,
scope_confidence: "medium",
contains_multiple_tasks: false,
fragments: []
},
raw_model_output: null,
validation: { passed: true, errors: [] },
usage: { input_tokens: 1, output_tokens: 1, total_tokens: 2 },
latency_ms: 10,
prompt_version: "normalizer_v2_0_2",
schema_version: "v2_0_2",
request_count_for_case: 1
}))
} as any;
const sessions = new AssistantSessionStore();
const service = new AssistantService(
normalizerService,
sessions as any,
{} as any,
{ persistSession: vi.fn() } as any,
addressQueryService
);
const response = await service.handleMessage({
session_id: `asst-predecompose-fallback-${Date.now()}`,
user_message: "свк доки за 20год покеж плс",
llmProvider: "local",
useMock: false
} as any);
expect(response.ok).toBe(true);
expect(response.reply_type).toBe("factual");
expect(calls).toHaveLength(1);
expect(calls[0].message).toBe("документы по контрагенту свк за 2020 год");
expect(response.debug?.llm_decomposition_attempted).toBe(true);
expect(response.debug?.llm_decomposition_applied).toBe(true);
expect(response.debug?.llm_decomposition_reason).toBe("fallback_rule_applied_after_llm");
expect(response.debug?.fallback_rule_hit).toBe("documents_counterparty_year_rewrite");
expect(response.debug?.sanitized_user_message).toContain("свк");
expect(response.debug?.tool_gate_decision).toBe("run_address_lane");
});
});