Spaces:
Sleeping
Sleeping
| """ | |
| Node 6 (Grader): Dataset Health Grader β Sub-env 2. | |
| This module implements the per-clip disposition grader that evaluates the | |
| output of the Clip Disposition Recommender agent (Node 5). | |
| ``grade_clip_disposition`` scores a single clip decision. The Dataset Health | |
| Grader (Node 6) aggregates scores across all clips and produces the | |
| ``DatasetHealthHandoff``. | |
| Scoring contract | |
| ---------------- | |
| - Maximum achievable score: 0.80 (0.40 base + 0.20 fix quality + 0.20 reasoning) | |
| - Override misuse subtracts up to 0.10 from the running total. | |
| - Final score is clamped to [0.0, 1.0] β never negative. | |
| - The ``defer`` branch checks ``ground_truth.disposition_ambiguity >= 0.5``; | |
| deferring on an unambiguous case is penalised as avoidance. | |
| - The override penalty applies **only** when ``override_decision == "applied"``. | |
| """ | |
| from __future__ import annotations | |
| from src.schemas.ground_truth import GroundTruthClipAnnotation | |
| from src.schemas.subenv2 import ClipDispositionAction | |
| def grade_clip_disposition( | |
| agent_action: ClipDispositionAction, | |
| ground_truth: GroundTruthClipAnnotation, | |
| ) -> float: | |
| """Grade a single clip disposition recommendation (Node 5). | |
| Evaluates four dimensions and returns a clamped composite score in | |
| [0.0, 1.0]: | |
| **1. Base disposition** (0.40 max) | |
| - Correct disposition + confidence within 0.15 of ground truth β +0.40 | |
| - Correct disposition but miscalibrated confidence β +0.28 | |
| - ``"fix"`` when ground truth is ``"reject"`` β +0.20 | |
| (partial credit: fix is better than blind accept) | |
| - ``"defer"`` on an ambiguous case (ambiguity β₯ 0.5): | |
| - with ``defer_reason`` β +0.15 | |
| - without ``defer_reason`` β +0.10 | |
| - ``"defer"`` on an unambiguous case (ambiguity < 0.5) β β0.05 | |
| (avoidance penalty; clamped so total never goes below 0.0) | |
| - ``"accept"`` when ground truth is ``"reject"`` β +0.00 | |
| (worst case) | |
| **2. Fix instruction quality** (0.20 max) | |
| Applies only when ``disposition == "fix"`` and ``fix_instructions`` is | |
| non-empty. Precision = fraction of agent steps present in | |
| ``ground_truth.valid_fix_steps``: | |
| - precision β₯ 0.8 β +0.20 | |
| - precision β₯ 0.5 β +0.10 | |
| - precision < 0.5 β +0.00 | |
| **3. Dataset impact reasoning** (0.20 max) | |
| Checks how many of ``ground_truth.expected_reasoning_elements`` appear | |
| (case-insensitive substring) in ``dataset_impact_reasoning``: | |
| - β₯ 80 % matched β +0.20 | |
| - β₯ 1 matched β +0.10 | |
| - none matched β +0.00 | |
| **4. Override misuse penalty** (applies only when ``override_decision == "applied"``) | |
| - No ``override_justification`` provided β β0.10 | |
| - Justification not in valid set β β0.05 | |
| - Valid justification present β no penalty | |
| Args: | |
| agent_action: The ``ClipDispositionAction`` produced by the Node 5 agent. | |
| ground_truth: The ``GroundTruthClipAnnotation`` for this test case. | |
| Returns: | |
| A float in [0.0, 1.0] representing the per-clip grader score. | |
| """ | |
| score: float = 0.0 | |
| # ------------------------------------------------------------------ | |
| # 1. Base disposition (0.40 max) | |
| # ------------------------------------------------------------------ | |
| if agent_action.disposition == ground_truth.disposition: | |
| calibrated = abs(agent_action.confidence - ground_truth.confidence) < 0.15 | |
| score += 0.40 if calibrated else 0.28 | |
| elif agent_action.disposition == "fix" and ground_truth.disposition == "reject": | |
| score += 0.20 # partial: fix is better than blind accept | |
| elif agent_action.disposition == "defer": | |
| if ground_truth.disposition_ambiguity >= 0.5: | |
| # Ambiguous case β deferring is reasonable; reward more if documented | |
| score += 0.15 if agent_action.defer_reason else 0.10 | |
| else: | |
| # Unambiguous case β defer is avoidance; penalise | |
| score = max(score - 0.05, 0.0) | |
| elif agent_action.disposition == "accept" and ground_truth.disposition == "reject": | |
| score += 0.00 # worst case β no credit | |
| # ------------------------------------------------------------------ | |
| # 2. Fix instruction quality (0.20 max) | |
| # ------------------------------------------------------------------ | |
| if agent_action.disposition == "fix" and agent_action.fix_instructions: | |
| valid_steps = sum( | |
| 1 | |
| for step in agent_action.fix_instructions | |
| if step in ground_truth.valid_fix_steps | |
| ) | |
| fix_precision = valid_steps / len(agent_action.fix_instructions) | |
| if fix_precision >= 0.8: | |
| score += 0.20 | |
| elif fix_precision >= 0.5: | |
| score += 0.10 | |
| # else: 0.00 β no addition | |
| # ------------------------------------------------------------------ | |
| # 3. Dataset impact reasoning (0.20 max) | |
| # ------------------------------------------------------------------ | |
| kw_elements = ground_truth.expected_reasoning_elements | |
| agent_text = agent_action.dataset_impact_reasoning.lower() | |
| matched = sum(1 for kw in kw_elements if kw in agent_text) | |
| if matched >= len(kw_elements) * 0.8: | |
| score += 0.20 | |
| elif matched >= 1: | |
| score += 0.10 | |
| # else: 0.00 β no addition | |
| # ------------------------------------------------------------------ | |
| # 4. Override misuse penalty | |
| # Evaluate ONLY when override labels are actually annotated. | |
| # ------------------------------------------------------------------ | |
| valid_override_justifications = ground_truth.valid_override_justifications | |
| has_override_labels = ( | |
| isinstance(valid_override_justifications, list) | |
| and len(valid_override_justifications) > 0 | |
| ) | |
| if has_override_labels and agent_action.override_decision == "applied": | |
| if not agent_action.override_justification: | |
| score -= 0.10 | |
| elif agent_action.override_justification not in valid_override_justifications: | |
| score -= 0.05 | |
| # Valid justification present β no penalty | |
| # ------------------------------------------------------------------ | |
| # Clamp β score must never go below 0.0 | |
| # ------------------------------------------------------------------ | |
| return max(score, 0.0) | |