File size: 2,404 Bytes
5ab38b4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | """Post-processing review-risk flags for accepted classifications."""
from __future__ import annotations
from gcmd_classifier.models import (
ClassificationFinalStatus,
ClassificationRecord,
OutputWarning,
SupportType,
)
REVIEW_RECOMMENDED_WEAK_SUPPORT = "REVIEW_RECOMMENDED_WEAK_SUPPORT"
def flag_review_risk(
classifications: tuple[ClassificationRecord, ...],
) -> tuple[ClassificationRecord, ...]:
"""Mark accepted classifications that should receive manual scientific review."""
return tuple(_flag_record(record) for record in classifications)
def _flag_record(record: ClassificationRecord) -> ClassificationRecord:
if not _requires_review(record):
return record
warning = OutputWarning(
code=REVIEW_RECOMMENDED_WEAK_SUPPORT,
message="Manual scientific review is recommended because support is weak or inferred.",
stage="review_flagging",
details={
"level": record.level,
"support_type": None if record.support_type is None else record.support_type.value,
"confidence_final": _confidence_final(record),
},
)
warnings = record.warnings
if not any(existing.code == REVIEW_RECOMMENDED_WEAK_SUPPORT for existing in warnings):
warnings = (*warnings, warning)
return record.model_copy(update={"review_required": True, "warnings": warnings})
def _requires_review(record: ClassificationRecord) -> bool:
if record.final_status is not ClassificationFinalStatus.ACCEPTED:
return False
if record.support_type is None:
return False
confidence_final = _confidence_final(record)
if record.level == "Topic" and record.support_type in {
SupportType.INFERRED,
SupportType.MIXED,
}:
return True
if record.support_type is SupportType.INFERRED and record.level in {
"Variable_Level_2",
"Variable_Level_3",
}:
return True
if (
record.support_type is SupportType.INFERRED
and confidence_final is not None
and confidence_final < 0.75
):
return True
return (
record.support_type is SupportType.MIXED
and confidence_final is not None
and confidence_final < 0.70
)
def _confidence_final(record: ClassificationRecord) -> float | None:
return None if record.confidence is None else record.confidence.final
|