RL Checkpoint (trained actor)¶
create_policy("rl", checkpoint_dir=...) returns an RLCheckpointPolicy - the
deterministic actor from a reinforcement-learning run, presented as an ordinary
Policy. It is the inference half of
Reinforcement Learning: create_trainer("ppo") (or
fast_sac / fast_td3) writes policy.pt + policy_meta.json, and this
provider rolls that pair out.
from strands_robots import Robot, create_policy
from strands_robots.training import create_trainer
result = create_trainer("ppo").train(spec) # -> result.checkpoint_dir
sim = Robot("so101", mode="sim")
sim.run_policy(
robot_name="so101",
policy_provider="rl",
policy_config={"checkpoint_dir": result.checkpoint_dir},
duration=10.0,
)
checkpoint_dir is spelled as the trainer spells it (TrainResult.checkpoint_dir,
BaseRLAlgo.load_checkpoint, latest_checkpoint), so the value a caller already
holds is the value this provider takes.
| Config key | Default | Meaning |
|---|---|---|
checkpoint_dir |
- | Directory holding policy.pt + policy_meta.json (required) |
device |
cpu |
Torch device to load the actor onto |
What the checkpoint decides¶
policy_meta.json is read, not guessed. It carries the vocabularies and the
network shape, and each one is load-bearing:
providerselects the actor architecture. The three backends do not share one network: PPO's actor emitsnum_actionsraw Gaussian means, FastTD3's emitsnum_actionsthrough atanh, and FastSAC's emits2 * num_actions(a mean/log-std pair) and squashes the mean. All three recordnum_actions, so the output width is not derivable from the metadata alone. The actor is rebuilt through the backend's ownbuild_actor_criticand driven through its ownact_inference, so the deployed graph is the one that was trained.actor_obs_keysare read from the observation by name, in the trained order - that order is part of the weights. A reshuffled observation dict gives the same action; a key the observation does not carry is refused, because substituting a zero would command the robot from a state it is not in.action_keysname the actuators the outputs drive - the robot'srobot_action_keys, not its joint list. They win overset_robot_state_keys, which is the fallback for a checkpoint saved without a robot bound. An actor whose width does not match the bound keys is refused rather than silently dropping a command.
The observation normalizer saved beside the weights is restored in eval mode, so
the statistics the run finished on are frozen: EmpiricalNormalization only
folds a batch while training, and a rollout that kept updating would drift the
whitening the trained weights expect.
Actions are one tick per call - an RL actor is a per-step controller trained on
the state it is given, so it has no horizon to predict over. instruction is
ignored: the actor was trained against a reward function, not language.
Needs torch, which the RL trainers already require; no extra beyond them.
Reading a checkpoint's actor without the policy wrapper is
strands_robots.training.rl.load_deployable_actor(checkpoint_dir).