File size: 3,586 Bytes
dcd4298
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
99
100
101
102
103
104
105
106
107
108
109
"""Pull playtest feedback down from the private HF Dataset and summarise it.



    python scripts/pull_feedback.py                 # summary to stdout

    python scripts/pull_feedback.py --out fb.jsonl  # also write a merged JSONL



Requires LWC_FEEDBACK_DATASET (e.g. "defenestrate/lwc-feedback") and HF_TOKEN.



Each feedback submission is stored as its own file under records/YYYY/MM/DD/

because the Space's local disk is ephemeral — see world_compiler/ui/feedback.py.

This script globs them back together in timestamp order.

"""

from __future__ import annotations

import argparse
import json
import os
import sys
from pathlib import Path


def load_records(local_dir: Path) -> list[dict]:
    records = []
    for path in sorted((local_dir / "records").rglob("*.json")):
        try:
            records.append(json.loads(path.read_text(encoding="utf-8")))
        except (OSError, json.JSONDecodeError) as exc:
            print(f"skipping unreadable {path.name}: {exc}", file=sys.stderr)
    records.sort(key=lambda r: r.get("timestamp", ""))
    return records


def summarise(records: list[dict]) -> None:
    if not records:
        print("No feedback yet.")
        return

    print(f"{len(records)} feedback records\n")

    by_version: dict[str, int] = {}
    for r in records:
        version = f"{r.get('scenario_id', '?')} v{r.get('scenario_version', '?')}"
        by_version[version] = by_version.get(version, 0) + 1

    print("By scenario version:")
    for version, count in sorted(by_version.items()):
        print(f"  {version}: {count}")
    print()

    for r in records:
        print("=" * 78)
        print(
            f"{r.get('timestamp', '?')}  {r.get('username', '?')}  "
            f"[{r.get('status', '?')}]  talking to: {r.get('character') or '(nobody)'}"
        )
        for student_text, actor_text in r.get("last_exchange") or []:
            print(f"  they asked: {student_text[:160]}")
            print(f"  reply began: {actor_text[:160]}")
        print(f"COMMENT: {str(r.get('comment', '')).strip()[:600]}")
        print()


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--out", type=Path, help="write merged JSONL here")
    parser.add_argument(
        "--local-dir",
        type=Path,
        default=Path("feedback_pull"),
        help="where to download the dataset snapshot",
    )
    args = parser.parse_args(argv)

    repo = os.getenv("LWC_FEEDBACK_DATASET")
    token = os.getenv("HF_TOKEN")
    if not repo or not token:
        print(
            "Set LWC_FEEDBACK_DATASET and HF_TOKEN first.\n"
            "  LWC_FEEDBACK_DATASET  the dataset repo id, e.g. defenestrate/lwc-feedback\n"
            "  HF_TOKEN              a token with read access to it",
            file=sys.stderr,
        )
        return 1

    from huggingface_hub import snapshot_download

    snapshot_download(
        repo_id=repo,
        repo_type="dataset",
        local_dir=str(args.local_dir),
        token=token,
    )

    records = load_records(args.local_dir)
    summarise(records)

    if args.out:
        args.out.parent.mkdir(parents=True, exist_ok=True)
        with args.out.open("w", encoding="utf-8") as fh:
            for r in records:
                fh.write(json.dumps(r, ensure_ascii=False) + "\n")
        print(f"wrote {len(records)} records -> {args.out}")

    return 0


if __name__ == "__main__":
    sys.exit(main())