--- title: MILO Benchmark Companion emoji: 🤖 colorFrom: blue colorTo: purple sdk: static pinned: false license: mit --- # MILO Benchmark Companion A read-only companion demo to [`naishashetty/milo_benchmark`](https://huggingface.co/datasets/naishashetty/milo_benchmark) on the Hugging Face Hub, and to the [MILO vision-language-robotics project](https://github.com/NaishaShetty/MILO) (origin repository). It shows a **leaderboard** and an **episode replay browser** built entirely from a real benchmark results JSON — four planners (`rule_based`, `behavior_tree`, `htn`, `react` on a local `qwen2.5:7b` model via Ollama) scored against a fixed 25-task, 5-scene, 3-tier AI2-THOR benchmark. ## This is not a live demo, and that's deliberate AI2-THOR requires a GPU-backed Unity subprocess to actually simulate a scene. **HF Spaces' free tier has no GPU and cannot run Unity**, so this Space cannot execute a real episode interactively, full stop. Rather than fake it (e.g. replaying a canned animation and implying it's live), this Space is explicit about being a **static replay** of one specific, timestamped, already-completed, reproducible benchmark run. If you want to run the benchmark for real, clone the origin repository and run `backend/planning_evaluation/run_benchmark.py` yourself against a real AI2-THOR installation (needs a GPU). ## What's real vs. reconstructed here This project's own writing convention (see `experiments/reports/phase_e_milo_benchmark_report.md` in the origin repo) is to say plainly what's measured vs. illustrative. Applied here: - **Leaderboard numbers**: real. Read directly from the source results JSON's `summary_by_planner` block (never re-derived from `episodes`, except for a couple of cost/latency columns not present in `summary_by_planner` at all, which are averaged from `episodes` instead — see `data.py`). - **Episode replay's logged fields** (planner, scene, instruction, goal/object/target, tier, plan_success/execution_success/goal_success, wall_clock_ms, failure_cause, llm_retry_attempts): real, read directly from that episode's row in the source JSON. - **Episode replay's "reconstructed plan trace"**: **not** real logged data. The source JSON only has aggregate per-episode counts (`action_count`, `plan_step_count`) — there is no literal per-step action log to replay. The step lists shown are built from each task's `goal`/`object`/`target` plus this project's documented, deterministic planner behavior (`tier3_store` = locate → navigate → pick_up → navigate → open if openable → place → close if opened, per `_deposit()`'s documented behavior in the dataset README and benchmark report). Every trace is labeled **"reconstructed plan trace for illustration"** in the UI. We chose to build these (rather than the simpler, arguably more conservative option of only showing logged fields) because a bare goal/object/target/outcome table alone doesn't give a reader unfamiliar with the codebase any sense of what a planner's "shape" of behavior actually looks like — but we did not want to under-label them as real trace data, since they aren't. - **Screenshots**: real UI screenshots from the live MILO product (`docs/screenshots/demo/` in the origin repo — 3 generic images: instruction typed, task in progress, task complete), **not** captured per-episode. There is no screenshot for each of the 25 dataset tasks. Where shown alongside an episode, the caption says explicitly that it's an illustrative example of the UI, not a capture of that literal episode's run. ## Why static HTML, not Gradio This Space started as a Gradio `Blocks` app (a `Dataframe` for the leaderboard plus a dropdown-driven detail view) — a small, well-trodden pattern for exactly this "table + browsable detail" shape. It was rebuilt as static HTML/CSS/JS after discovering that **Gradio and Docker Spaces require an HF Pro subscription for CPU hosting on this account**; static Spaces are free. Nothing about the page's actual content or logic needed the change: everything here was already precomputed from a results JSON with no live Python execution per request, so a static page loses nothing over the Gradio version for this use case — it swaps a server-rendered `Dataframe`/`Dropdown` for the equivalent plain HTML table and `