102 lines
3.5 KiB
Python
102 lines
3.5 KiB
Python
"""Tests for DeepSeek interaction-event adjudication without network calls."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from adjudicate_easycom_interaction_events import (
|
|
OUTPUT_SCHEMA_VERSION,
|
|
PROMPT_VERSION,
|
|
_validate_decisions,
|
|
_validate_resume_rows,
|
|
build_user_prompt,
|
|
stratified_limit,
|
|
)
|
|
|
|
|
|
class AdjudicationTests(unittest.TestCase):
|
|
def test_prompt_contains_json_and_candidate_context(self) -> None:
|
|
prompt = build_user_prompt(
|
|
[{"uid": "u1", "event_type": "backchannel_candidate", "transcription": "Yeah."}],
|
|
0,
|
|
)
|
|
self.assertIn("JSON", prompt)
|
|
self.assertIn("u1", prompt)
|
|
self.assertIn("Yeah.", prompt)
|
|
|
|
def test_response_requires_exact_uid_set(self) -> None:
|
|
with self.assertRaisesRegex(ValueError, "mismatch"):
|
|
_validate_decisions({"items": []}, ["u1"])
|
|
|
|
def test_valid_response_is_returned_in_input_order(self) -> None:
|
|
payload = {
|
|
"items": [
|
|
{"uid": "u2", "label": "uncertain", "confidence": "low", "rationale": "Not enough evidence."},
|
|
{"uid": "u1", "label": "backchannel", "confidence": "high", "rationale": "Floor is retained."},
|
|
]
|
|
}
|
|
actual = _validate_decisions(payload, ["u1", "u2"])
|
|
self.assertEqual([row["uid"] for row in actual], ["u1", "u2"])
|
|
|
|
def test_invalid_label_is_rejected(self) -> None:
|
|
payload = {
|
|
"items": [
|
|
{"uid": "u1", "label": "guess", "confidence": "high", "rationale": "No."}
|
|
]
|
|
}
|
|
with self.assertRaisesRegex(ValueError, "Invalid label"):
|
|
_validate_decisions(payload, ["u1"])
|
|
|
|
def test_resume_rejects_mixed_model(self) -> None:
|
|
rows = [
|
|
{
|
|
"uid": "u1",
|
|
"schema_version": OUTPUT_SCHEMA_VERSION,
|
|
"model": "different-model",
|
|
"prompt_version": PROMPT_VERSION,
|
|
"passes": 2,
|
|
}
|
|
]
|
|
with self.assertRaisesRegex(ValueError, "different adjudication"):
|
|
_validate_resume_rows(rows, model="deepseek-v4-flash", passes=2)
|
|
|
|
def test_resume_accepts_matching_configuration(self) -> None:
|
|
rows = [
|
|
{
|
|
"uid": "u1",
|
|
"schema_version": OUTPUT_SCHEMA_VERSION,
|
|
"model": "deepseek-v4-flash",
|
|
"prompt_version": PROMPT_VERSION,
|
|
"passes": 2,
|
|
}
|
|
]
|
|
_validate_resume_rows(rows, model="deepseek-v4-flash", passes=2)
|
|
|
|
def test_pilot_limit_is_stratified_and_deterministic(self) -> None:
|
|
rows = [
|
|
{
|
|
"uid": f"{event_type}-{session}-{index}",
|
|
"event_type": event_type,
|
|
"session": session,
|
|
}
|
|
for event_type in ("backchannel_candidate", "interruption_candidate")
|
|
for session in ("Session_4", "Session_5")
|
|
for index in range(3)
|
|
]
|
|
first = stratified_limit(rows, 4, seed=2027)
|
|
second = stratified_limit(rows, 4, seed=2027)
|
|
self.assertEqual(first, second)
|
|
self.assertEqual(
|
|
{(row["event_type"], row["session"]) for row in first},
|
|
{
|
|
("backchannel_candidate", "Session_4"),
|
|
("backchannel_candidate", "Session_5"),
|
|
("interruption_candidate", "Session_4"),
|
|
("interruption_candidate", "Session_5"),
|
|
},
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|