| """Label normalization shared by parsing + scoring.""" | |
| from __future__ import annotations | |
| import json | |
| import re | |
| _ARTICLES = {"a", "an", "the"} | |
| def normalize_label(text: str) -> str: | |
| """Lowercase, strip punctuation/articles, collapse whitespace.""" | |
| text = text.strip().lower() | |
| text = re.sub(r"[^a-z0-9\s\-]", " ", text) | |
| tokens = [t for t in text.split() if t and t not in _ARTICLES] | |
| return " ".join(tokens) | |
| def parse_label_json(raw: str) -> str | None: | |
| """Best-effort extraction of {"label": ...} from a model response.""" | |
| raw = raw.strip() | |
| # Direct JSON. | |
| try: | |
| obj = json.loads(raw) | |
| if isinstance(obj, dict) and "label" in obj: | |
| return normalize_label(str(obj["label"])) | |
| except json.JSONDecodeError: | |
| pass | |
| # Embedded JSON object. | |
| m = re.search(r"\{.*?\"label\".*?\}", raw, re.DOTALL) | |
| if m: | |
| try: | |
| obj = json.loads(m.group(0)) | |
| if "label" in obj: | |
| return normalize_label(str(obj["label"])) | |
| except json.JSONDecodeError: | |
| pass | |
| return None | |