Spaces:
Sleeping
Sleeping
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())
|