from __future__ import annotations import json from pathlib import Path import gradio as gr ROOT = Path(__file__).parent MANIFEST_PATH = ROOT / "data" / "manifest.json" CONDITION_LABELS = { "dataset": "Dataset trajectory", "draw": "Drawn trajectory", "specialist": "No trajectory input", } def load_manifest() -> dict: with MANIFEST_PATH.open(encoding="utf-8") as f: return json.load(f) MANIFEST = load_manifest() RUNS = MANIFEST["runs"] def score_label(score: float | None) -> str: if score is None: return "n/a" return f"{score * 100:.1f}%" def task_options() -> list[str]: return ["All"] + sorted({run["task"] for run in RUNS}) def model_options() -> list[str]: return ["All"] + sorted({run["model"] for run in RUNS}) def condition_options() -> list[str]: return ["All"] + sorted({run["condition"] for run in RUNS}) def matching_runs(task: str, model: str, condition: str) -> list[dict]: return [ run for run in RUNS if (task == "All" or run["task"] == task) and (model == "All" or run["model"] == model) and (condition == "All" or run["condition"] == condition) ] def run_label(run: dict) -> str: condition = CONDITION_LABELS.get(run["condition"], run["condition"]) return f"{run['task']} | {run['model']} | {condition} | {score_label(run.get('mean_score'))}" def summary_rows() -> list[list[str]]: rows = [] for run in RUNS: rows.append( [ run["task"], run["model"], CONDITION_LABELS.get(run["condition"], run["condition"]), score_label(run.get("mean_score")), str(run.get("num_episodes", "")), run.get("hf_eval_dataset_id") or "", ] ) return rows def update_run_choices(task: str, model: str, condition: str): runs = matching_runs(task, model, condition) choices = [run_label(run) for run in runs] value = choices[0] if choices else None max_episode = runs[0]["num_episodes"] if runs else 1 return ( gr.update(choices=choices, value=value), gr.update(minimum=1, maximum=max_episode, value=1), ) def selected_run(label: str | None) -> dict | None: if not label: return None for run in RUNS: if run_label(run) == label: return run return None def render_episode(run_choice: str | None, episode_number: int): run = selected_run(run_choice) if run is None: return None, None, "No run selected.", "No trajectory input." episode_number = int(episode_number) episodes = run["episodes"] episode = next((ep for ep in episodes if ep["episode_number"] == episode_number), episodes[0]) video = episode.get("video") overlay = episode.get("overlay") if overlay: overlay = str(ROOT / overlay) if run["condition"] == "specialist": trajectory_text = "Specialist baseline: no trajectory sketch or dataset trajectory was provided." elif episode.get("trajectory_source_mode") == "dataset": trajectory_text = f"Dataset trajectory from source episode {episode.get('trajectory_source_episode')}." elif episode.get("trajectory_source_mode") == "draw": trajectory_text = "Drawn trajectory input." else: trajectory_text = "Trajectory metadata unavailable." comment = episode.get("comment") or "" error = episode.get("episode_error") or "" details = "\n".join( line for line in [ f"Task: {run['task']}", f"Model: {run['model']}", f"Condition: {CONDITION_LABELS.get(run['condition'], run['condition'])}", f"Run: {run.get('run_id')}", f"Episode: {episode.get('episode_number')}", f"Score: {score_label(episode.get('score'))}", f"Dataset: {run.get('hf_eval_dataset_id')}", f"Comment: {comment}" if comment else "", f"Error: {error}" if error else "", episode.get("video_note") or "The video is the full LeRobot chunk for this run. Use the slider to change the overlay image to the current dataset episode.", "Video unavailable in manifest." if not video else "", ] if line ) return video, overlay, details, trajectory_text def update_episode_bounds(run_choice: str | None): run = selected_run(run_choice) max_episode = run["num_episodes"] if run else 1 return gr.update(minimum=1, maximum=max_episode, value=1) css = """ .main-header h1 { margin-bottom: 0.25rem; } .main-header p { margin-top: 0; color: #475569; } textarea { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; } """ with gr.Blocks(title=MANIFEST.get("title", "Trajectory Showcase")) as demo: gr.Markdown( f"""

{MANIFEST.get("title", "Diffusion Trajectory Model Showcase")}

Episode-level videos, trajectory inputs, and scores generated from experiment logs.

""" ) gr.Dataframe( headers=["Task", "Model", "Condition", "Mean score", "Episodes", "Dataset"], value=summary_rows(), interactive=False, wrap=True, ) with gr.Row(): task_filter = gr.Dropdown(task_options(), value="All", label="Task") model_filter = gr.Dropdown(model_options(), value="All", label="Model") condition_filter = gr.Dropdown(condition_options(), value="All", label="Condition") initial_runs = matching_runs("All", "All", "All") run_select = gr.Dropdown( [run_label(run) for run in initial_runs], value=run_label(initial_runs[0]) if initial_runs else None, label="Run", ) episode_slider = gr.Slider( minimum=1, maximum=initial_runs[0]["num_episodes"] if initial_runs else 1, value=1, step=1, label="Episode", ) gr.Markdown("Use the slider to change the overlay image to the current dataset episode.") with gr.Row(): video = gr.Video(label="Result video") overlay = gr.Image(label="Trajectory input", type="filepath") trajectory_text = gr.Textbox(label="Trajectory source", interactive=False) details = gr.Textbox(label="Episode metadata", lines=10, interactive=False) for control in (task_filter, model_filter, condition_filter): control.change( update_run_choices, inputs=[task_filter, model_filter, condition_filter], outputs=[run_select, episode_slider], ).then(render_episode, inputs=[run_select, episode_slider], outputs=[video, overlay, details, trajectory_text]) run_select.change(update_episode_bounds, inputs=run_select, outputs=episode_slider).then( render_episode, inputs=[run_select, episode_slider], outputs=[video, overlay, details, trajectory_text], ) episode_slider.change( render_episode, inputs=[run_select, episode_slider], outputs=[video, overlay, details, trajectory_text], ) demo.load(render_episode, inputs=[run_select, episode_slider], outputs=[video, overlay, details, trajectory_text]) if __name__ == "__main__": demo.launch(css=css)