Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion src/tether/exporters/monolithic.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,22 @@ def _require_monolithic_deps() -> None:
except ImportError:
missing.append(pip_name)

# lerobot version must be exactly 0.5.1 — the SmolVLA/pi0 export patches
# target its 0.5.1 module layout (SmolVLMWithExpertModel.embed_image, the
# masking_utils surface). A different lerobot imports fine but then fails
# the monkeypatch or exports a wrong graph — the common, confusing failure
# behind issue #190. Assert it explicitly rather than discovering it later.
try:
import lerobot
lerobot_ver = getattr(lerobot, "__version__", "unknown")
if lerobot_ver != "0.5.1":
missing.append(
f"lerobot==0.5.1 (found {lerobot_ver}; the monolithic export "
f"patches target lerobot 0.5.1's module layout exactly)"
)
except ImportError:
pass # already reported as missing above

if missing:
raise ImportError(
"Missing dependencies for monolithic export:\n - "
Expand Down Expand Up @@ -251,7 +267,17 @@ def _embed_image_with_explicit_patch_mask(self, image):
_embed_image_with_explicit_patch_mask._tether_patched = True
_smolvla.SmolVLMWithExpertModel.embed_image = _embed_image_with_explicit_patch_mask
except Exception as exc:
logger.debug("SmolVLA explicit patch-mask export patch not installed: %s", exc)
# WARNING, not debug: if this patch fails to apply (e.g. a lerobot API
# change moved SmolVLMWithExpertModel.embed_image), the SmolVLA export
# proceeds with the UNPATCHED forward and can fail later with a cryptic
# mask-broadcast error — or export a subtly wrong graph. Surface it so
# the failure is attributable, not silent (relates to issue #190).
logger.warning(
"SmolVLA explicit patch-mask export patch did NOT apply (%s). "
"The export will continue unpatched; if it fails downstream with a "
"vision/attention-mask shape error, this is the likely cause. "
"Verify lerobot==0.5.1 is installed.", exc,
)

try:
from transformers.models.smolvlm import modeling_smolvlm as _smolvlm
Expand Down
40 changes: 40 additions & 0 deletions tests/test_monolithic_version_guard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""The monolithic export must reject a wrong lerobot version up front (#190).

Previously only `transformers` was version-checked; `lerobot` was merely
imported, so a mismatched lerobot passed the dep check and failed later with a
confusing monkeypatch/mask error.
"""
from __future__ import annotations

import sys
import types

import pytest

from tether.exporters import monolithic


def _fake_lerobot(version: str) -> types.ModuleType:
m = types.ModuleType("lerobot")
m.__version__ = version
return m


def test_wrong_lerobot_version_is_reported(monkeypatch):
monkeypatch.setitem(sys.modules, "lerobot", _fake_lerobot("0.4.0"))
with pytest.raises(ImportError) as ei:
monolithic._require_monolithic_deps()
assert "lerobot==0.5.1 (found 0.4.0" in str(ei.value)


def test_correct_lerobot_version_not_reported(monkeypatch):
monkeypatch.setitem(sys.modules, "lerobot", _fake_lerobot("0.5.1"))
# Other monolithic deps may be absent in this env (so it can still raise),
# but the lerobot-version complaint must NOT be among the reasons.
try:
monolithic._require_monolithic_deps()
msg = ""
except ImportError as e:
msg = str(e)
assert "found 0.5.1" not in msg
assert "lerobot==0.5.1 (found" not in msg
Loading