Revise wearer entry and yield annotation protocol
This commit is contained in:
@@ -59,8 +59,9 @@ class FloorEventReviewTests(unittest.TestCase):
|
||||
"dense_start_seconds": 1.2,
|
||||
"event_time": 1.2,
|
||||
"candidate_source": "WEARER_ONSET",
|
||||
"task": "wearer_entry",
|
||||
"ai_verdict": "POSITIVE",
|
||||
"ai_event_type": "EOT_RESPONSE",
|
||||
"ai_event_type": "WEARER_ENTRY",
|
||||
"ai_subtype": None,
|
||||
"speaker_timeline": [
|
||||
{
|
||||
@@ -129,7 +130,7 @@ class FloorEventReviewTests(unittest.TestCase):
|
||||
resumed = ReviewStore(output, candidates)
|
||||
self.assertEqual(
|
||||
resumed.reviews[candidates[0].candidate_id]["review"]["human_event_type"],
|
||||
"EOT_RESPONSE",
|
||||
"WEARER_ENTRY",
|
||||
)
|
||||
self.assertFalse(resumed.reviews[candidates[0].candidate_id]["review"]["relabeled"])
|
||||
self.assertEqual(resumed.reviews[candidates[0].candidate_id]["review"]["reviewer"], "")
|
||||
@@ -162,7 +163,7 @@ class FloorEventReviewTests(unittest.TestCase):
|
||||
{
|
||||
"uid": "Session_4/wearer_onset/00000338",
|
||||
"candidate_source": "WEARER_ONSET",
|
||||
"task": "eot_response",
|
||||
"task": "wearer_entry",
|
||||
},
|
||||
]
|
||||
path.write_text(
|
||||
@@ -183,18 +184,83 @@ class FloorEventReviewTests(unittest.TestCase):
|
||||
"human_action": "relabel",
|
||||
"human_verdict": "HARD_NEGATIVE",
|
||||
"human_event_type": None,
|
||||
"human_subtype": "EOT_WEARER_BACKCHANNEL",
|
||||
"human_subtype": "ENTRY_WEARER_BACKCHANNEL",
|
||||
"exclude_reason": None,
|
||||
"boundary_correction_seconds": None,
|
||||
"confidence": "medium",
|
||||
"reviewer": "r2",
|
||||
"notes": "brief acknowledgement",
|
||||
})
|
||||
self.assertEqual(record["ai_event_type"], "EOT_RESPONSE")
|
||||
self.assertEqual(record["review"]["human_subtype"], "EOT_WEARER_BACKCHANNEL")
|
||||
self.assertEqual(record["ai_event_type"], "WEARER_ENTRY")
|
||||
self.assertEqual(record["review"]["human_subtype"], "ENTRY_WEARER_BACKCHANNEL")
|
||||
self.assertTrue(record["review"]["relabeled"])
|
||||
|
||||
def test_eot_review_selects_only_a_supplied_opportunity_anchor(self) -> None:
|
||||
def test_removed_verdicts_cannot_be_accepted_or_reintroduced(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
_, events = self._fixture(root)
|
||||
candidates = load_candidates([events])
|
||||
candidate = candidates[0]
|
||||
store = ReviewStore(root / "reviews.jsonl", candidates)
|
||||
base = {
|
||||
"human_event_type": None, "human_subtype": None,
|
||||
"selected_opportunity_uid": None, "exclude_reason": None,
|
||||
"boundary_correction_seconds": None, "confidence": "medium",
|
||||
"notes": "legacy fallback",
|
||||
}
|
||||
for verdict in ("UNSURE", "NOT_APPLICABLE"):
|
||||
with self.subTest(action="relabel", verdict=verdict), self.assertRaisesRegex(
|
||||
ValueError, "Invalid human_verdict"
|
||||
):
|
||||
store.save(candidate.candidate_id, {
|
||||
**base, "human_action": "relabel", "human_verdict": verdict,
|
||||
})
|
||||
|
||||
candidate.payload["ai_verdict"] = verdict
|
||||
with self.subTest(action="accept", verdict=verdict), self.assertRaisesRegex(
|
||||
ValueError, "Accept requires an AI pre-label"
|
||||
):
|
||||
store.save(candidate.candidate_id, {
|
||||
**base, "human_action": "accept", "human_verdict": None,
|
||||
})
|
||||
|
||||
candidate.payload["ai_verdict"] = "POSITIVE"
|
||||
|
||||
def test_relabel_subtype_must_match_candidate_family(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
_, events = self._fixture(root)
|
||||
candidates = load_candidates([events])
|
||||
store = ReviewStore(root / "reviews.jsonl", candidates)
|
||||
with self.assertRaisesRegex(ValueError, "ENTRY candidate requires ENTRY_"):
|
||||
store.save(candidates[0].candidate_id, {
|
||||
"human_action": "relabel", "human_verdict": "HARD_NEGATIVE",
|
||||
"human_event_type": None, "human_subtype": "INT_OTHER_BACKCHANNEL",
|
||||
"selected_opportunity_uid": None, "exclude_reason": None,
|
||||
"boundary_correction_seconds": None, "confidence": "medium",
|
||||
"notes": "wrong family",
|
||||
})
|
||||
|
||||
def test_normal_completion_can_be_excluded_as_out_of_scope(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
_, events = self._fixture(root)
|
||||
candidates = load_candidates([events])
|
||||
store = ReviewStore(root / "reviews.jsonl", candidates)
|
||||
record = store.save(candidates[0].candidate_id, {
|
||||
"human_action": "exclude", "human_verdict": None,
|
||||
"human_event_type": None, "human_subtype": None,
|
||||
"selected_opportunity_uid": None,
|
||||
"exclude_reason": "OUT_OF_SCOPE_NORMAL_COMPLETION",
|
||||
"boundary_correction_seconds": None, "confidence": "high",
|
||||
"notes": "wearer completed; laughter did not take over",
|
||||
})
|
||||
self.assertEqual(record["review"]["human_verdict"], "EXCLUDE")
|
||||
self.assertEqual(
|
||||
record["review"]["exclude_reason"], "OUT_OF_SCOPE_NORMAL_COMPLETION"
|
||||
)
|
||||
|
||||
def test_entry_review_may_select_only_a_supplied_opportunity_anchor(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
_, events = self._fixture(root)
|
||||
@@ -208,7 +274,7 @@ class FloorEventReviewTests(unittest.TestCase):
|
||||
store = ReviewStore(root / "reviews.jsonl", candidates)
|
||||
base = {
|
||||
"human_action": "relabel", "human_verdict": "POSITIVE",
|
||||
"human_event_type": "EOT_RESPONSE", "human_subtype": None,
|
||||
"human_event_type": "WEARER_ENTRY", "human_subtype": None,
|
||||
"exclude_reason": None, "boundary_correction_seconds": None,
|
||||
"confidence": "high", "notes": "clear response",
|
||||
}
|
||||
@@ -219,11 +285,15 @@ class FloorEventReviewTests(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
record["review"]["valid_prediction_interval_seconds"], [1.0, 1.2]
|
||||
)
|
||||
with self.assertRaisesRegex(ValueError, "requires one supplied"):
|
||||
with self.assertRaisesRegex(ValueError, "only a supplied"):
|
||||
store.save(
|
||||
candidate.candidate_id,
|
||||
{**base, "selected_opportunity_uid": "invented"},
|
||||
)
|
||||
optional = store.save(
|
||||
candidate.candidate_id, {**base, "selected_opportunity_uid": None}
|
||||
)
|
||||
self.assertIsNone(optional["review"]["selected_opportunity_uid"])
|
||||
|
||||
def test_byte_ranges(self) -> None:
|
||||
self.assertEqual(parse_byte_range("bytes=2-5", 10), (2, 5))
|
||||
|
||||
Reference in New Issue
Block a user