mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-24 10:16:09 +00:00
fix pi052 runtime and training safety
This commit is contained in:
@@ -19,7 +19,71 @@ import torch
|
||||
|
||||
pytest.importorskip("transformers")
|
||||
|
||||
from lerobot.policies.pi052.modeling_pi052 import _lin_ce_flat
|
||||
from lerobot.policies.pi052.modeling_pi052 import _lin_ce_flat, _shifted_lin_ce
|
||||
|
||||
|
||||
def test_shifted_ce_none_retains_distinct_per_sample_losses():
|
||||
hidden = torch.tensor(
|
||||
[
|
||||
[[8.0, 0.0], [0.0, 8.0], [0.0, 0.0]],
|
||||
[[0.0, 8.0], [8.0, 0.0], [0.0, 0.0]],
|
||||
]
|
||||
)
|
||||
labels = torch.tensor([[0, 0, 1], [0, 0, 1]])
|
||||
losses = _shifted_lin_ce(hidden, torch.eye(2), labels, reduction="none")
|
||||
|
||||
assert losses.shape == (2,)
|
||||
assert losses[0] < losses[1]
|
||||
|
||||
|
||||
def test_checkpoint_resolution_forwards_explicit_hub_options(monkeypatch, tmp_path):
|
||||
import lerobot.policies.pi052.modeling_pi052 as modeling_pi052
|
||||
|
||||
checkpoint = tmp_path / "model.safetensors"
|
||||
checkpoint.touch()
|
||||
calls = []
|
||||
|
||||
def fake_cached_file(model_id, filename, **kwargs):
|
||||
calls.append((model_id, filename, kwargs))
|
||||
return None if filename.endswith("index.json") else str(checkpoint)
|
||||
|
||||
monkeypatch.setattr(modeling_pi052, "cached_file", fake_cached_file)
|
||||
files = modeling_pi052._resolve_weight_files(
|
||||
"org/model",
|
||||
force_download=True,
|
||||
resume_download=True,
|
||||
proxies={"https": "proxy"},
|
||||
token="secret",
|
||||
cache_dir=tmp_path / "cache",
|
||||
local_files_only=True,
|
||||
revision="commit",
|
||||
)
|
||||
|
||||
assert files == [checkpoint]
|
||||
for _model_id, _filename, kwargs in calls:
|
||||
assert kwargs["revision"] == "commit"
|
||||
assert kwargs["cache_dir"] == tmp_path / "cache"
|
||||
assert kwargs["force_download"] is True
|
||||
assert kwargs["resume_download"] is True
|
||||
assert kwargs["proxies"] == {"https": "proxy"}
|
||||
assert kwargs["token"] == "secret"
|
||||
assert kwargs["local_files_only"] is True
|
||||
|
||||
|
||||
def test_checkpoint_resolution_rejects_local_directory_without_weights(tmp_path):
|
||||
import lerobot.policies.pi052.modeling_pi052 as modeling_pi052
|
||||
|
||||
with pytest.raises(FileNotFoundError, match="model.safetensors"):
|
||||
modeling_pi052._resolve_weight_files(
|
||||
tmp_path,
|
||||
force_download=False,
|
||||
resume_download=None,
|
||||
proxies=None,
|
||||
token=None,
|
||||
cache_dir=None,
|
||||
local_files_only=False,
|
||||
revision=None,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("z_loss_weight", [0.0, 1e-4])
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Copyright 2026 The HuggingFace Inc. team. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def test_pi052_config_import_does_not_load_model_or_dataset_processor():
|
||||
code = """
|
||||
import sys
|
||||
from lerobot.policies import PI052Config
|
||||
assert PI052Config.__name__ == "PI052Config"
|
||||
assert "lerobot.policies.pi052.modeling_pi052" not in sys.modules
|
||||
assert "lerobot.policies.pi052.processor_pi052" not in sys.modules
|
||||
"""
|
||||
subprocess.run([sys.executable, "-c", code], check=True)
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from lerobot.policies import factory
|
||||
from lerobot.policies.pi0_fast.configuration_pi0_fast import PI0FastConfig
|
||||
from lerobot.policies.pi052 import fit_fast_tokenizer as fit_module
|
||||
@@ -48,6 +50,27 @@ def test_pi0_fast_resolves_dataset_specific_tokenizer(monkeypatch, tmp_path):
|
||||
}
|
||||
|
||||
|
||||
def test_fast_fit_failure_is_not_silently_replaced(monkeypatch, tmp_path):
|
||||
config = PI0FastConfig(auto_fit_fast_tokenizer=True, fast_tokenizer_cache_dir=str(tmp_path))
|
||||
monkeypatch.setattr(
|
||||
fit_module,
|
||||
"fit_fast_tokenizer",
|
||||
lambda **kwargs: (_ for _ in ()).throw(RuntimeError("fit failed")),
|
||||
)
|
||||
|
||||
with pytest.raises(RuntimeError, match="fit failed"):
|
||||
fit_module.resolve_fast_tokenizer(config, "user/dataset")
|
||||
|
||||
|
||||
def test_each_node_uses_its_local_rank_zero_as_fit_leader(monkeypatch):
|
||||
monkeypatch.setenv("RANK", "8")
|
||||
monkeypatch.setenv("LOCAL_RANK", "0")
|
||||
assert fit_module._is_local_leader()
|
||||
|
||||
monkeypatch.setenv("LOCAL_RANK", "1")
|
||||
assert not fit_module._is_local_leader()
|
||||
|
||||
|
||||
def test_pretrained_pi0_fast_overrides_only_fitted_tokenizer(monkeypatch):
|
||||
config = PI0FastConfig(auto_fit_fast_tokenizer=True)
|
||||
calls = []
|
||||
|
||||
Reference in New Issue
Block a user