Narrow WorldForge to the latent planning-and-scoring backbone (#337) #177
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Robotics Showcase | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: robotics-showcase-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| UV_LOCKED: "true" | |
| UV_VERSION: "0.9.18" | |
| PYTHON_VERSION: "3.13" | |
| LEROBOT_VERSION: "0.5.1" | |
| LEWORLDMODEL_REVISION: "22b330c28c27ead4bfd1888615af1340e3fe9052" | |
| LEROBOT_POLICY_PATH: "lerobot/diffusion_pusht" | |
| LEROBOT_POLICY_TYPE: "diffusion" | |
| LEROBOT_DEVICE: "cpu" | |
| LEWORLDMODEL_POLICY: "pusht/lewm" | |
| LEWORLDMODEL_DEVICE: "cpu" | |
| PYGAME_HIDE_SUPPORT_PROMPT: "1" | |
| jobs: | |
| real-inference: | |
| name: Real LeRobot + LeWorldModel inference | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| env: | |
| HF_HOME: ${{ github.workspace }}/.cache/huggingface | |
| LEROBOT_CACHE_DIR: ${{ github.workspace }}/.cache/huggingface/lerobot | |
| STABLEWM_HOME: ${{ github.workspace }}/.cache/stable-wm | |
| LEWORLDMODEL_ASSET_CACHE_DIR: ${{ github.workspace }}/.cache/worldforge/leworldmodel | |
| WORLDFORGE_ROBOTICS_RUN_DIR: ${{ github.workspace }}/.worldforge/robotics-showcase-ci | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| version: ${{ env.UV_VERSION }} | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Verify lockfile | |
| run: uv lock --check | |
| - name: Restore model and checkpoint caches | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| .cache/huggingface | |
| .cache/stable-wm | |
| .cache/worldforge/leworldmodel | |
| key: robotics-showcase-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-uv${{ env.UV_VERSION }}-lerobot-${{ env.LEROBOT_VERSION }}-lewm-${{ env.LEWORLDMODEL_REVISION }}-${{ hashFiles('scripts/robotics-showcase', 'scripts/lewm-lerobot-real', 'src/worldforge/smoke/leworldmodel_checkpoint.py', 'src/worldforge/smoke/pusht_showcase_inputs.py') }} | |
| restore-keys: | | |
| robotics-showcase-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-uv${{ env.UV_VERSION }}-lerobot-${{ env.LEROBOT_VERSION }}-lewm-${{ env.LEWORLDMODEL_REVISION }}- | |
| - name: Run non-interactive real robotics showcase | |
| run: | | |
| mkdir -p "$WORLDFORGE_ROBOTICS_RUN_DIR" | |
| scripts/robotics-showcase \ | |
| --policy-path "$LEROBOT_POLICY_PATH" \ | |
| --policy-type "$LEROBOT_POLICY_TYPE" \ | |
| --stablewm-home "$STABLEWM_HOME" \ | |
| --lewm-cache-dir "$STABLEWM_HOME" \ | |
| --lewm-asset-cache-dir "$LEWORLDMODEL_ASSET_CACHE_DIR" \ | |
| --lewm-revision "$LEWORLDMODEL_REVISION" \ | |
| --lerobot-cache-dir "$LEROBOT_CACHE_DIR" \ | |
| --device cpu \ | |
| --json-only \ | |
| --no-tui \ | |
| --no-rerun \ | |
| --json-output "$WORLDFORGE_ROBOTICS_RUN_DIR/real-run.json" \ | |
| --run-manifest "$WORLDFORGE_ROBOTICS_RUN_DIR/run_manifest.json" \ | |
| > "$WORLDFORGE_ROBOTICS_RUN_DIR/stdout.json" | |
| - name: Validate robotics showcase evidence | |
| run: | | |
| python - <<'PY' | |
| import json | |
| import os | |
| from pathlib import Path | |
| run_dir = Path(os.environ["WORLDFORGE_ROBOTICS_RUN_DIR"]) | |
| summary_path = run_dir / "real-run.json" | |
| manifest_path = run_dir / "run_manifest.json" | |
| stdout_path = run_dir / "stdout.json" | |
| summary = json.loads(summary_path.read_text(encoding="utf-8")) | |
| stdout_payload = json.loads(stdout_path.read_text(encoding="utf-8")) | |
| manifest = json.loads(manifest_path.read_text(encoding="utf-8")) | |
| failures = [] | |
| def require(condition, message): | |
| if not condition: | |
| failures.append(message) | |
| require(summary == stdout_payload, "stdout JSON and summary artifact differ") | |
| require( | |
| summary.get("mode") == "real_lerobot_policy_plus_real_leworldmodel_score", | |
| "unexpected run mode", | |
| ) | |
| health = summary.get("health", {}) | |
| require(health.get("lerobot", {}).get("healthy") is True, "LeRobot health failed") | |
| require( | |
| health.get("leworldmodel", {}).get("healthy") is True, | |
| "LeWorldModel health failed", | |
| ) | |
| inputs = summary.get("inputs", {}) | |
| require(inputs.get("score_action_candidates_shape") == [1, 3, 4, 10], "unexpected candidate tensor shape") | |
| score_result = summary.get("score_result", {}) | |
| scores = score_result.get("scores") | |
| require(isinstance(scores, list) and len(scores) == 3, "expected three LeWorldModel scores") | |
| require(isinstance(score_result.get("best_index"), int), "missing best_index") | |
| events = { | |
| (event.get("provider"), event.get("operation"), event.get("phase")) | |
| for event in summary.get("provider_events", []) | |
| } | |
| require(("lerobot", "policy", "success") in events, "missing successful LeRobot event") | |
| require( | |
| ("leworldmodel", "score", "success") in events, | |
| "missing successful LeWorldModel event", | |
| ) | |
| require("rerun" not in summary, "non-interactive CI run should not write Rerun output") | |
| require(manifest.get("status") == "passed", "run manifest did not pass") | |
| require(manifest.get("capability") == "policy+score", "unexpected manifest capability") | |
| if failures: | |
| raise SystemExit("\n".join(failures)) | |
| summary_file = Path(os.environ["GITHUB_STEP_SUMMARY"]) | |
| with summary_file.open("a", encoding="utf-8") as handle: | |
| handle.write("## Robotics Showcase Evidence\n\n") | |
| handle.write(f"- LeWorldModel revision: `{os.environ['LEWORLDMODEL_REVISION']}`\n") | |
| handle.write(f"- Policy: `{inputs.get('policy_path')}`\n") | |
| handle.write(f"- Scores: `{scores}`\n") | |
| handle.write(f"- Best index: `{score_result.get('best_index')}`\n") | |
| handle.write(f"- Summary: `{summary_path.relative_to(Path.cwd())}`\n") | |
| handle.write(f"- Manifest: `{manifest_path.relative_to(Path.cwd())}`\n") | |
| PY | |
| - name: Upload robotics showcase evidence | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: robotics-showcase-real-inference-${{ github.run_id }} | |
| path: | | |
| .worldforge/robotics-showcase-ci/*.json | |
| if-no-files-found: warn | |
| retention-days: 14 |