From c98c695127478000d691004c90692d8f492ae4a5 Mon Sep 17 00:00:00 2001 From: Pepijn Date: Tue, 12 May 2026 17:26:59 +0200 Subject: [PATCH] feat(smolvla2-runtime): 'rephrase:' prefix to swap task string in place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a third stdin channel alongside 'task:' and bare interjections: rephrase: Swaps state['task'] with the new string while preserving plan/memory/ subtask. Lets the operator probe how robust the model is to wording variations of the same task — the trained augmentation provided n_task_rephrasings≈30 task wordings per dataset task, and this is the direct way to exercise that distribution at inference without generating a fresh plan via user_interjection_response. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../scripts/lerobot_smolvla2_runtime.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/lerobot/scripts/lerobot_smolvla2_runtime.py b/src/lerobot/scripts/lerobot_smolvla2_runtime.py index a47929208..09548f2d1 100644 --- a/src/lerobot/scripts/lerobot_smolvla2_runtime.py +++ b/src/lerobot/scripts/lerobot_smolvla2_runtime.py @@ -785,17 +785,32 @@ def _run_autonomous( # Typing a rephrasing of the current task as an # interjection is the trained way to redirect without # resetting the high-level plan from scratch. + # ``task: `` — full task switch, clears plan/memory/subtask + # ``rephrase: `` — swap the task string in place, + # keep plan/memory/subtask. Tests + # prompt robustness from the + # n_task_rephrasings training + # augmentation: the model should + # behave the same on equivalent + # phrasings of the same task. + # bare line ending in ``?`` — VQA + # bare line — interjection if lower.startswith("task:"): new_task = line[5:].strip() if new_task: runtime.set_task(new_task) - # Clear stale plan/memory/subtask so the next - # high-level pass regenerates from the new task - # rather than carrying over context from the old. runtime.state["current_plan"] = None runtime.state["current_memory"] = None runtime.state["current_subtask"] = None continue + if lower.startswith("rephrase:"): + rephrased = line[len("rephrase:"):].strip() + if rephrased: + runtime.state["task"] = rephrased + runtime.state.setdefault("log_lines", []).append( + f"Task rephrased: {rephrased} (plan/memory preserved)" + ) + continue if not runtime.state.get("task"): runtime.set_task(line) continue @@ -1110,6 +1125,13 @@ def _run_repl(runtime: Any, *, initial_task: str | None, max_ticks: int | None) runtime.state["current_plan"] = None runtime.state["current_memory"] = None runtime.state["current_subtask"] = None + elif lower.startswith("rephrase:"): + rephrased = line[len("rephrase:"):].strip() + if rephrased: + runtime.state["task"] = rephrased + runtime.state.setdefault("log_lines", []).append( + f"Task rephrased: {rephrased} (plan/memory preserved)" + ) elif not runtime.state.get("task"): runtime.set_task(line) elif lower.endswith("?"):