Download runtime/rl/journal.py from BAAI/PingPongRealWorldRL: direct link, hf CLI and curl.
- Browser
- Download file 4.44 kB
-
https://huggingface.co/BAAI/PingPongRealWorldRL/resolve/main/runtime/rl/journal.py
- Command line
-
hf download hf://BAAI/PingPongRealWorldRL/runtime/rl/journal.py
-
curl -L -o journal.py https://huggingface.co/BAAI/PingPongRealWorldRL/resolve/main/runtime/rl/journal.py
4.44 kB
| """Reserved asynchronous summary logging; disk work stays off the control thread.""" | |
| from __future__ import annotations | |
| from collections import Counter | |
| import csv | |
| import json | |
| from pathlib import Path | |
| import queue | |
| import threading | |
| import numpy as np | |
| from .events import ADJUDICATION_VERSION | |
| from .metrics import BallMetrics, REWARD_FIELDS, format_ball | |
| def json_default(value): | |
| if isinstance(value, np.ndarray): | |
| return value.tolist() | |
| if isinstance(value, np.generic): | |
| return value.item() | |
| raise TypeError(type(value).__name__) | |
| class AsyncJournal: | |
| def __init__(self, root, capacity): | |
| self.root = Path(root) | |
| self.queue = queue.Queue() | |
| self.slots = threading.BoundedSemaphore(capacity) | |
| self.error = None | |
| self.closed = False | |
| self.dropped_balls = Counter() | |
| self.dropped_telemetry = 0 | |
| self.submitted_balls = self.written_balls = 0 | |
| self.metrics = BallMetrics() | |
| self.thread = threading.Thread(target=self._run, name="h2-rl-journal", daemon=True) | |
| self.thread.start() | |
| def reserve(self): | |
| return not self.closed and self.error is None and self.slots.acquire(blocking=False) | |
| def missed_ball(self, phase): | |
| self.dropped_balls[phase] += 1 | |
| if sum(self.dropped_balls.values()) == 1: | |
| print("[RL ERROR] ball summary unavailable; unlogged attempts are counted in journal_status.json") | |
| def submit_reserved(self, record): | |
| if record.get("kind", "ball") == "ball": | |
| self.submitted_balls += 1 | |
| self.queue.put_nowait(record) | |
| def telemetry(self, record): | |
| if self.reserve(): | |
| self.submit_reserved(dict(kind="telemetry", summary=record)) | |
| else: | |
| self.dropped_telemetry += 1 | |
| def snapshot(self): | |
| return dict(unlogged_attempts=dict(self.dropped_balls), | |
| submitted_balls=self.submitted_balls, written_balls=self.written_balls, | |
| unwritten_balls=self.submitted_balls-self.written_balls, | |
| dropped_telemetry=self.dropped_telemetry, error=self.error) | |
| def _run(self): | |
| try: | |
| with (self.root / "balls.jsonl").open("a", encoding="utf-8") as balls, \ | |
| (self.root / "control.jsonl").open("a", encoding="utf-8") as control, \ | |
| (self.root / "metrics.csv").open("w", newline="", encoding="utf-8") as metrics: | |
| template = dict(kind="", phase="", attempt="", **dict.fromkeys(REWARD_FIELDS), | |
| **self.metrics.phases["warmup"].snapshot()) | |
| writer = csv.DictWriter(metrics, fieldnames=list(template)) | |
| writer.writeheader() | |
| while True: | |
| item = self.queue.get() | |
| if item is None: | |
| for phase, stats in self.metrics.phases.items(): | |
| writer.writerow(dict(kind="final", phase=phase, attempt="", | |
| **stats.snapshot(self.dropped_balls[phase]))) | |
| return | |
| try: | |
| summary = dict(item["summary"], adjudication_version=ADJUDICATION_VERSION) | |
| is_ball = item.get("kind", "ball") == "ball" | |
| stream = balls if is_ball else control | |
| stream.write(json.dumps(summary, default=json_default, allow_nan=False) + "\n") | |
| stream.flush() | |
| if is_ball: | |
| self.written_balls += 1 | |
| row = self.metrics.add(summary, self.dropped_balls[summary["phase"]]) | |
| writer.writerow(row) | |
| metrics.flush() | |
| print(format_ball(summary, row), flush=True) | |
| finally: | |
| self.slots.release() | |
| except Exception as error: | |
| self.error = str(error) | |
| print(f"[RL ERROR] journal failed: {error}", flush=True) | |
| def close(self): | |
| if self.closed: | |
| return | |
| self.closed = True | |
| self.queue.put_nowait(None) | |
| self.thread.join() | |
| (self.root / "journal_status.json").write_text( | |
| json.dumps(self.snapshot(), indent=2), encoding="utf-8") | |
| if self.error: | |
| raise RuntimeError(f"RL journal failed: {self.error}") | |