Spaces:
Sleeping
Sleeping
Download scripts/pull_feedback.py from defenestrate/learning-world-goliath: direct link, hf CLI and curl.
- Browser
- Download file 3.59 kB
-
https://huggingface.co/spaces/defenestrate/learning-world-goliath/resolve/main/scripts/pull_feedback.py
- Command line
-
hf download hf://spaces/defenestrate/learning-world-goliath/scripts/pull_feedback.py
-
curl -L -o pull_feedback.py https://huggingface.co/spaces/defenestrate/learning-world-goliath/resolve/main/scripts/pull_feedback.py
3.59 kB
| """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()) | |