File size: 3,881 Bytes
de8702b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""Build dataset/v0.2/public.jsonl from the case modules in scripts/v02_cases/.

Each module defines CASES, a list of rows:
  (id, domain, task, category, phenomena, difficulty, group, position, state, expected)
Ambiguous rows use a list of valid answers instead of expected; they are unscored.
Edit cases in the modules, not in the JSONL.

Labels from filled sheets in dataset/v0.2/annotations/*.csv (see scripts/annotation.py)
are merged into `annotations`; `?` is stored as null. Model sheets under
annotations/llm/ are not merged and never mark a case as reviewed.

--module builds a single module to --out, so one domain can be validated and gated alone:
  python scripts/build_v02.py --module travel --out /tmp/travel.jsonl
  python scripts/validate_dataset.py --version 0.2 --dataset /tmp/travel.jsonl
  python scripts/baseline_report.py --version 0.2 --dataset /tmp/travel.jsonl
"""
import argparse
import importlib
import json
import sys
from pathlib import Path

HERE = Path(__file__).resolve().parent
ROOT = HERE.parent
sys.path.insert(0, str(HERE))
sys.path.insert(0, str(ROOT))

from annotation import UNSURE, read_sheet  # noqa: E402
from benchmark.dataset import display_path, load_tasks, version_paths  # noqa: E402

MODULES = ["pilot", "subscription", "telecom", "shipping", "health", "public_services", "travel"]
PUBLIC, TASKS = version_paths("0.2", "public")
SHEETS = PUBLIC.parent / "annotations"


def load_rows(modules):
    rows = []
    for name in modules:
        if not (HERE / "v02_cases" / f"{name}.py").exists():
            continue
        for cid, domain, task, category, phenomena, difficulty, group, position, state, label in \
                importlib.import_module(f"v02_cases.{name}").CASES:
            scored = not isinstance(label, list)
            rows.append({
                "id": cid,
                "version": "0.2",
                "split": "public",
                "domain": domain,
                "task_id": task,
                "category": category,
                "phenomena": phenomena,
                "difficulty": difficulty,
                "group_id": group,
                "answer_position": position,
                "state": state,
                "expected": label if scored else None,
                "valid_answers": [label] if scored else label,
                "scored": scored,
                "review_status": "draft",
                "annotations": {},
            })
    return rows


def merge_annotations(rows):
    tasks = load_tasks(TASKS)
    for sheet in sorted(SHEETS.glob("*.csv")):
        labels, errors = read_sheet(sheet, rows, tasks, ignore_unknown=True)
        if errors:
            sys.exit(f"{sheet.name}: " + "; ".join(errors))
        for row in rows:
            label = labels.get(row["id"], (None,))[0]
            if label:
                row["annotations"][sheet.stem] = None if label == UNSURE else label
                row["review_status"] = "reviewed"


def main():
    parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument("--module", choices=MODULES, help="build only this case module")
    parser.add_argument("--out", type=Path, default=PUBLIC)
    args = parser.parse_args()
    if args.module and args.out == PUBLIC:
        parser.error("--module needs --out, the public file must contain every module")

    rows = load_rows([args.module] if args.module else MODULES)
    merge_annotations(rows)
    args.out.parent.mkdir(parents=True, exist_ok=True)
    with args.out.open("w", encoding="utf-8") as f:
        for row in rows:
            f.write(json.dumps(row, ensure_ascii=False) + "\n")
    reviewed = sum(r["review_status"] == "reviewed" for r in rows)
    print(f"Wrote {len(rows)} cases ({reviewed} reviewed) to {display_path(args.out)}")


if __name__ == "__main__":
    main()