NODEDC_1C/llm_normalizer/backend/src/services/assistantDeepTurnCompositio...

78 lines
3.5 KiB
TypeScript

import type { AssistantRequirement, AnswerGroundingCheck, RequirementCoverageReport, UnifiedRetrievalResult } from "../types/assistant";
import type { NormalizeResponsePayload, RouteHintSummary } from "../types/normalizer";
import type { InvestigationStateWithProblemUnits } from "../types/stage2ProblemUnits";
import type { QuestionTypeClass } from "./questionTypeResolver";
import { resolveQuestionType } from "./questionTypeResolver";
import { composeAssistantAnswer } from "./answerComposer";
export interface BuildAssistantDeepTurnCompositionInput {
userMessage: string;
routeSummary: RouteHintSummary | null;
retrievalResults: UnifiedRetrievalResult[];
requirements: AssistantRequirement[];
coverageReport: RequirementCoverageReport;
groundingCheck: AnswerGroundingCheck;
followupUsage: unknown | null | undefined;
investigationState: InvestigationStateWithProblemUnits | null | undefined;
companyAnchors: unknown;
normalizedPayload: NormalizeResponsePayload["normalized"];
featureAnswerPolicyV11: boolean;
featureProblemCentricAnswerV1: boolean;
featureLifecycleAnswerV1: boolean;
hasExplicitPeriodAnchor: (normalizedPayload: NormalizeResponsePayload["normalized"]) => boolean;
resolveQuestionTypeFn?: (input: string) => QuestionTypeClass;
composeAssistantAnswerFn?: typeof composeAssistantAnswer;
}
export interface AssistantDeepTurnCompositionOutput {
focusDomainHint: string | null;
questionTypeClass: QuestionTypeClass;
hasPeriodInCompanyAnchors: boolean;
normalizationPeriodExplicit: boolean;
composition: ReturnType<typeof composeAssistantAnswer>;
}
export function buildAssistantDeepTurnComposition(
input: BuildAssistantDeepTurnCompositionInput
): AssistantDeepTurnCompositionOutput {
const resolveQuestionTypeSafe = input.resolveQuestionTypeFn ?? resolveQuestionType;
const composeAssistantAnswerSafe = input.composeAssistantAnswerFn ?? composeAssistantAnswer;
const followupApplied = Boolean((input.followupUsage as { applied?: unknown } | null)?.applied);
const focusDomainHint = followupApplied
? input.investigationState?.followup_context?.active_domain ?? input.investigationState?.focus.domain ?? null
: null;
const questionTypeClass = resolveQuestionTypeSafe(input.userMessage);
const companyAnchorSet = input.companyAnchors as {
dates?: unknown[];
periods?: unknown[];
} | null;
const hasPeriodInCompanyAnchors =
(Array.isArray(companyAnchorSet?.dates) && companyAnchorSet.dates.some((item) => String(item ?? "").trim().length > 0)) ||
(Array.isArray(companyAnchorSet?.periods) && companyAnchorSet.periods.some((item) => String(item ?? "").trim().length > 0));
const normalizationPeriodExplicit = input.hasExplicitPeriodAnchor(input.normalizedPayload) || hasPeriodInCompanyAnchors;
const composition = composeAssistantAnswerSafe({
userMessage: input.userMessage,
routeSummary: input.routeSummary,
retrievalResults: input.retrievalResults,
requirements: input.requirements,
coverageReport: input.coverageReport,
groundingCheck: input.groundingCheck,
focusDomainHint,
questionTypeHint: questionTypeClass,
companyAnchors: input.companyAnchors as any,
normalizationPeriodExplicit,
enableAnswerPolicyV11: input.featureAnswerPolicyV11,
enableProblemCentricAnswerV1: input.featureProblemCentricAnswerV1,
enableLifecycleAnswerV1: input.featureLifecycleAnswerV1
});
return {
focusDomainHint,
questionTypeClass,
hasPeriodInCompanyAnchors,
normalizationPeriodExplicit,
composition
};
}