Changelog¶
All notable changes to VersatIL will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
[0.4.0] - 2026-07-05¶
Added¶
- Vision-language-action policies:
AutoregressiveVLADecoder(OpenVLA, pi0-FAST),OpenVLAOFTDecoder, and interleaved-attention decoders for Pi0, Pi0.5, and SmolVLA, with LIBERO end-to-end presets for all six. Decoders own their VLM backbones (Prismatic, PaliGemma, SmolVLM) through decoder-localvision_language_modelconfig groups, with LoRA enabled by default. PrismaticVLMwith raw TRI-ML checkpoint loading and DINOv2+SigLIP visual prefixes, plus a reusableDinoV2SigLIPRGBEncoderand aVLMEncoderfor policies that need image-text embeddings without a generative backbone.- PEFT LoRA adaptation for HuggingFace language encoders, VLM encoders, timm image encoders, and generative VLM backbones.
- Action tokenization split into
ActionDiscretizer(fast,binned) andActionTokenIdMapping(identity,language_vocabulary), with uniform and quantile binning strategies and aDiscreteDecoderbase for tokenized-action decoders. - Quantization-aware training through torchao's eager
QATConfig, with ready-to-composeqat_int8_dynamic_intx_int4,qat_int4_weight_only, andqat_int2_weight_onlypresets and QAT-aware checkpoint loading. - Standalone quantization workflows (
none,eager,pt2e) with per-module targets, an XNNPACK PT2E backend, and anExecutorchXNNPACKBackendthat lowers exported programs to ExecuTorch.pteartifacts. - Explainability package (
versatil.explainability): Grad-CAM, Grad-CAM++, and Ablation-CAM attribution over dataset samples or live inference, with per-decoder explanation targets, heatmap rendering, and theversatil.endpoints.explainendpoint. RGBCameraMetadata/DepthCameraMetadatawith semantic camera-modality validation and metadata-driven pixel scaling viamax_pixel_value.trust_remote_codesupport for HuggingFace models that ship custom code, and aninfer_constant_priorflag onGaussianPriorfor deterministic deployment latents.
Changed¶
- Every feature crossing the encoding-pipeline boundary carries a canonical
(B, T, ...)layout, even for a single observation frame. Rank alone identifies the feature kind (5D spatial, 4D token sequence, 3D vector, 2D algorithm context); thehas_time_dimflag and runtime shape guessing are gone. Custom encoders and decoders must follow this contract. - Action keys follow action-space metadata declaration order everywhere (policy outputs, tokenization, exported and compressed artifacts), replacing the mix of alphabetical and insertion orders.
- Public parameters standardized on explicit long forms
(
embedding_dimension,number_of_heads,input_dimension,hidden_dimension(s),conditioning_dimension,maximum_sequence_length,epsilon) across layers, decoders, encoders, configs, and YAMLs. - Losses moved to
versatil.metrics.losseswith one module per family. Checkpoints saved before this change need the_target_paths rewritten in their storedconfig.yaml. - The twelve per-dataset directory resolvers are replaced by
${dataset_dir:ENV_VAR,subpath}. - The deployment endpoint is Hydra-based and renamed from
versatil.endpoints.testtoversatil.endpoints.deploy, with client settings under theclient.group shared with online explainability, and arequest_timeout_secondsthat raises instead of blocking on a dead server. - Hydra configs ship inside the wheel (
versatil.hydra_configs), so the documented CLI works for pip installs; training-run recipes ship as examples. - Checkpoints load with
weights_only=Trueunder an explicit allowlist, so third-party checkpoints cannot execute pickled code. - A zarr replay buffer is rebuilt only when structurally corrupt; key
mismatches raise unless
recreate_zarr_on_missing_keysopts in. - torchao compatibility patches apply in memory through an import hook instead of editing installed site-packages files.
- Every config dataclass documents its fields, so the API reference renders complete config documentation.
- Dependencies: PyTorch 2.12 (
cu130index), torchao 0.17, timm 1.0.27, transformers 5.9, hydra-core 1.4.0.dev5/omegaconf 2.4.0.dev12 for Python 3.14. Dev tooling moved to a uvdevdependency group; torchaudio removed.
Fixed¶
- EMA checkpoints stored averaged weights as the policy state, so resumed trainings continued from EMA weights; raw weights are now preserved and EMA respects gradient-accumulation boundaries.
- Image normalization broadcast per-channel statistics against the wrong axis, producing striped images.
- Padding-aware loss reduction scaled
(B, T, D)losses by the action dimension relative to unmasked losses; both paths now average over valid elements. - Binary gripper inference thresholded the raw logit instead of the sigmoid probability, biasing deployment toward the closed state.
- MoE experts ran on unsynchronized CUDA streams, nondeterministically corrupting GPU outputs and gradients.
- Geometric attention mixed head and spatial dimensions in a reshape, scrambling head contents.
- The DFormerv2 encoder now reproduces the reference implementation exactly and loads the official pretrained checkpoints (mirrored on HuggingFace), verified tensor-for-tensor against the reference forward.
- Roll-angle action deltas were not wrapped at the ±π discontinuity.
- Fitted action statistics dropped each episode's final row for precomputed actions, letting served actions normalize outside the fitted range; action padding masks now cover mixed precomputed/on-the-fly spaces.
- Raw dataset import resized every camera to the first camera's resolution; each camera now uses its own configured size, and depth clamping at inference uses each camera's own normalizer range.
- Per-sample image augmentations drew independent spatial transforms per camera; cameras within a sample now share replayed parameters.
- Epoch metrics averaged per-batch instead of per-sample, deflating components that appear in only some batches and skewing partial batches.
ReduceLROnPlateaunever stepped without a validation loader, was silently undone when combined with per-step LR schedules (now rejected), and lost its state on checkpoint resume.- Phase-classification metrics included edge-padded steps.
ConditionalUnet1Dinjected up-path local conditioning at half temporal resolution.- Variational training leaked decoder-only latent jitter into prior targets and logged latents.
- Post-training compression: reports compared quantized models against
already-mutated baselines, denoising thresholds were dropped from
artifacts, Conv+BN fusion missed
Sequential-wrapped pairs, exports specialized the batch dimension, compressed eager artifacts never moved off CPU, and unstructured pruning defaulted to every weight parameter including norm scales and embeddings (now convolution and linear layers). - Stricter validation throughout: degenerate data (constant depth, single-row fits, unordered winsorization quantiles), misconfigured modules (invalid routing, temperatures, head counts), and mismatched tensor layouts fail loudly instead of training silently wrong.
Removed¶
- Legacy experimental decoders
DiscreteDETRActionTransformer,FreeActionTransformer, andMoEFreeActionTransformer, with their Hydra configs. - Dead public API surface:
Workspace.load_checkpoint/predict,LossOutput.__add__, the unusedvalidate_loss_keyspolicy-constructor parameter, and decorative constructor flags. - Obsolete torch 2.10/torchao 0.16 source-partition monkey patch for X86Inductor PT2E quantization.
[0.3.0] - 2026-05-11¶
Added¶
- End-to-end experiment config families for PushT, Block Pushing, Kitchen, Multimodal Ant, UR3 Block Push, and synthetic multimodal benchmarks, including state/RGB variants where supported.
- LIBERO/LIBERO+ configs for GPT-style action transformers, Pi0/SmolVLA-style VLA policies, and vision/language encoder sweeps.
- Dataset schema, Zarr metadata, observation/action-space configs, OmegaConf path resolvers, and
.envvariables for the new local/LeRobot-compatible benchmark families. - Synthetic multimodal benchmark generation, presets, rollout metrics, and training/evaluation configs for mode-recovery experiments.
- Variational latent-modeling components for multimodal action distributions: VQ posterior encoder, uniform/learned codebook priors, DiT latent prior configs, conditional MMD losses, and relaxed conditional Sinkhorn/OT losses.
- Staged training support with epoch-indexed trainability, optimizer, and loss-weight overrides, plus prior-target standardization and richer latent/synthetic rollout callbacks.
Pi0DecoderandSmolVLADecoderfactories — interleaved VLM-expert joint attention architectures where a pretrained VLM backbone is paired 1:1 with learned expert layers. Pi0 fuses timestep via MLP, Pi0.5 via adaptive normalization. SmolVLA alternates cross-attention and joint self-attention layers.GenerativeVLMEncoderabstract base for single-stream VLMs (embed images → embed text → concat → LM). Thin subclasses:PaliGemmaEncoder,SmolVLMEncoder. Replaces the monolithicmultimodal/vlm.py.TwoTowerVLMEncoder— CLIP-style separate vision/language towers withImageEncoderMixin+LanguageEncoderMixin.ImageEncoderMixin— abstract base class for multi-camera dispatch with per-camera feature naming (rgb:left,rgb:right). Subclassed byRGBEncoderMixin,DepthEncoderMixin,RGBDEncoderMixin.- Per-camera image sizes — encoding pipeline sets dimensions from
CameraMetadatain observation space.set_image_size()hook on encoders. LanguageEncoderMixin— shared tokenized text pad/truncate, attention mask construction, and output padding mask.FeatureMetadatafrozen dataclass(key, feature_type, dimension)withFeatureTypeenum (SPATIAL, SEQUENTIAL, FLAT). ReplacesEncoderOutput.GenerationCache/GenerationLayerCache— append-only cache for autoregressive generation. Grows token-by-token.ConditioningCache/ConditioningLayerCache— write-once cache for static context (observations, encoder features). Stores K/V and optionally Q for bidirectional conditioning. Cache presence implies behavior — nouse_cacheboolean.- Cross-attention caching for diffusion decoders —
DiffusionActionTransformerprecomputes conditioning K/V once and reuses across all denoising steps. - Transformer package decomposed into
attention/,block/,layer/,cache/sub-packages — ~1600 lines of duplicated diffusion transformer internals deleted. TransformerMixin— shared weight init, positional encoding setup/application withoffsetfor cached generation, padding mask expansion.BlockNormalizationtype (AdaNorm | UnconditionedNorm) — uniform(x, condition) → (normed, gate)interface. Eliminates conditioning branches in transformer blocks.GatedLinearUnitgeneralizesSwiGLU— base class with configurable gate activation, plusSwiGLU(SiLU gate) andGeGLU(GELU-tanh gate) subclasses.- Encoder refactoring — encoders renamed by output format (spatial vs flat), not architecture.
CNNEncoder+SwinEncoder→SpatialRGBEncoder,ViTEncoder→FlatRGBEncoder,DepthCNNEncoder→SpatialDepthEncoder. - New backbones: ConvNeXtV2-Nano, TinyViT-21M, DINOv3-ConvNeXt-Small.
exclude_cls→num_prefix_tokensonTokenPoolingHead— handles CLS + register tokens.ImageProcessor— per-camera image processing extracted into standalone class (resize, augmentation, normalization).CallbackProviderprotocol for training callbacks — decoders/algorithms declare their own callbacks; Workspace collects via protocol check instead ofisinstancechains.action_execution_horizonparameter onInferenceClient— controls how many actions from each predicted chunk to execute before re-querying. Defaults toprediction_horizon.make_attention_masksupportscausal_actionsflag andcausal_prefix_suffix_lengthfor VLA prefix-suffix patterns.- LR scheduler now uses HuggingFace
transformers.get_schedulerwithlr_scheduler_kwargspassthrough.
Changed¶
ActionTransformerno longer requires spatial features — accepts any feature type.- Fusion modules report correct output feature types (SEQUENTIAL when inputs are sequential).
LanguageEncoderdetects CLS token viaAutoTokenizer.cls_token_idinstead of hardcoding.- Encoding pipeline YAML defaults cleaned up: removed redundant
_target_, added missing config group references. DataLoaderConfigno longer hardcodesimage_height/image_width— dimensions come from per-cameraCameraMetadata.ObservationPreprocessorusesImageProcessor+CameraMetadatainstead of raw albumentations transforms.PolicyLoaderreads precision from checkpoint config instead of requiring aprecisionparameter.FlowMatchingConfigaddsreverse_flow_conventionflag.data/augmentation/restructured todata/processing/—ActionProcessorandTransformBuildermoved alongsideImageProcessor.depth/dformerv2anddepth/light_geometricencoders moved tocross_modal/rgbd/.multimodal/package renamed bycross_modal/,vlm.pyis now avision_languagepackage.- Loss
_target_paths updated across all YAML configs for metrics package restructure (removed__init__.pyexports). - Diffusion transformer high-level classes (
CrossAttentionDiT,MMDiTTransformer,DiTBlock) now delegate to sharedtransformer/blocks and layers instead of maintaining duplicated implementations. - All
__init__.pyre-exports removed across transformer, training, and inference packages — consumers import from concrete modules.
Fixed¶
- GPT Action Transformer tokenized head had a 64-dim MLP bottleneck before predicting 1025 vocab classes with weight tying in the same space. Removed bottleneck — direct
embedding_dimension→ vocab projection. DiTPrioralways targeted noise regardless ofprediction_type— now branches correctly for epsilon, sample, and velocity.GaussianPriorused staleself.deviceafter.to()— now uses_device_trackerbuffer.ConditionalCNNEncoderpooling head not re-frozen afterset_image_size()whenfrozen=True.- EMA callback
optimization_stepincremented per batch instead of per optimizer step — replaced withtrainer.global_step. - Inference client discarded predicted action chunks — without temporal aggregation, only first action was sent. Now sends
action_execution_horizonactions per inference call. - Post-training compression
validate()skipped in global mode — iterated emptyself.modulesinstead of resolved targets. DictOfTensorMixin.deviceraisedStopIterationwhenparams_dictempty — now uses_device_trackerbuffer.- DataLoader
persistent_workers=Truecrashed withnum_workers=0— now conditionally set. TemporalAggregatorcrashed withIndexErrorwhen exceedingmax_timesteps— now raisesRuntimeError.TrajectoryLengthLosszeroed padded timesteps before computing diffs, creating spurious jumps at boundaries.TrajectorySmoothnesspadding mask only checkedis_pad[:, 2:]but acceleration depends on 3 positions.DiscreteDETRActionTransformerhadrequires_actions=Truebut ignores actions — changed toFalse.SmolVLADecodermissingproprioceptive_projection = Noneinit.- Phantom batch in metrics accumulator from lazy module init — reset after dummy forward pass.
- SigLIP2 tokenizer fallback when
attention_masknot returned.
Removed¶
- Legacy encoder files:
rgb/cnn.py,rgb/swin.py,rgb/vit.py,depth/cnn.pyand their tests — superseded bySpatialRGBEncoder,FlatRGBEncoder,SpatialDepthEncoder.
[0.2.0] - 2026-04-09¶
Fixed¶
Policy.compute_losswas comparing network predictions against raw ground-truth actions instead of the algorithm-specific targets (velocity field for flow matching, noise for diffusion epsilon mode). IntroducedDecodingAlgorithm.get_targets()so each algorithm provides the correct regression target to the loss module.- Added
DecodingAlgorithm.predicts_in_action_spaceandBaseLoss.requires_action_space_targetsto detect incompatible loss-algorithm pairings at init.
Added¶
- Post-training compression pipeline (
post_training_compression/+quantization/):PostTrainingCompressororchestrates load → prepare → prune → export → quantize → save. Supports per-moduleCompressionTarget, composable pruning (unstructured + structured), PT2E quantization viaX86InductorBackend, and quantize_() API for dynamic/weight-only quantization.CompressedPolicyLoaderloads.pt2archives withtorch.compile. - Python 3.14 compatibility patch for torchao
Union.__module__assignment.
Changed¶
inference/__init__.pyandinference/policy_loading/__init__.pyno longer re-export submodules (prevents circular imports)- All consumers import from concrete modules (e.g.,
from versatil.inference.policy_loading.float_loader import PolicyLoader)
[0.1.1] - 2026-03-20¶
Migrate to Python 3.13+ and PyTorch 2.10 with CUDA 12.8.
Changed¶
- Minimum Python version raised from 3.11 to 3.13
- PyTorch upgraded to 2.10 with CUDA 12.8 (was 2.4 with CUDA 12.4)
- HuggingFace Transformers bumped to 5.x, with compatibility fixes for FAST tokenizer and SigLIP VLM encoder
- NumPy dependency bumped for Python 3.14 compatibility
- Ruff target version updated to
py313 str, enum.Enumreplaced withenum.StrEnum(PEP 659, Python 3.11+)torch.loadnow usesweights_only=Falseby default to match PyTorch 2.10 behavior- CI/CD Docker image updated to Python 3.14, pipelines now trigger only on merge requests
Removed¶
flash-attndependency — PyTorch 2.10 SDPA natively dispatches to FlashAttention kernelsFLASH_ATTENTION_2attention implementation type (replaced bySDPA)
Fixed¶
asyncio.get_event_loop()replaced withasyncio.run()for Python 3.14 compatibility in WebP codec- OpenCV dependency conflict resolved
- CI/CD pipeline no longer passes silently when unit tests fail
[0.1.0] - 2026-03-19¶
Initial release of VersatIL — a modular Imitation Learning framework for robotic manipulation.
Added¶
- Composable policy architecture: Policy = EncodingPipeline + Algorithm + Action Decoder + Loss.
- Algorithms: Behavioral Cloning, Diffusion, Flow Matching, VariationalAlgorithm (compositional variational inference wrapping any base algorithm).
- Encoders: RGB/Depth (timm backbones), Conditional CNN (FiLM), DFormerV2, Geometric RGBD, Proprioceptive (MLP), Language (HuggingFace transformers), Vision-Language (HuggingFace multimodal).
- Fusion modules: Concatenation, MLP, Attention.
- Decoder factories: ACT, Action Transformer, Conditional Action U-Net, Diffusion Action Transformer (Cross-Attention and MultiModal), Discrete-DETR, DiT-Block, Free Action Transformer, GPT Action Transformer, LACT, MoDE-ACT, MoE Decoder, MoE Free Action Transformer, Phase-ACT.
- Action heads: Single-Output, Gaussian (mean + log-variance), Mixture of Experts (MoE).
- Data pipeline: Zarr episodic store, CSV/HDF5/LeRobot raw formats, action/observation processing, image augmentation, normalization, tokenization.
- Inference: pluggable transport protocol (ZMQ), observation/action preprocessing, temporal aggregation, unified client for simulation and on-hardware.
- Training: PyTorch Lightning loop, Hydra/OmegaConf configs, WandB tracking, custom callbacks and checkpoint management.
- Losses: composable system via
nn.Modulecomposition — regression, classification, KL divergence, Sinkhorn divergence, MMD. - CI/CD: GitLab CI and GitHub Actions, unit and integration tests with >90% coverage, Ruff formatting/linting.