Migrating From 0.1.x To 0.2¶
Version 0.2.0 is an explicit pre-1.0 compatibility boundary. Keep 0.1.1 pinned until downstream extensions and recorded experiments have been validated against the new contracts.
The architecture remains
ExperimentConfig -> VariantPipeline -> VisualTower -> PolicyVariant -> ActionDecoder.
The change consolidates inference and closed-loop execution; it does not add
another trainer or require a dependency upgrade.
Inference Context And State¶
Import extension contracts through open_wam.sdk.policy.
| 0.1.x usage | 0.2 contract |
|---|---|
PolicyInferContext(extra={...}) |
Use explicit task_text, metadata, sample_seed, initial_video_noise, initial_action_noise, and request fields as appropriate. |
| Mutating a context after construction | Contexts are frozen; construct a new context or use dataclasses.replace. |
PolicyInferState(step_index=..., cache=...) |
The immutable state owns a cursor, variant state, decoder state, geometry, revision, and observed-frame boundary. Consume the returned next_state; do not synthesize a cursor from an old step counter. |
state.step_index = ... |
step_index is a read-only view of cursor.block_index. Variant/session logic publishes the advanced cursor. |
state.bind_temporal_geometry(geometry) |
Use the returned state.with_temporal_geometry(geometry); it validates rather than mutating the input. |
Arbitrary shared state.cache payloads |
Keep recurrent state in the typed variant/decoder session. Built-in feature caching is local to a denoising call, not a session-wide K/V store. |
For example, task text and row metadata are explicit batch-aligned inputs:
from open_wam.sdk.policy import PolicyInferContext
context = PolicyInferContext(
task_text=("put the mug on the plate",),
metadata=({"episode_id": 0},),
sample_seed=0,
)
This illustrates input construction, not a complete model call. A policy may
also require model-ready proprioception and resolved temporal geometry.
Do not move retired execution flags into metadata; metadata is not an
escape hatch for untyped runtime controls.
Published state tensors must also be treated as read-only: a frozen dataclass does not stop in-place tensor mutation. Observed history is committed explicitly after execution, independently of speculative predictions.
Action Decoders¶
ActionDecoder.build_rollout_plan(output) now requires an action prediction
with shape [1, steps, channels] and returns the full chunk as detached FP32
CPU actions. It rejects multiple environment rows instead of silently taking
the first, and it does not interpret aux["current_action"].
Override the hook for a custom release/slicing policy. Override
commit_rollout_plan(state, plan) by returning the new decoder state,
without modifying the input. An old override that mutates state and returns
None must be migrated, not reused unchanged.
The pipeline applies the output action mask before decoder plan hooks. Integration code converts the plan from model space into the dataset action schema and executable simulator controls. See the decoder cookbook.
Simulator Extensions¶
Import ControlCommand and ControlTransition from
open_wam.sdk.simulator; SimulatorStepResult is no longer exported.
Replace action_from_model_action(...) with
materialize_control(source_action, *, data_config) -> ControlCommand.
The input is already in the dataset's source action schema, not the raw model
output. Return both the executable action and the corresponding
source_action after any clipping/conversion. History must record what was
executed, not an unclipped prediction.
step(action) still takes the executable action array, not the command
object. It returns ControlTransition[SimulatorObservation] with separate
done, success, reward, and info fields. Do not infer success from episode
termination or label a scheduler action budget as native environment
termination. The shared engine records the budget reason separately.
Proprio-conditioned policies require finite, exact-width, model-ready
SimulatorObservation.state; native EEF/qpos conversion belongs in the
adapter. See the simulator cookbook.
Rollout Entry Points And History¶
Use scripts/run_libero_policy.py and
scripts/run_libero_policy_batch.py for source-checkout blocking LIBERO
evaluation. For fixed-rate LIBERO use scripts/run_libero_realtime_sandbox.py;
for registered simulator adapters use openwam-sim-rollout.
Consult each maintained parser rather than forwarding flags from a retired
architecture-named visualization script.
The retired LingbotExactRunner and architecture-private executors are not
compatibility aliases. Package integrations use VariantRolloutRunner with
the shared planner/lifecycle/engine; see
Extension SDK and Architecture.
Fallback-freeze/quarantine policies, including freeze_until_clean_chunk,
are removed. Actual fallback controls and observations enter canonical
history. There is no semantics-preserving flag substitution that hides those
transitions. Use blocking control when waiting without stepping is intended,
or fixed-rate execution when the simulator must keep running, and record that
scheduling choice with the result.
Numerical And Training Expectations¶
- Startup uses one observed frame with a masked action placeholder; only future predictions are returned. Cache enablement does not choose startup semantics.
- Inference honors explicit per-stream CFG and draws noise in stage order for updated modalities. The same global seed can produce a different action trace from a retired runner. Controlled numerical comparisons must also match per-modality noise, observations, guidance, and geometry.
- Parallel inference preserves its requested chunk length and configured dtype/device. It no longer interpolates a short action chunk to the training horizon or silently converts the model to BF16. Training decoding is unchanged.
inference.use_cache=truereuses dependency-invariant features within a denoising call. It does not promise persistent full-prefix equivalence. The maintained causal chunk-conditioned preset keeps caching off; explicit cache-on use needs checkpoint/task validation.trainer.strategy=fsdpnow applies with one worker, including mixed precision and optional CPU offload. To preserve an older one-rank unwrapped run, explicitly selecttrainer.strategy=single_device. Check training resume and numerics before changing strategies. Worker count and effective batch size remain launcher/config responsibilities.- Explicit
trainer.accelerator=cpuFSDP uses a CPU mesh even when CUDA is visible. This is separate from GPU FSDP's optional CPU offload, which keeps its CUDA compute mesh.
This release does not introduce a new weight format or require tensor conversion solely for the execution refactor. That is not a guarantee of arbitrary old checkpoint/config compatibility or identical rollouts. Retain strict checkpoint loading, inspect its compatibility report, and test full-state resume separately from weight initialization.
Version 0.2.0 retains training recipes and third-party dependency pins. The inference and FSDP changes above still require validation before resuming an existing experiment.
Upgrade Checklist¶
- Preserve the old environment, checkpoint, resolved config, seed, and baseline artifacts before changing versions.
- Migrate SDK extensions and launchers using the contracts above; validate authored configs and checkpoint loading without partial-load bypasses.
- Run one forward/backward update and full-state save/resume for training integrations, plus a complete representative checkpoint rollout.
- Record output geometry, execution budgets, renderer, success, action traces, and resolved guidance. Do not interpret an import or tiny-model pass as unchanged benchmark success.
- Use the corresponding source revision and frozen lock for characterization; a wheel install resolves allowed dependency ranges instead.
This release does not claim new task-success rates or universal old/new bitwise parity. See Compatibility, Testing, and Releases. Deferred upgrades leave existing, expiring dependency-risk exceptions in force; they do not fix the vulnerabilities.