from typing import Any
from backend.extract_schema import EXTRACT_FIELDS
def extract_expected_from_sample(task: str, sample: dict[str, Any]) -> dict[str, Any] | None:
if task == "classify" and sample.get("expected_category") is not None:
return {"category": sample["expected_category"]}
if task == "match" and sample.get("expected_is_match") is not None:
return {"is_match": sample["expected_is_match"]}
if task == "extract" and sample.get("expected_result") is not None:
return sample["expected_result"]
return None
def _normalize_text(value: Any) -> str:
return str(value).strip().lower().replace(" ", "")
def _list_overlap(expected: list[Any], actual: list[Any]) -> bool:
if not expected:
return True
if not actual:
return False
normalized_actual = [_normalize_text(item) for item in actual]
for item in expected:
target = _normalize_text(item)
if any(target in candidate or candidate in target for candidate in normalized_actual):
continue
return False
return True
def evaluate_correctness(
task: str,
expected: dict[str, Any] | None,
result: dict[str, Any] | None,
) -> bool | None:
if expected is None or result is None:
return None
if task == "classify":
return expected.get("category") == result.get("category")
if task == "match":
return expected.get("is_match") == result.get("is_match")
if task == "extract":
for key in EXTRACT_FIELDS:
expected_values = expected.get(key, [])
if not isinstance(expected_values, list) or not expected_values:
continue
actual_values = result.get(key, [])
if not isinstance(actual_values, list):
return False
if not _list_overlap(expected_values, actual_values):
return False
return True
return None
def format_match_label(is_correct: bool | None) -> str:
if is_correct is True:
return "正确"
if is_correct is False:
return "错误"
return "未比对"