ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Stage 4.7: внедрить stage4_contract_compliance_rate в P0 quality-gap и baseline gate

This commit is contained in:
2026-04-12 09:32:27 +03:00
parent ce1ebae8ec
commit a49212608f
8 changed files with 75 additions and 7 deletions
@@ -161,6 +161,13 @@ function buildQualityGapChecks(input: {
threshold: thresholds.followup_context_retention_score_min,
comparator: ">=",
passed: metrics.followup_context_retention_score >= thresholds.followup_context_retention_score_min
},
{
metric: "stage4_contract_compliance_rate",
value: metrics.stage4_contract_compliance_rate,
threshold: thresholds.stage4_contract_compliance_rate_min,
comparator: ">=",
passed: metrics.stage4_contract_compliance_rate >= thresholds.stage4_contract_compliance_rate_min
}
];
}
@@ -15,6 +15,7 @@ import {
} from "../config";
import { AssistantService } from "../services/assistantService";
import { AssistantSessionStore } from "../services/assistantSessionStore";
import { buildStage4AnswerContractAuditV1 } from "../services/assistantStage4AnswerContractAudit";
import { NormalizerService } from "../services/normalizerService";
import type { AssistantMessageResponsePayload } from "../types/assistant";
import type { EvalRunMode, NormalizeRequestPayload } from "../types/normalizer";
@@ -1291,6 +1292,10 @@ function computeQualityGapMetrics(caseRecords: P0CaseRecord[]): {
const mechanismSpecificityScores = caseRecords.map((item) => item.metric_subscores.mechanism_specificity_score);
const followupCases = caseRecords.filter((item) => item.query_class === "followup_investigation");
const followupRetainedCases = followupCases.filter((item) => item.checks.followup_context_retained).length;
const stage4ContractAuditedCases = caseRecords
.map((item) => buildStage4AnswerContractAuditV1(item.assistant_reply ?? ""))
.filter((item) => item.schema_version === "stage4_answer_contract_audit_v1");
const stage4ContractCompliantCases = stage4ContractAuditedCases.filter((item) => item.is_stage4_shape === true).length;
return {
raw: {
@@ -1299,11 +1304,15 @@ function computeQualityGapMetrics(caseRecords: P0CaseRecord[]): {
mechanism_specificity_score: average(mechanismSpecificityScores),
followup_context_retention_score: round2(
followupCases.length === 0 ? 1 : followupRetainedCases / Math.max(1, followupCases.length)
),
stage4_contract_compliance_rate: round2(
stage4ContractAuditedCases.length === 0 ? 0 : stage4ContractCompliantCases / Math.max(1, stage4ContractAuditedCases.length)
)
},
denominators: {
cases_total: caseRecords.length,
followup_cases_total: followupCases.length
followup_cases_total: followupCases.length,
stage4_contract_audited_cases_total: stage4ContractAuditedCases.length
}
};
}
@@ -68,6 +68,7 @@ export interface P0QualityGapMetricVector {
false_confidence_rate: number;
mechanism_specificity_score: number;
followup_context_retention_score: number;
stage4_contract_compliance_rate: number;
}
export type P0QualityGapMetricName = keyof P0QualityGapMetricVector;
@@ -147,6 +148,11 @@ export const P0_QUALITY_GAP_METRIC_DEFINITIONS: Record<P0QualityGapMetricName, P
description: "Rate of correct context retention in follow-up investigation cases.",
unit: "rate",
direction: "higher_is_better"
},
stage4_contract_compliance_rate: {
description: "Share of answers that satisfy the Stage 4 user-facing answer contract shape.",
unit: "rate",
direction: "higher_is_better"
}
};
@@ -183,6 +189,7 @@ export interface P0QualityGapThresholds {
false_confidence_rate_max: number;
mechanism_specificity_score_min: number;
followup_context_retention_score_min: number;
stage4_contract_compliance_rate_min: number;
}
export const P0_DEFAULT_ACCEPTANCE_THRESHOLDS: P0AcceptanceThresholds = {
@@ -200,7 +207,8 @@ export const P0_DEFAULT_QUALITY_GAP_THRESHOLDS: P0QualityGapThresholds = {
generic_explanation_rate_max: 0.2,
false_confidence_rate_max: 0.12,
mechanism_specificity_score_min: 3.0,
followup_context_retention_score_min: 0.75
followup_context_retention_score_min: 0.75,
stage4_contract_compliance_rate_min: 0.9
};
function isProblemUnitType(value: unknown): value is ProblemUnitType {