Spaces:
Running on Zero
Running on Zero
Download src/solarwm/cli.py from hugging-apps/solarrenderer: direct link, hf CLI and curl.
- Browser
- Download file 12.5 kB
-
https://huggingface.co/spaces/hugging-apps/solarrenderer/resolve/main/src/solarwm/cli.py
- Command line
-
hf download hf://spaces/hugging-apps/solarrenderer/src/solarwm/cli.py
-
curl -L -o cli.py https://huggingface.co/spaces/hugging-apps/solarrenderer/resolve/main/src/solarwm/cli.py
12.5 kB
| """Command-line interface for training, inference, preencoding, and data inspection.""" | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import json | |
| import os | |
| import sys | |
| import tempfile | |
| from collections.abc import Sequence | |
| from pathlib import Path | |
| from typing import Any | |
| from solarwm import __version__ | |
| from solarwm.config import load_config | |
| from solarwm.config.routes import supported_routes, validate_route | |
| from solarwm.data.index import inventory, read_index | |
| from solarwm.data.sampling import ( | |
| CanonicalSampler, | |
| ReaderIdentity, | |
| SamplingConfig, | |
| plan_fingerprint, | |
| ) | |
| from solarwm.errors import SolarWMError | |
| from solarwm.runtime.create_only import write_file_create_only | |
| from solarwm.runtime.images import probe_python_runtime | |
| from solarwm.runtime.output_layout import ( | |
| camera_inference_output_layout, | |
| invocation_output_dir, | |
| ) | |
| from solarwm.runtime.provenance import build_launch_manifest, reject_inline_secrets | |
| def _common_config(parser: argparse.ArgumentParser) -> None: | |
| parser.add_argument("--config", required=True, type=Path) | |
| parser.add_argument( | |
| "--set", | |
| action="append", | |
| default=[], | |
| metavar="KEY=VALUE", | |
| help="override one dotted config value; may be repeated", | |
| ) | |
| def build_parser() -> argparse.ArgumentParser: | |
| parser = argparse.ArgumentParser(prog="solarwm") | |
| parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}") | |
| commands = parser.add_subparsers(dest="command", required=True) | |
| for action in ("train", "infer", "preencode"): | |
| child = commands.add_parser(action, help=f"run the unified {action} entrypoint") | |
| _common_config(child) | |
| config = commands.add_parser("config", help="resolve and inspect a run config") | |
| config_commands = config.add_subparsers(dest="config_command", required=True) | |
| resolve = config_commands.add_parser("resolve") | |
| _common_config(resolve) | |
| resolve.add_argument("--output", type=Path) | |
| config_commands.add_parser("routes") | |
| data = commands.add_parser("data", help="inspect canonical index semantics") | |
| data_commands = data.add_subparsers(dest="data_command", required=True) | |
| inspect = data_commands.add_parser("inspect") | |
| inspect.add_argument("index", type=Path) | |
| plan = data_commands.add_parser("plan") | |
| plan.add_argument("index", type=Path) | |
| plan.add_argument("--seed", type=int, required=True) | |
| plan.add_argument("--pixel-frames", type=int, required=True) | |
| plan.add_argument("--rank", type=int, default=0) | |
| plan.add_argument("--world-size", type=int, default=1) | |
| plan.add_argument("--worker-id", type=int, default=0) | |
| plan.add_argument("--num-workers", type=int, default=1) | |
| plan.add_argument("--epoch", type=int, default=0) | |
| plan.add_argument("--limit", type=int, default=16) | |
| plan.add_argument("--shuffle-buffer", type=int, default=4096) | |
| environment = commands.add_parser("environment", help="inspect the current runtime") | |
| environment_commands = environment.add_subparsers(dest="environment_command", required=True) | |
| environment_commands.add_parser("probe") | |
| return parser | |
| def _write_json(value: Any, output: Path | None = None) -> None: | |
| payload = json.dumps(value, indent=2, sort_keys=True, ensure_ascii=False) + "\n" | |
| if output is None: | |
| sys.stdout.write(payload) | |
| return | |
| output.parent.mkdir(parents=True, exist_ok=True) | |
| temporary: str | None = None | |
| try: | |
| with tempfile.NamedTemporaryFile( | |
| mode="w", | |
| encoding="utf-8", | |
| dir=output.parent, | |
| prefix=f".{output.name}.", | |
| suffix=".tmp", | |
| delete=False, | |
| ) as handle: | |
| temporary = handle.name | |
| handle.write(payload) | |
| handle.flush() | |
| os.fsync(handle.fileno()) | |
| os.replace(temporary, output) | |
| temporary = None | |
| finally: | |
| if temporary is not None: | |
| Path(temporary).unlink(missing_ok=True) | |
| def _run_backend(args: argparse.Namespace) -> int: | |
| resolved = load_config(args.config, args.set) | |
| reject_inline_secrets(resolved.values) | |
| configured_action = str(resolved.values["action"]) | |
| if configured_action != args.command: | |
| raise SolarWMError( | |
| f"command {args.command!r} does not match config action {configured_action!r}" | |
| ) | |
| route = validate_route(resolved.values) | |
| runtime = resolved.values.get("runtime", {}) | |
| from solarwm.backends import load_backend | |
| backend = load_backend(route.family) | |
| backend.validate_config(resolved.values) | |
| if not str(runtime.get("output_dir", "")).strip(): | |
| raise SolarWMError("runtime.output_dir is required") | |
| publication_layout = camera_inference_output_layout(resolved.values) | |
| output_dir = invocation_output_dir(resolved.values) | |
| launcher_rank = int(os.environ.get("RANK", "0")) | |
| if launcher_rank == 0: | |
| if publication_layout is not None: | |
| publication_layout.publish_root.mkdir(parents=True, exist_ok=True) | |
| output_dir.parent.mkdir(parents=True, exist_ok=True) | |
| try: | |
| output_dir.mkdir() | |
| except FileExistsError as exc: | |
| raise SolarWMError(f"camera inference run already exists: {output_dir}") from exc | |
| else: | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| # A terminal result describes only the current invocation. Remove | |
| # a result left by an earlier legacy invocation before work starts. | |
| (output_dir / "run-result.json").unlink(missing_ok=True) | |
| resolved.write_json(output_dir / "resolved-config.json") | |
| manifest = build_launch_manifest( | |
| config=resolved.values, | |
| source_config=resolved.path, | |
| source_digest=resolved.source_digest, | |
| resolved_digest=resolved.resolved_digest, | |
| route=route.key, | |
| repository=Path(__file__).resolve().parents[2], | |
| ) | |
| _write_json(manifest, output_dir / "launch-manifest.json") | |
| operation = getattr(backend, args.command) | |
| try: | |
| result = int(operation(resolved.values) or 0) | |
| except Exception as exc: | |
| if launcher_rank == 0: | |
| _write_json( | |
| { | |
| "schema": "solarwm.run-result.v1", | |
| "status": "failed", | |
| "error_type": type(exc).__name__, | |
| "message": str(exc), | |
| }, | |
| output_dir / "run-result.json", | |
| ) | |
| raise | |
| if launcher_rank == 0: | |
| _write_json( | |
| {"schema": "solarwm.run-result.v1", "status": "complete", "exit_code": result}, | |
| output_dir / "run-result.json", | |
| ) | |
| if publication_layout is not None and result == 0: | |
| publication_complete = output_dir / "publication" / "COMPLETE.json" | |
| if not publication_complete.is_file(): | |
| raise SolarWMError( | |
| "camera inference returned without a publication completion marker" | |
| ) | |
| publication_payload = publication_complete.read_bytes() | |
| run_result_payload = (output_dir / "run-result.json").read_bytes() | |
| complete_payload = ( | |
| json.dumps( | |
| { | |
| "schema": "solarwm.camera-inference-run-complete.v1", | |
| "layout": publication_layout.layout, | |
| "run_id": publication_layout.run_id, | |
| "resolved_config_digest": resolved.resolved_digest, | |
| "publication_complete_digest": hashlib.blake2s( | |
| publication_payload | |
| ).hexdigest(), | |
| "run_result_digest": hashlib.blake2s(run_result_payload).hexdigest(), | |
| }, | |
| allow_nan=False, | |
| sort_keys=True, | |
| separators=(",", ":"), | |
| ensure_ascii=False, | |
| ) | |
| + "\n" | |
| ).encode("utf-8") | |
| write_file_create_only( | |
| output_dir / "COMPLETE.json", | |
| complete_payload, | |
| error_type=SolarWMError, | |
| label="camera inference run completion marker", | |
| ) | |
| return result | |
| def _config_command(args: argparse.Namespace) -> int: | |
| if args.config_command == "routes": | |
| _write_json([route.key for route in supported_routes()]) | |
| return 0 | |
| resolved = load_config(args.config, args.set) | |
| reject_inline_secrets(resolved.values) | |
| route = validate_route(resolved.values) | |
| from solarwm.backends import load_backend | |
| load_backend(route.family).validate_config(resolved.values) | |
| payload = { | |
| "source": str(resolved.path), | |
| "source_digest": resolved.source_digest, | |
| "resolved_digest": resolved.resolved_digest, | |
| "route": route.key, | |
| "config": resolved.values, | |
| } | |
| _write_json(payload, args.output) | |
| return 0 | |
| def _data_command(args: argparse.Namespace) -> int: | |
| rows = read_index(args.index) | |
| report = inventory(args.index, rows) | |
| if args.data_command == "inspect": | |
| _write_json( | |
| { | |
| "index": str(args.index.resolve()), | |
| "rows": report.rows, | |
| "virtual_occurrences": report.virtual_occurrences, | |
| "ordered_sample_id_digest": report.ordered_sample_id_digest, | |
| "ordered_row_digest": report.ordered_row_digest, | |
| "decompressed_digest": report.decompressed_digest, | |
| } | |
| ) | |
| return 0 | |
| config = SamplingConfig( | |
| seed=args.seed, | |
| pixel_frames=args.pixel_frames, | |
| shuffle_buffer=args.shuffle_buffer, | |
| ) | |
| identity = ReaderIdentity( | |
| rank=args.rank, | |
| world_size=args.world_size, | |
| worker_id=args.worker_id, | |
| num_workers=args.num_workers, | |
| ) | |
| plans = list(CanonicalSampler(rows, config, identity).iter_epoch(args.epoch)) | |
| selected = plans[: max(0, args.limit)] | |
| _write_json( | |
| { | |
| "full_plan_fingerprint": plan_fingerprint(plans), | |
| "full_plan_count": len(plans), | |
| "shown": [ | |
| { | |
| "sample_id": plan.sample_id, | |
| "key": plan.key, | |
| "shard": plan.shard, | |
| "repeat_ordinal": plan.repeat_ordinal, | |
| "start_frame": plan.start_frame, | |
| "source_frame_indices": plan.source_frame_indices, | |
| } | |
| for plan in selected | |
| ], | |
| } | |
| ) | |
| return 0 | |
| def _environment_command(args: argparse.Namespace) -> int: | |
| if args.environment_command == "probe": | |
| _write_json(probe_python_runtime()) | |
| return 0 | |
| raise SolarWMError(f"unhandled environment command {args.environment_command!r}") | |
| def _run_backend_or_leave(args: argparse.Namespace) -> int: | |
| """Run a backend command; a rank of a distributed launch that fails exits outright. | |
| A rank that returns from a failure still joins its threads at interpreter shutdown, and one | |
| that never ends leaves it alive: the launcher never sees it fail, and every other | |
| rank waits out the collective timeout. Leaving at once hands the failure to the launcher. | |
| """ | |
| if int(os.environ.get("WORLD_SIZE", "1")) <= 1: | |
| return _run_backend(args) | |
| try: | |
| return _run_backend(args) | |
| except (SolarWMError, OSError, ValueError) as exc: | |
| print(f"solarwm: error: {exc}", file=sys.stderr) | |
| status = 2 | |
| except BaseException: | |
| import traceback | |
| traceback.print_exc() | |
| status = 1 | |
| sys.stdout.flush() | |
| sys.stderr.flush() | |
| os._exit(status) | |
| def main(argv: Sequence[str] | None = None) -> int: | |
| args = build_parser().parse_args(argv) | |
| try: | |
| if args.command in {"train", "infer", "preencode"}: | |
| return _run_backend_or_leave(args) | |
| if args.command == "config": | |
| return _config_command(args) | |
| if args.command == "data": | |
| return _data_command(args) | |
| if args.command == "environment": | |
| return _environment_command(args) | |
| raise SolarWMError(f"unhandled command {args.command!r}") | |
| except (SolarWMError, OSError, ValueError) as exc: | |
| print(f"solarwm: error: {exc}", file=sys.stderr) | |
| return 2 | |
| if __name__ == "__main__": # pragma: no cover | |
| raise SystemExit(main()) | |