mirror of
https://github.com/huggingface/lerobot.git
synced 2026-08-08 17:39:44 +00:00
refactor(g05): use recipe message dropout
This commit is contained in:
@@ -47,6 +47,17 @@ def test_message_turn_requires_a_stream():
|
||||
MessageTurn(role="user", content="${task}")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dropout", [-0.1, 1.1, float("inf"), float("nan")])
|
||||
def test_message_turn_rejects_invalid_dropout(dropout):
|
||||
with pytest.raises(ValueError, match="between 0 and 1"):
|
||||
MessageTurn(role="user", content="${task}", stream="high_level", dropout=dropout)
|
||||
|
||||
|
||||
def test_message_turn_rejects_non_numeric_dropout():
|
||||
with pytest.raises(TypeError, match="probability"):
|
||||
MessageTurn(role="user", content="${task}", stream="high_level", dropout="half")
|
||||
|
||||
|
||||
def test_message_recipe_requires_at_least_one_target():
|
||||
with pytest.raises(ValueError, match="target"):
|
||||
TrainingRecipe(
|
||||
@@ -152,33 +163,25 @@ def test_from_dict_with_nested_blend():
|
||||
assert isinstance(recipe.blend["a"].messages[0], MessageTurn)
|
||||
|
||||
|
||||
def test_applicable_blend_round_trips_from_dict():
|
||||
def test_message_dropout_round_trips_from_dict():
|
||||
recipe = TrainingRecipe.from_dict(
|
||||
{
|
||||
"select_from_applicable": True,
|
||||
"blend": {
|
||||
"subtask": {
|
||||
"weight": 2,
|
||||
"requires": ["subtask"],
|
||||
"messages": [
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "${subtask}",
|
||||
"stream": "low_level",
|
||||
"target": True,
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{"role": "user", "content": "${task}", "stream": "low_level"},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "${subtask}",
|
||||
"stream": "low_level",
|
||||
"target": True,
|
||||
"if_present": "subtask",
|
||||
"dropout": 0.5,
|
||||
},
|
||||
"action": {
|
||||
"weight": 1,
|
||||
"messages": [{"role": "user", "content": "${task}", "stream": "low_level"}],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
assert recipe.select_from_applicable
|
||||
assert recipe.blend["subtask"].requires == ["subtask"]
|
||||
assert recipe.messages[1].dropout == 0.5
|
||||
assert recipe.messages[1].if_present == "subtask"
|
||||
|
||||
|
||||
def test_from_yaml_round_trips_through_load_recipe(tmp_path: Path):
|
||||
|
||||
@@ -176,27 +176,19 @@ def test_deterministic_blend_sampling():
|
||||
assert first == second
|
||||
|
||||
|
||||
def test_applicable_blend_filters_missing_bindings_before_weighted_selection():
|
||||
def test_message_dropout_skips_missing_optional_bindings():
|
||||
recipe = TrainingRecipe(
|
||||
select_from_applicable=True,
|
||||
blend={
|
||||
"missing": TrainingRecipe(
|
||||
weight=1_000,
|
||||
requires=["subtask"],
|
||||
messages=[
|
||||
MessageTurn(
|
||||
role="assistant",
|
||||
content="${subtask}",
|
||||
stream="low_level",
|
||||
target=True,
|
||||
)
|
||||
],
|
||||
messages=[
|
||||
MessageTurn(role="user", content="${task}", stream="low_level"),
|
||||
MessageTurn(
|
||||
role="assistant",
|
||||
content="${subtask}",
|
||||
stream="low_level",
|
||||
target=True,
|
||||
if_present="subtask",
|
||||
dropout=0.5,
|
||||
),
|
||||
"action": TrainingRecipe(
|
||||
weight=1,
|
||||
messages=[MessageTurn(role="user", content="${task}", stream="low_level")],
|
||||
),
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
rendered = render_sample(
|
||||
@@ -212,7 +204,7 @@ def test_applicable_blend_filters_missing_bindings_before_weighted_selection():
|
||||
assert rendered["target_message_indices"] == []
|
||||
|
||||
|
||||
def test_applicable_blend_can_select_joint_bbox_subtask_target():
|
||||
def test_g05_dropout_produces_all_bbox_subtask_combinations():
|
||||
recipe = TrainingRecipe.from_yaml("src/lerobot/configs/recipes/g05_bbox_subtask.yaml")
|
||||
persistent = [persistent_row("assistant", "grasp the cup", "subtask", 0.0)]
|
||||
events = [
|
||||
@@ -224,24 +216,64 @@ def test_applicable_blend_can_select_joint_bbox_subtask_target():
|
||||
}
|
||||
]
|
||||
|
||||
rendered = next(
|
||||
candidate
|
||||
for sample_idx in range(100)
|
||||
if (
|
||||
candidate := render_sample(
|
||||
recipe=recipe,
|
||||
persistent=persistent,
|
||||
events=events,
|
||||
t=0.0,
|
||||
sample_idx=sample_idx,
|
||||
task="pick the cup",
|
||||
)
|
||||
rendered_by_targets = {}
|
||||
for sample_idx in range(100):
|
||||
rendered = render_sample(
|
||||
recipe=recipe,
|
||||
persistent=persistent,
|
||||
events=events,
|
||||
t=0.0,
|
||||
sample_idx=sample_idx,
|
||||
task="pick the cup",
|
||||
)
|
||||
and candidate["target_message_indices"] == [1, 2]
|
||||
targets = tuple(
|
||||
rendered["messages"][idx]["content"].split(":", 1)[0]
|
||||
for idx in rendered["target_message_indices"]
|
||||
)
|
||||
rendered_by_targets.setdefault(targets, rendered)
|
||||
|
||||
assert set(rendered_by_targets) == {
|
||||
(),
|
||||
("BBoxJSON",),
|
||||
("Subtask",),
|
||||
("BBoxJSON", "Subtask"),
|
||||
}
|
||||
joint = rendered_by_targets[("BBoxJSON", "Subtask")]
|
||||
assert joint["messages"][1]["content"].startswith("BBoxJSON:")
|
||||
assert joint["messages"][2]["content"] == "Subtask: grasp the cup"
|
||||
|
||||
|
||||
def test_message_dropout_is_deterministic_for_sample_index():
|
||||
recipe = TrainingRecipe(
|
||||
messages=[
|
||||
MessageTurn(role="user", content="${task}", stream="low_level"),
|
||||
MessageTurn(
|
||||
role="assistant",
|
||||
content="${subtask}",
|
||||
stream="low_level",
|
||||
target=True,
|
||||
dropout=0.5,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
assert rendered["messages"][1]["content"].startswith("BBoxJSON:")
|
||||
assert rendered["messages"][2]["content"] == "Subtask: grasp the cup"
|
||||
first = render_sample(
|
||||
recipe=recipe,
|
||||
persistent=PERSISTENT,
|
||||
events=[],
|
||||
t=0.0,
|
||||
sample_idx=42,
|
||||
task="pick the cup",
|
||||
)
|
||||
second = render_sample(
|
||||
recipe=recipe,
|
||||
persistent=PERSISTENT,
|
||||
events=[],
|
||||
t=0.0,
|
||||
sample_idx=42,
|
||||
task="pick the cup",
|
||||
)
|
||||
assert first == second
|
||||
|
||||
|
||||
def test_emitted_at_filters_vqa_by_camera():
|
||||
|
||||
Reference in New Issue
Block a user