mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-25 18:56:09 +00:00
fix: add attention_mask
This commit is contained in:
+57
-7
@@ -1,7 +1,7 @@
|
|||||||
"""Processor for past-only temporal SigLIP2 value inputs."""
|
"""Processor for past-only temporal SigLIP2 value inputs."""
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
from typing import Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
from torch import Tensor
|
from torch import Tensor
|
||||||
@@ -16,7 +16,6 @@ from lerobot.processor import (
|
|||||||
ProcessorStep,
|
ProcessorStep,
|
||||||
ProcessorStepRegistry,
|
ProcessorStepRegistry,
|
||||||
RenameObservationsProcessorStep,
|
RenameObservationsProcessorStep,
|
||||||
TokenizerProcessorStep,
|
|
||||||
batch_to_transition,
|
batch_to_transition,
|
||||||
policy_action_to_transition,
|
policy_action_to_transition,
|
||||||
transition_to_batch,
|
transition_to_batch,
|
||||||
@@ -27,10 +26,21 @@ from lerobot.rewards.distributional_value_function.processor_distributional_valu
|
|||||||
resize_with_pad_torch,
|
resize_with_pad_torch,
|
||||||
)
|
)
|
||||||
from lerobot.types import EnvTransition, TransitionKey
|
from lerobot.types import EnvTransition, TransitionKey
|
||||||
from lerobot.utils.constants import POLICY_POSTPROCESSOR_DEFAULT_NAME, POLICY_PREPROCESSOR_DEFAULT_NAME
|
from lerobot.utils.constants import (
|
||||||
|
OBS_LANGUAGE_ATTENTION_MASK,
|
||||||
|
OBS_LANGUAGE_TOKENS,
|
||||||
|
POLICY_POSTPROCESSOR_DEFAULT_NAME,
|
||||||
|
POLICY_PREPROCESSOR_DEFAULT_NAME,
|
||||||
|
)
|
||||||
|
from lerobot.utils.import_utils import _transformers_available, require_package
|
||||||
|
|
||||||
from .configuration_temporal_siglip_value_function import TemporalSiglipVFConfig
|
from .configuration_temporal_siglip_value_function import TemporalSiglipVFConfig
|
||||||
|
|
||||||
|
if TYPE_CHECKING or _transformers_available:
|
||||||
|
from transformers import AutoTokenizer
|
||||||
|
else:
|
||||||
|
AutoTokenizer = None
|
||||||
|
|
||||||
|
|
||||||
@ProcessorStepRegistry.register(name="temporal_siglip_vf_image_processor")
|
@ProcessorStepRegistry.register(name="temporal_siglip_vf_image_processor")
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -91,6 +101,48 @@ class TemporalSiglipImageProcessorStep(ProcessorStep):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ProcessorStepRegistry.register(name="temporal_siglip_vf_tokenizer")
|
||||||
|
@dataclass
|
||||||
|
class TemporalSiglipTokenizerStep(ProcessorStep):
|
||||||
|
tokenizer_name: str
|
||||||
|
max_length: int
|
||||||
|
_tokenizer: Any = field(default=None, init=False, repr=False)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
require_package("transformers", extra="recap")
|
||||||
|
self._tokenizer = AutoTokenizer.from_pretrained(self.tokenizer_name)
|
||||||
|
|
||||||
|
def __call__(self, transition: EnvTransition) -> EnvTransition:
|
||||||
|
transition = transition.copy()
|
||||||
|
task = transition.get(TransitionKey.COMPLEMENTARY_DATA, {}).get("task")
|
||||||
|
if task is None:
|
||||||
|
raise ValueError("Task is required for TemporalSiglipTokenizerStep")
|
||||||
|
task = [task] if isinstance(task, str) else list(task)
|
||||||
|
tokenized = self._tokenizer(
|
||||||
|
task,
|
||||||
|
padding="max_length",
|
||||||
|
max_length=self.max_length,
|
||||||
|
truncation=True,
|
||||||
|
return_tensors="pt",
|
||||||
|
)
|
||||||
|
input_ids = tokenized["input_ids"]
|
||||||
|
attention_mask = tokenized.get("attention_mask")
|
||||||
|
if attention_mask is None:
|
||||||
|
attention_mask = input_ids.ne(self._tokenizer.pad_token_id)
|
||||||
|
|
||||||
|
observation = dict(transition.get(TransitionKey.OBSERVATION, {}))
|
||||||
|
observation[OBS_LANGUAGE_TOKENS] = input_ids
|
||||||
|
observation[OBS_LANGUAGE_ATTENTION_MASK] = attention_mask.bool()
|
||||||
|
transition[TransitionKey.OBSERVATION] = observation
|
||||||
|
return transition
|
||||||
|
|
||||||
|
def transform_features(self, features):
|
||||||
|
return features
|
||||||
|
|
||||||
|
def get_config(self):
|
||||||
|
return {"tokenizer_name": self.tokenizer_name, "max_length": self.max_length}
|
||||||
|
|
||||||
|
|
||||||
def make_temporal_siglip_vf_pre_post_processors(
|
def make_temporal_siglip_vf_pre_post_processors(
|
||||||
config: TemporalSiglipVFConfig,
|
config: TemporalSiglipVFConfig,
|
||||||
dataset_stats: dict[str, dict[str, torch.Tensor]] | None = None,
|
dataset_stats: dict[str, dict[str, torch.Tensor]] | None = None,
|
||||||
@@ -116,11 +168,9 @@ def make_temporal_siglip_vf_pre_post_processors(
|
|||||||
history_steps=config.history_steps,
|
history_steps=config.history_steps,
|
||||||
),
|
),
|
||||||
DistributionalVFPrepareTaskPromptStep(),
|
DistributionalVFPrepareTaskPromptStep(),
|
||||||
TokenizerProcessorStep(
|
TemporalSiglipTokenizerStep(
|
||||||
tokenizer_name=config.siglip_path,
|
tokenizer_name=config.siglip_path,
|
||||||
max_length=config.tokenizer_max_length,
|
max_length=config.tokenizer_max_length,
|
||||||
padding_side="right",
|
|
||||||
padding="max_length",
|
|
||||||
),
|
),
|
||||||
DeviceProcessorStep(device=config.device or "cpu"),
|
DeviceProcessorStep(device=config.device or "cpu"),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -64,6 +64,31 @@ def test_temporal_image_processor():
|
|||||||
assert -1.0 <= observation[CAMERAS[0]].min() <= observation[CAMERAS[0]].max() <= 1.0
|
assert -1.0 <= observation[CAMERAS[0]].min() <= observation[CAMERAS[0]].max() <= 1.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_siglip_tokenizer_builds_missing_attention_mask(monkeypatch):
|
||||||
|
from lerobot.rewards.temporal_siglip_value_function import (
|
||||||
|
processor_temporal_siglip_value_function as processing,
|
||||||
|
)
|
||||||
|
|
||||||
|
class FakeTokenizer:
|
||||||
|
pad_token_id = 0
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
return {"input_ids": torch.tensor([[5, 1, 0, 0]])}
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
processing.AutoTokenizer,
|
||||||
|
"from_pretrained",
|
||||||
|
lambda *args, **kwargs: FakeTokenizer(),
|
||||||
|
)
|
||||||
|
step = processing.TemporalSiglipTokenizerStep("fake", max_length=4)
|
||||||
|
transition = {
|
||||||
|
TransitionKey.OBSERVATION: {},
|
||||||
|
TransitionKey.COMPLEMENTARY_DATA: {"task": ["Task: stack blocks."]},
|
||||||
|
}
|
||||||
|
observation = step(transition)[TransitionKey.OBSERVATION]
|
||||||
|
assert observation[OBS_LANGUAGE_ATTENTION_MASK].tolist() == [[True, True, False, False]]
|
||||||
|
|
||||||
|
|
||||||
def test_temporal_model_forward(monkeypatch):
|
def test_temporal_model_forward(monkeypatch):
|
||||||
from lerobot.rewards.temporal_siglip_value_function import (
|
from lerobot.rewards.temporal_siglip_value_function import (
|
||||||
modeling_temporal_siglip_value_function as modeling,
|
modeling_temporal_siglip_value_function as modeling,
|
||||||
|
|||||||
Reference in New Issue
Block a user