Convert policy.json to the Rho format and remove RhoAlpha tensor aliases
This PR fixes https://github.com/microsoft/rhobotics/issues/54 for this checkpoint.
Problem
policy.json declares "type": "phi4mm_tactile" (with "name": "rhoalpha"), a policy type that the current rhobotics code no longer registers. Evaluating or serving this checkpoint directly fails while its config is read:
draccus.utils.DecodingError: Couldn't find a choice class for 'phi4mm_tactile' in <class 'rho.policies.base.PolicyConfig'>
Fine-tuning from this checkpoint is unaffected, because training builds the policy from the training YAML and loads only the weights. Checkpoints fine-tuned from it are also unaffected, because they store their own "type": "rho" config.
Change
Two metadata files change; the weight files do not.
policy.json is converted to the Rho format that microsoft/rho-fr3-duo already uses:
typeandnameare set torho.- 48 RhoAlpha-only settings are removed (listed below).
RhoConfighas none of these fields, and the loader already discarded them. - The
namekey insidelr_scheduleris removed; it duplicatestype. "pretrained_repo_id": "microsoft/rho-base"is added. This isRhoConfig's default, so loading behaves the same either way; it is included so that the file has the same fields asrho-fr3-duo's.
All other values are unchanged. The weights already use the Rho layout: all 964 tensors match microsoft/rho-base in name, shape and dtype.
model.safetensors.index.json loses 651 model.text_output_model.* entries from its metadata. They are aliases left over from RhoAlpha's text-output head, each pointing to a tensor that is stored under its model.flow_model.* name. The rhobotics loader currently restores these aliases and then drops them again, logging "Dropped 651 non-Rho keys while converting RhoAlpha weights", so loading depends on RhoAlpha compatibility code. The weight map is unchanged. The only other edit is the trailing comma after rho_version, which is now the last metadata entry. No other Rho checkpoint (rho-base, rho-fr3-duo, rho-libero, rho-roboeval) has such aliases.
Verification
Tested with rhobotics main at fd9cc54:
load_configs_from_checkpointreads the config asRhoConfig. The decoded config matchesrho-fr3-duo's except fornum_flow_samples(1 vs. 8), which only affects training.- Following the serving code path (
EvalConfig,make_policy,load_from_pretrained,PolicyInterface.get_action_chunk) withflash_attention_2, all weights load under strict key checking, and the policy returns finite(1, 50, 20)action chunks that are identical across repeated calls. - With the new index, loading no longer drops any keys, and the action chunks are bit-identical to those produced with the original index for the same inputs and noise.
Not in scope
This checkpoint's stats.json and data_config.json are copies of rho-base's. That is tracked separately in https://github.com/microsoft/rhobotics/issues/53. Until it is fixed, actions decoded with the shipped statistics are not correctly scaled; for example, gripper values fall outside [0, 1].
Removed policy.json settings (48)
action_lora_alpha, action_lora_dropout, action_lora_end, action_lora_init_from_scratch, action_lora_modules, action_lora_r, action_lora_start, add_separator_tokens, baku_weight_init, combine_action_tactile_head, drop_n_last_frames, dynamic_hd, empty_cameras, endstate_target_format, endstate_target_prefix, endstate_target_rotation, endstate_target_units, freeze_action_lora, freeze_vision_projector, freeze_vision_transformer, knowledge_insulation_alpha, language_action_chunk_reduction, language_action_eef_frame_prob, language_action_include_rotation, max_tactile_dim, merge_vision_lora, monkeypatch_siglip_encoder, robot_hz, scheduler_name, tactile_encoder, tactile_head_loss, tactile_history_length, tactile_history_time, tactile_loss_beta, tactile_mask, tokenizer_max_length, training_modes, use_action_lora, use_cache, use_delta_joint_actions_aloha, use_full_causal_mask, use_hd_transform, use_tactile_head, use_tactile_history, vl_lm_max_length, vl_loss_weight, vlm_backend, vlm_model_name