mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-24 10:16:09 +00:00
171e06c6ba
Set up the runtime so a second language-conditioned policy reuses the CLI/REPL/UI instead of copying pi052's. The tick loop, REPL, panel, and interactive CLI are now policy-independent in lerobot/runtime/; a policy plugs in only a LanguageConditionedPolicyAdapter. - Move repl.py, ui.py, and runtime_cli.py (-> cli.py) from pi052/inference/ into lerobot/runtime/. Generalize labels/titles (panel_label param, [runtime] prefixes). - lerobot.runtime.cli.run(argv, *, adapter_factory, panel_label, prog) is the shared entry; policy loading already dispatches generically via the factory on cfg.type. - lerobot-pi052-runtime is now a thin entry (scripts/lerobot_pi052_runtime.py) that passes PI052PolicyAdapter into run(). pi052/inference/ keeps only the adapter. - Drop PI052Runtime back-compat wrapper (no consumers). - Drop VQA visualization: delete inference/vqa.py + test_pi052_vqa_loc.py, remove answer_vqa/VQAResult from the Protocol + adapter, and the /question command + overlay paths from the CLI/REPL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
53 lines
2.1 KiB
Python
53 lines
2.1 KiB
Python
from types import SimpleNamespace
|
|
|
|
from lerobot.policies.pi052.inference.pi052_adapter import PI052PolicyAdapter, split_plan_and_say
|
|
from lerobot.runtime import RuntimeState
|
|
|
|
|
|
def test_pi052_adapter_builds_recipe_prompts_from_runtime_state():
|
|
adapter = PI052PolicyAdapter(policy=object())
|
|
state = RuntimeState(
|
|
task="clean the kitchen",
|
|
language_context={"memory": "cup moved", "plan": "pick then place"},
|
|
extra={"prior_subtask": "pick the cup"},
|
|
)
|
|
|
|
assert adapter.messages_for("subtask", state) == [{"role": "user", "content": "clean the kitchen"}]
|
|
assert adapter.messages_for("memory", state) == [
|
|
{"role": "user", "content": "clean the kitchen"},
|
|
{"role": "assistant", "content": "Previous memory: cup moved"},
|
|
{"role": "user", "content": "Completed subtask: pick the cup"},
|
|
]
|
|
assert adapter.messages_for("interjection", state, user_text="wait") == [
|
|
{"role": "user", "content": "clean the kitchen"},
|
|
{"role": "assistant", "content": "Previous plan:\npick then place"},
|
|
{"role": "user", "content": "wait"},
|
|
]
|
|
|
|
|
|
def test_pi052_adapter_strips_say_markers_from_plan_text():
|
|
adapter = PI052PolicyAdapter(policy=object())
|
|
text = "Move to the sink. <say>heading to the sink</say>"
|
|
|
|
assert split_plan_and_say(text) == ("Move to the sink.", "heading to the sink")
|
|
assert adapter.plan_from_text(text) == "Move to the sink."
|
|
|
|
|
|
def test_pi052_runtime_cli_smoke_does_not_load_model(monkeypatch):
|
|
"""The pi052 entry wires its adapter into the generic runtime CLI."""
|
|
from lerobot.runtime import cli
|
|
from lerobot.scripts import lerobot_pi052_runtime
|
|
|
|
fake_policy = SimpleNamespace(config=SimpleNamespace(device="cpu"))
|
|
|
|
monkeypatch.setattr(
|
|
cli,
|
|
"_load_policy_and_preprocessor",
|
|
lambda policy_path, dataset_repo_id: (fake_policy, None, None, None),
|
|
)
|
|
monkeypatch.setattr(cli, "_run_repl", lambda runtime, **kwargs: 0)
|
|
|
|
assert (
|
|
lerobot_pi052_runtime.main(["--policy.path=fake", "--no_robot", "--task=clean", "--max_ticks=0"]) == 0
|
|
)
|