dongqianyu99 commited on
Commit
6835450
·
verified ·
1 Parent(s): ba7e4f3

Publish completed deadly_corridor QwenOFT H1 mean-profile 5000-update run

Browse files
Files changed (28) hide show
  1. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/README.md +8 -0
  2. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/checkpoints/model.pt +3 -0
  3. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/collection_quality_report.json +14 -0
  4. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/config.full.yaml +276 -0
  5. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/config.yaml +45 -0
  6. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/dataset_statistics.json +805 -0
  7. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/dataset_statistics_eval.json +805 -0
  8. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/files.sha256.json +110 -0
  9. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/latency_prompt_map.json +7 -0
  10. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/launch_audit.json +35 -0
  11. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/manifest.json +404 -0
  12. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/profile.source.json +66 -0
  13. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/provenance.json +118 -0
  14. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/startup_verified.json +64 -0
  15. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/summary.jsonl +10 -0
  16. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/task_contract.json +62 -0
  17. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/QWen3.py +444 -0
  18. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/QwenOFT.py +1244 -0
  19. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/datasets.py +0 -0
  20. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/doom-mean-reset.patch +192 -0
  21. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/gym-language-contract.patch +17 -0
  22. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/loader-spawn-cache.patch +18 -0
  23. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/loader-spawn-test.patch +31 -0
  24. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/mean-profile-preparation.patch +147 -0
  25. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/train_starvla.py +0 -0
  26. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/trainer_tools.py +736 -0
  27. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/worker_context.py +77 -0
  28. latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training_results.json +17 -0
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/README.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # deadly_corridor QwenOFT H1 mean-profile VLA
2
+
3
+ Training complete:5000 optimizer updates, seed42, globalbatch128, microbatch64 perGPU, accumulation1, gradientcheckpointingTrue, BF16/ZeRO2. Hardware:2 RTX PRO6000 Blackwell GPUs. Fixed mean73.69250777493353ms uses originalRTX3090 profile; all actual science/runtime settings and user-authorized throughput changes are recorded in config.full.yaml/launch_audit.json. Horizon1, native state/action dimensions120/7.
4
+
5
+ Puretensor weights checkCPUweights_only/allfinite passed. Portable inferenceconfig, normalization/statistics, taskcontract, sourcecode/profile/data provenance included. Full optimizer recovery remains local. Finalofflinevalidation loss0.020563077181577682; this is not closed-loop task-performance acceptance. Latency-bench evaluation pending until all four models finish.
6
+
7
+ Dataset:https://huggingface.co/datasets/latency-sensitive-bench/Standard-Pipeline/tree/f33126deefb1d4819a338281cfd4b6db07c8029b/deadly_corridor/profile_latency/QwenOFT/mean_rtx3090_s42_8500ep_v1
8
+ Training:https://wandb.ai/dongqianyu99-zhejiang-university/starvla_tasks/runs/mean3090-deadly_corridor-vla-blackwell-20260930
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/checkpoints/model.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a756924b1f9a93cc4f278e03535dd61535977037f9484957672336e6b9c9265c
3
+ size 9785680289
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/collection_quality_report.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "task": "deadly_corridor",
3
+ "teacher_checkpoint": "/home/ubuntu/lzj/mean-profiling/deadly_corridor/teacher-publication/checkpoint.pth",
4
+ "teacher_sha256": "e631e9017634f799860c581761b5fa48601109393c11d20a35187c6f75d14b88",
5
+ "episodes": 8500,
6
+ "train_episodes": 7650,
7
+ "val_episodes": 850,
8
+ "train_rows": 313925,
9
+ "val_rows": 34465,
10
+ "fixed_latency_ms": 73.69250777493353,
11
+ "action_horizon": 1,
12
+ "unique_seeds": 8500,
13
+ "state_dim": 120
14
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/config.full.yaml ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ framework:
2
+ name: QwenOFT
3
+ qwenvl:
4
+ base_vlm: /home/ubuntu/lzj/models/Qwen3-VL-4B-Instruct
5
+ attn_implementation: flash_attention_2
6
+ enable_gradient_checkpointing: true
7
+ action_model:
8
+ action_model_type: MLP
9
+ action_dim: 7
10
+ state_dim: 120
11
+ action_hidden_dim: 2560
12
+ future_action_window_size: 0
13
+ past_action_window_size: 0
14
+ loss_type: multibinary_bce
15
+ state_encoding: continuous_projector
16
+ task_objective: null
17
+ action_horizon: 1
18
+ action_env_dim: 7
19
+ kv_memory:
20
+ enabled: false
21
+ window: 4
22
+ rollout_len: 8
23
+ packed_train: false
24
+ rebased_sink: true
25
+ datasets:
26
+ vla_data:
27
+ dataset_py: lerobot_datasets
28
+ include_state: true
29
+ data_root_dir: /home/ubuntu/lzj/mean-profiling/deadly_corridor/data
30
+ data_mix: lerobot
31
+ eval_data_mix: lerobot__val
32
+ custom_mixtures_path: /home/ubuntu/lzj/mean-profiling/deadly_corridor/data/_generated_mixtures/lerobot.json
33
+ action_type: discrete
34
+ sequential_step_sampling: false
35
+ eval_sequential_step_sampling: null
36
+ num_workers: 2
37
+ eval_num_workers: 2
38
+ prefetch_factor: 4
39
+ persistent_workers: true
40
+ pin_memory: true
41
+ shuffle: true
42
+ action_balance:
43
+ enabled: false
44
+ strategy: balanced_epoch
45
+ action_key: action_id
46
+ target_flap_fraction: 0.3
47
+ noop_id: 0
48
+ flap_id: 1
49
+ latency_curriculum:
50
+ enabled: false
51
+ strategy: exclusive
52
+ latencies: null
53
+ phase_steps: null
54
+ phase_distributions: null
55
+ new_latency_passes: 1.0
56
+ replay_passes: 0.25
57
+ target_total_passes: 2.0
58
+ final_equalization: true
59
+ step_budget_mode: auto
60
+ eval_at_phase_end: false
61
+ save_at_phase_end: false
62
+ computed_plan: null
63
+ per_device_batch_size: 64
64
+ load_all_data_for_training: true
65
+ num_obs_frames: 1
66
+ image_mode: single
67
+ prompt_mode: raw
68
+ stitch_grid:
69
+ - 2
70
+ - 2
71
+ obs_image_size: null
72
+ video_backend: torchvision_av
73
+ dataset:
74
+ source_hf: ''
75
+ config_name: null
76
+ source_subdir: null
77
+ converted_name: deadly_corridor_train
78
+ single_source_hf: ''
79
+ mixed_source_hf: ''
80
+ single_converted_name: deadly_corridor_train
81
+ mixed_converted_name: deadly_corridor_mixed_latency_train
82
+ single_latency_filter: null
83
+ mixed_latency_filter: null
84
+ force_download: false
85
+ setup_force: false
86
+ skip_verification: false
87
+ target_latency_unit: observation_steps
88
+ verify_rows: 200
89
+ max_episodes: null
90
+ episodes_per_latency: null
91
+ latency_filter: null
92
+ debug_subset:
93
+ enabled: false
94
+ max_episodes: 5
95
+ suffix: debug
96
+ base_model:
97
+ repo_id: Qwen/Qwen3-VL-4B-Instruct
98
+ initialization:
99
+ checkpoint_local_dir: null
100
+ checkpoint_hf_repo_id: null
101
+ checkpoint_filename: null
102
+ trainer:
103
+ max_train_steps: 5000
104
+ num_warmup_steps: 100
105
+ save_interval: 500
106
+ eval_interval: 500
107
+ eval_num_batches: 50
108
+ per_latency_eval_num_batches: null
109
+ eval_action_classification: false
110
+ eval_action_classification_interval: null
111
+ cc_f1_tolerance: 1
112
+ learning_rate:
113
+ base: 3.0e-05
114
+ qwen_vl_interface: 3.0e-06
115
+ action_model: 0.0001
116
+ lr_scheduler_type: cosine_with_min_lr
117
+ scheduler_specific_kwargs:
118
+ min_lr_rate: 0.03333333333333333
119
+ freeze_modules: ''
120
+ freeze_vit: false
121
+ freeze_tied_embedding: false
122
+ freeze_llm_layers: []
123
+ loss_scale:
124
+ vla: 1.0
125
+ vlm: 0.0
126
+ max_grad_norm: 1.0
127
+ weight_decay: 0.0
128
+ logging_frequency: 1
129
+ profile_timing:
130
+ enabled: false
131
+ log_interval: 10
132
+ gradient_clipping: 1.0
133
+ gradient_accumulation_steps: 1
134
+ distributed_backend: deepspeed
135
+ is_resume: false
136
+ pretrained_checkpoint: null
137
+ resume_step: 0
138
+ reload_modules: null
139
+ optimizer:
140
+ name: AdamW
141
+ betas:
142
+ - 0.9
143
+ - 0.95
144
+ eps: 1.0e-08
145
+ weight_decay: 1.0e-08
146
+ fused: true
147
+ save_format: pt
148
+ hist8_diagnostics:
149
+ steps:
150
+ - 0
151
+ - 500
152
+ - 1000
153
+ - 2500
154
+ - 5000
155
+ sample_count: 2048
156
+ noise_seeds:
157
+ - 1729
158
+ sample_seed: 42
159
+ batch_size: 8
160
+ bootstrap_repeats: 4000
161
+ workspace_dir: WORKSPACE_DIR
162
+ run_root_dir: /home/ubuntu/lzj/mean-profiling/deadly_corridor/vla
163
+ seed: 42
164
+ wandb_entity: dongqianyu99-zhejiang-university
165
+ wandb_project: starvla_tasks
166
+ auth:
167
+ env_file: null
168
+ hf_token_env: HF_TOKEN
169
+ wandb_api_key_env: WANDB_API_KEY
170
+ paths:
171
+ run_root_dir: results/Checkpoints
172
+ dataset_local_dir: playground/Datasets/rl_games
173
+ dataset_cache_dir: null
174
+ base_model_dir: /home/ubuntu/lzj/models/Qwen3-VL-4B-Instruct
175
+ accelerate_config: starVLA/config/deepseeds/deepspeed_zero2.yaml
176
+ launch:
177
+ use_accelerate: true
178
+ gpus: null
179
+ num_processes: 1
180
+ dry_run: false
181
+ conda:
182
+ enabled: true
183
+ env_name: null
184
+ rl_games:
185
+ model_alias: openvla
186
+ env_eval:
187
+ image_size: 224
188
+ frameskip: 4
189
+ image_transform: raw_rgb
190
+ prompt_mode: raw
191
+ ghost_trail:
192
+ history_frames: 5
193
+ gamma: 1.3
194
+ min_alpha: 35
195
+ scroll_px_per_step: 4.0
196
+ ground_fraction: 0.22
197
+ seed: 42
198
+ fixed_episode_seeds: true
199
+ latency_seed_stride: 0
200
+ task_seed_stride: 0
201
+ task_description: You are playing Deadly Corridor in VizDoom. Choose actions from
202
+ MOVE_FORWARD, MOVE_BACKWARD, MOVE_LEFT, MOVE_RIGHT, TURN_LEFT, TURN_RIGHT, ATTACK.
203
+ eval_parallel_envs: 5
204
+ action_chunk_execution:
205
+ enabled: false
206
+ chunk_size: null
207
+ deadly:
208
+ action_layout: multibinary_7
209
+ multibinary_threshold: null
210
+ enabled: false
211
+ eval_backend: latency_bench
212
+ distributed_mode: none
213
+ vectorized:
214
+ enabled: false
215
+ batch_size: 1
216
+ latency:
217
+ prompt_map_path: null
218
+ mode: single
219
+ values:
220
+ - 0
221
+ mid_train:
222
+ enabled: false
223
+ interval_steps: 100
224
+ latencies:
225
+ - 0
226
+ num_episodes: 5
227
+ max_steps_per_episode: 3600
228
+ post_train:
229
+ enabled: false
230
+ latencies:
231
+ - 0
232
+ - 1
233
+ - 2
234
+ - 3
235
+ - 4
236
+ num_episodes: 5
237
+ max_steps_per_episode: 3600
238
+ task: deadly_corridor
239
+ deadly_corridor_loss_type: null
240
+ initialization_mode: scratch
241
+ action_carrier: native
242
+ model: openvla
243
+ env: deadly_corridor
244
+ init: scratch
245
+ mode: single
246
+ checkpoint:
247
+ load: none
248
+ hf_repo_id: null
249
+ save_best_model: false
250
+ save_final_model: true
251
+ save_pt_file: true
252
+ save_training_state: true
253
+ save_safetensors_file: false
254
+ local:
255
+ keep_last_n: 2
256
+ sync:
257
+ enabled: false
258
+ repo_id: null
259
+ keep_last_n: 0
260
+ sync_every_n_checkpoints: 1
261
+ resume_policy: local_latest
262
+ run_id: deadly_corridor-qwenoft-mean-3090-s42
263
+ output_dir: /home/ubuntu/lzj/mean-profiling/deadly_corridor/vla/deadly_corridor-qwenoft-mean-3090-s42
264
+ config_yaml: /home/ubuntu/lzj/mean-profiling/deadly_corridor/vla.yaml
265
+ is_debug: false
266
+ version_id: '0.21'
267
+ wandb_name: deadly_corridor-qwenoft-mean-3090-s42
268
+ wandb_group: mean-profiling-3090-blackwell
269
+ wandb_tags:
270
+ - deadly_corridor
271
+ - qwenoft
272
+ - hist8-v2
273
+ - history01
274
+ - scratch
275
+ - profile-latency
276
+ training_latency_condition: mean-profile
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/config.yaml ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ framework:
2
+ name: QwenOFT
3
+ qwenvl:
4
+ base_vlm: Qwen/Qwen3-VL-4B-Instruct
5
+ attn_implementation: flash_attention_2
6
+ enable_gradient_checkpointing: true
7
+ action_model:
8
+ action_model_type: MLP
9
+ action_dim: 7
10
+ state_dim: 120
11
+ action_hidden_dim: 2560
12
+ future_action_window_size: 0
13
+ past_action_window_size: 0
14
+ loss_type: multibinary_bce
15
+ state_encoding: continuous_projector
16
+ task_objective: null
17
+ action_horizon: 1
18
+ action_env_dim: 7
19
+ kv_memory:
20
+ enabled: false
21
+ window: 4
22
+ rollout_len: 8
23
+ packed_train: false
24
+ rebased_sink: true
25
+ version_id: '0.21'
26
+ datasets:
27
+ vla_data:
28
+ include_state: true
29
+ obs_image_size: null
30
+ image_mode: single
31
+ stitch_grid:
32
+ - 2
33
+ - 2
34
+ num_obs_frames: 1
35
+ trainer:
36
+ pretrained_checkpoint: null
37
+ backbone:
38
+ repo_id: Qwen/Qwen3-VL-4B-Instruct
39
+ revision: ebb281ec70b05090aa6165b016eac8ec08e71b17
40
+ allow_patterns:
41
+ - '*.json'
42
+ - '*.safetensors'
43
+ - '*.txt'
44
+ - '*.jinja'
45
+ - '*.model'
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/dataset_statistics.json ADDED
@@ -0,0 +1,805 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "new_embodiment": {
3
+ "action": {
4
+ "mean": [
5
+ 0.9897363781929016,
6
+ 0.0,
7
+ 0.14210718870162964,
8
+ 0.6669108867645264,
9
+ 0.2289145439863205,
10
+ 0.10847176611423492,
11
+ 0.7685338854789734
12
+ ],
13
+ "std": [
14
+ 0.10063733160495758,
15
+ 0.0,
16
+ 0.34875211119651794,
17
+ 0.47094491124153137,
18
+ 0.4195047914981842,
19
+ 0.31092607975006104,
20
+ 0.42183926701545715
21
+ ],
22
+ "max": [
23
+ 1.0,
24
+ 0.0,
25
+ 1.0,
26
+ 1.0,
27
+ 1.0,
28
+ 1.0,
29
+ 1.0
30
+ ],
31
+ "min": [
32
+ 0.0,
33
+ 0.0,
34
+ 0.0,
35
+ 0.0,
36
+ 0.0,
37
+ 0.0,
38
+ 0.0
39
+ ],
40
+ "q01": [
41
+ 0.0,
42
+ 0.0,
43
+ 0.0,
44
+ 0.0,
45
+ 0.0,
46
+ 0.0,
47
+ 0.0
48
+ ],
49
+ "q99": [
50
+ 1.0,
51
+ 0.0,
52
+ 1.0,
53
+ 1.0,
54
+ 1.0,
55
+ 1.0,
56
+ 1.0
57
+ ],
58
+ "mask": [
59
+ true,
60
+ true,
61
+ true,
62
+ true,
63
+ true,
64
+ true,
65
+ true
66
+ ]
67
+ },
68
+ "state": {
69
+ "mean": [
70
+ 0.8055841326713562,
71
+ 0.17911602556705475,
72
+ 0.08755913376808167,
73
+ 0.7956868410110474,
74
+ 0.0,
75
+ 0.13805526494979858,
76
+ 0.4818730652332306,
77
+ 0.6388723254203796,
78
+ 0.17911602556705475,
79
+ 0.08755913376808167,
80
+ 0.7956868410110474,
81
+ 0.0,
82
+ 0.13805526494979858,
83
+ 0.4818730652332306,
84
+ 0.6388723254203796,
85
+ 0.8298032879829407,
86
+ 0.1822887659072876,
87
+ 0.08801146596670151,
88
+ 0.8198900818824768,
89
+ 0.0,
90
+ 0.1383451521396637,
91
+ 0.5053499937057495,
92
+ 0.6508943438529968,
93
+ 0.1822887659072876,
94
+ 0.08801146596670151,
95
+ 0.8198900818824768,
96
+ 0.0,
97
+ 0.1383451521396637,
98
+ 0.5053499937057495,
99
+ 0.6508943438529968,
100
+ 0.8540224432945251,
101
+ 0.18232062458992004,
102
+ 0.08829497545957565,
103
+ 0.8440997004508972,
104
+ 0.0,
105
+ 0.13869555294513702,
106
+ 0.528728187084198,
107
+ 0.6671115756034851,
108
+ 0.18232062458992004,
109
+ 0.08829497545957565,
110
+ 0.8440997004508972,
111
+ 0.0,
112
+ 0.13869555294513702,
113
+ 0.528728187084198,
114
+ 0.6671115756034851,
115
+ 0.8782415986061096,
116
+ 0.18242254853248596,
117
+ 0.08874731510877609,
118
+ 0.8683188557624817,
119
+ 0.0,
120
+ 0.13913513720035553,
121
+ 0.5520139932632446,
122
+ 0.6807518005371094,
123
+ 0.18242254853248596,
124
+ 0.08874731510877609,
125
+ 0.8683188557624817,
126
+ 0.0,
127
+ 0.13913513720035553,
128
+ 0.5520139932632446,
129
+ 0.6807518005371094,
130
+ 0.9025340676307678,
131
+ 0.1839197278022766,
132
+ 0.08997690677642822,
133
+ 0.892608106136322,
134
+ 0.0,
135
+ 0.1396416276693344,
136
+ 0.575299859046936,
137
+ 0.6965198516845703,
138
+ 0.1839197278022766,
139
+ 0.08997690677642822,
140
+ 0.892608106136322,
141
+ 0.0,
142
+ 0.1396416276693344,
143
+ 0.575299859046936,
144
+ 0.6965198516845703,
145
+ 0.9268933534622192,
146
+ 0.19009636342525482,
147
+ 0.09329298138618469,
148
+ 0.9169578552246094,
149
+ 0.0,
150
+ 0.14013856649398804,
151
+ 0.5985760688781738,
152
+ 0.7158270478248596,
153
+ 0.19009636342525482,
154
+ 0.09329298138618469,
155
+ 0.9169578552246094,
156
+ 0.0,
157
+ 0.14013856649398804,
158
+ 0.5985760688781738,
159
+ 0.7158270478248596,
160
+ 0.9512622356414795,
161
+ 0.20292745530605316,
162
+ 0.0966855138540268,
163
+ 0.9412598609924316,
164
+ 0.0,
165
+ 0.1407342553138733,
166
+ 0.6217217445373535,
167
+ 0.7305694222450256,
168
+ 0.20292745530605316,
169
+ 0.0966855138540268,
170
+ 0.9412598609924316,
171
+ 0.0,
172
+ 0.1407342553138733,
173
+ 0.6217217445373535,
174
+ 0.7305694222450256,
175
+ 0.9756311178207397,
176
+ 0.21536991000175476,
177
+ 0.10258501023054123,
178
+ 0.9655013084411621,
179
+ 0.0,
180
+ 0.14144141972064972,
181
+ 0.6445552110671997,
182
+ 0.7461718320846558,
183
+ 0.21536991000175476,
184
+ 0.10258501023054123,
185
+ 0.9655013084411621,
186
+ 0.0,
187
+ 0.14144141972064972,
188
+ 0.6445552110671997,
189
+ 0.7461718320846558
190
+ ],
191
+ "std": [
192
+ 0.3959074020385742,
193
+ 0.38303840160369873,
194
+ 0.2828328013420105,
195
+ 0.4033564329147339,
196
+ 0.0,
197
+ 0.34534159302711487,
198
+ 0.49943462014198303,
199
+ 0.4797308146953583,
200
+ 0.38303840160369873,
201
+ 0.2828328013420105,
202
+ 0.4033564329147339,
203
+ 0.0,
204
+ 0.34534159302711487,
205
+ 0.49943462014198303,
206
+ 0.4797308146953583,
207
+ 0.375529021024704,
208
+ 0.38657844066619873,
209
+ 0.28343474864959717,
210
+ 0.38407179713249207,
211
+ 0.0,
212
+ 0.3455885350704193,
213
+ 0.49999451637268066,
214
+ 0.4761778712272644,
215
+ 0.38657844066619873,
216
+ 0.28343474864959717,
217
+ 0.38407179713249207,
218
+ 0.0,
219
+ 0.3455885350704193,
220
+ 0.49999451637268066,
221
+ 0.4761778712272644,
222
+ 0.3528599739074707,
223
+ 0.3866046071052551,
224
+ 0.28378376364707947,
225
+ 0.36217108368873596,
226
+ 0.0,
227
+ 0.3459450602531433,
228
+ 0.499480277299881,
229
+ 0.4708371162414551,
230
+ 0.3866046071052551,
231
+ 0.28378376364707947,
232
+ 0.36217108368873596,
233
+ 0.0,
234
+ 0.3459450602531433,
235
+ 0.499480277299881,
236
+ 0.4708371162414551,
237
+ 0.32749050855636597,
238
+ 0.3866473138332367,
239
+ 0.284260094165802,
240
+ 0.3381800651550293,
241
+ 0.0,
242
+ 0.34623581171035767,
243
+ 0.4972201883792877,
244
+ 0.4661324620246887,
245
+ 0.3866473138332367,
246
+ 0.284260094165802,
247
+ 0.3381800651550293,
248
+ 0.0,
249
+ 0.34623581171035767,
250
+ 0.4972201883792877,
251
+ 0.4661324620246887,
252
+ 0.2968117594718933,
253
+ 0.3875378370285034,
254
+ 0.2858831584453583,
255
+ 0.30985113978385925,
256
+ 0.0,
257
+ 0.34660419821739197,
258
+ 0.49394044280052185,
259
+ 0.46013525128364563,
260
+ 0.3875378370285034,
261
+ 0.2858831584453583,
262
+ 0.30985113978385925,
263
+ 0.0,
264
+ 0.34660419821739197,
265
+ 0.49394044280052185,
266
+ 0.46013525128364563,
267
+ 0.26024550199508667,
268
+ 0.39244508743286133,
269
+ 0.2904002070426941,
270
+ 0.27631235122680664,
271
+ 0.0,
272
+ 0.3470449149608612,
273
+ 0.49046778678894043,
274
+ 0.4512428343296051,
275
+ 0.39244508743286133,
276
+ 0.2904002070426941,
277
+ 0.27631235122680664,
278
+ 0.0,
279
+ 0.3470449149608612,
280
+ 0.49046778678894043,
281
+ 0.4512428343296051,
282
+ 0.21497759222984314,
283
+ 0.4028102159500122,
284
+ 0.29600071907043457,
285
+ 0.23558039963245392,
286
+ 0.0,
287
+ 0.34749558568000793,
288
+ 0.4850335419178009,
289
+ 0.4443678557872772,
290
+ 0.4028102159500122,
291
+ 0.29600071907043457,
292
+ 0.23558039963245392,
293
+ 0.0,
294
+ 0.34749558568000793,
295
+ 0.4850335419178009,
296
+ 0.4443678557872772,
297
+ 0.15395309031009674,
298
+ 0.41143739223480225,
299
+ 0.3030264377593994,
300
+ 0.18218672275543213,
301
+ 0.0,
302
+ 0.34799501299858093,
303
+ 0.47797465324401855,
304
+ 0.4346904754638672,
305
+ 0.41143739223480225,
306
+ 0.3030264377593994,
307
+ 0.18218672275543213,
308
+ 0.0,
309
+ 0.34799501299858093,
310
+ 0.47797465324401855,
311
+ 0.4346904754638672
312
+ ],
313
+ "max": [
314
+ 1.0,
315
+ 1.0,
316
+ 1.0,
317
+ 1.0,
318
+ 1.0,
319
+ 1.0,
320
+ 1.0,
321
+ 1.0,
322
+ 1.0,
323
+ 1.0,
324
+ 1.0,
325
+ 1.0,
326
+ 1.0,
327
+ 1.0,
328
+ 1.0,
329
+ 1.0,
330
+ 1.0,
331
+ 1.0,
332
+ 1.0,
333
+ 1.0,
334
+ 1.0,
335
+ 1.0,
336
+ 1.0,
337
+ 1.0,
338
+ 1.0,
339
+ 1.0,
340
+ 1.0,
341
+ 1.0,
342
+ 1.0,
343
+ 1.0,
344
+ 1.0,
345
+ 1.0,
346
+ 1.0,
347
+ 1.0,
348
+ 1.0,
349
+ 1.0,
350
+ 1.0,
351
+ 1.0,
352
+ 1.0,
353
+ 1.0,
354
+ 1.0,
355
+ 1.0,
356
+ 1.0,
357
+ 1.0,
358
+ 1.0,
359
+ 1.0,
360
+ 1.0,
361
+ 1.0,
362
+ 1.0,
363
+ 1.0,
364
+ 1.0,
365
+ 1.0,
366
+ 1.0,
367
+ 1.0,
368
+ 1.0,
369
+ 1.0,
370
+ 1.0,
371
+ 1.0,
372
+ 1.0,
373
+ 1.0,
374
+ 1.0,
375
+ 1.0,
376
+ 1.0,
377
+ 1.0,
378
+ 1.0,
379
+ 1.0,
380
+ 1.0,
381
+ 1.0,
382
+ 1.0,
383
+ 1.0,
384
+ 1.0,
385
+ 1.0,
386
+ 1.0,
387
+ 1.0,
388
+ 1.0,
389
+ 1.0,
390
+ 1.0,
391
+ 1.0,
392
+ 1.0,
393
+ 1.0,
394
+ 1.0,
395
+ 1.0,
396
+ 1.0,
397
+ 1.0,
398
+ 1.0,
399
+ 1.0,
400
+ 1.0,
401
+ 1.0,
402
+ 1.0,
403
+ 1.0,
404
+ 1.0,
405
+ 1.0,
406
+ 1.0,
407
+ 1.0,
408
+ 1.0,
409
+ 1.0,
410
+ 1.0,
411
+ 1.0,
412
+ 1.0,
413
+ 1.0,
414
+ 1.0,
415
+ 1.0,
416
+ 1.0,
417
+ 1.0,
418
+ 1.0,
419
+ 1.0,
420
+ 1.0,
421
+ 1.0,
422
+ 1.0,
423
+ 1.0,
424
+ 1.0,
425
+ 1.0,
426
+ 1.0,
427
+ 1.0,
428
+ 1.0,
429
+ 1.0,
430
+ 1.0,
431
+ 1.0,
432
+ 1.0,
433
+ 1.0
434
+ ],
435
+ "min": [
436
+ 0.0,
437
+ 0.0,
438
+ 0.0,
439
+ 0.0,
440
+ 0.0,
441
+ 0.0,
442
+ 0.0,
443
+ 0.0,
444
+ 0.0,
445
+ 0.0,
446
+ 0.0,
447
+ 0.0,
448
+ 0.0,
449
+ 0.0,
450
+ 0.0,
451
+ 0.0,
452
+ 0.0,
453
+ 0.0,
454
+ 0.0,
455
+ 0.0,
456
+ 0.0,
457
+ 0.0,
458
+ 0.0,
459
+ 0.0,
460
+ 0.0,
461
+ 0.0,
462
+ 0.0,
463
+ 0.0,
464
+ 0.0,
465
+ 0.0,
466
+ 0.0,
467
+ 0.0,
468
+ 0.0,
469
+ 0.0,
470
+ 0.0,
471
+ 0.0,
472
+ 0.0,
473
+ 0.0,
474
+ 0.0,
475
+ 0.0,
476
+ 0.0,
477
+ 0.0,
478
+ 0.0,
479
+ 0.0,
480
+ 0.0,
481
+ 0.0,
482
+ 0.0,
483
+ 0.0,
484
+ 0.0,
485
+ 0.0,
486
+ 0.0,
487
+ 0.0,
488
+ 0.0,
489
+ 0.0,
490
+ 0.0,
491
+ 0.0,
492
+ 0.0,
493
+ 0.0,
494
+ 0.0,
495
+ 0.0,
496
+ 0.0,
497
+ 0.0,
498
+ 0.0,
499
+ 0.0,
500
+ 0.0,
501
+ 0.0,
502
+ 0.0,
503
+ 0.0,
504
+ 0.0,
505
+ 0.0,
506
+ 0.0,
507
+ 0.0,
508
+ 0.0,
509
+ 0.0,
510
+ 0.0,
511
+ 0.0,
512
+ 0.0,
513
+ 0.0,
514
+ 0.0,
515
+ 0.0,
516
+ 0.0,
517
+ 0.0,
518
+ 0.0,
519
+ 0.0,
520
+ 0.0,
521
+ 0.0,
522
+ 0.0,
523
+ 0.0,
524
+ 0.0,
525
+ 0.0,
526
+ 0.0,
527
+ 0.0,
528
+ 0.0,
529
+ 0.0,
530
+ 0.0,
531
+ 0.0,
532
+ 0.0,
533
+ 0.0,
534
+ 0.0,
535
+ 0.0,
536
+ 0.0,
537
+ 0.0,
538
+ 0.0,
539
+ 0.0,
540
+ 0.0,
541
+ 0.0,
542
+ 0.0,
543
+ 0.0,
544
+ 0.0,
545
+ 0.0,
546
+ 0.0,
547
+ 0.0,
548
+ 0.0,
549
+ 0.0,
550
+ 0.0,
551
+ 0.0,
552
+ 0.0,
553
+ 0.0,
554
+ 0.0,
555
+ 0.0
556
+ ],
557
+ "q01": [
558
+ 0.0,
559
+ 0.0,
560
+ 0.0,
561
+ 0.0,
562
+ 0.0,
563
+ 0.0,
564
+ 0.0,
565
+ 0.0,
566
+ 0.0,
567
+ 0.0,
568
+ 0.0,
569
+ 0.0,
570
+ 0.0,
571
+ 0.0,
572
+ 0.0,
573
+ 0.0,
574
+ 0.0,
575
+ 0.0,
576
+ 0.0,
577
+ 0.0,
578
+ 0.0,
579
+ 0.0,
580
+ 0.0,
581
+ 0.0,
582
+ 0.0,
583
+ 0.0,
584
+ 0.0,
585
+ 0.0,
586
+ 0.0,
587
+ 0.0,
588
+ 0.0,
589
+ 0.0,
590
+ 0.0,
591
+ 0.0,
592
+ 0.0,
593
+ 0.0,
594
+ 0.0,
595
+ 0.0,
596
+ 0.0,
597
+ 0.0,
598
+ 0.0,
599
+ 0.0,
600
+ 0.0,
601
+ 0.0,
602
+ 0.0,
603
+ 0.0,
604
+ 0.0,
605
+ 0.0,
606
+ 0.0,
607
+ 0.0,
608
+ 0.0,
609
+ 0.0,
610
+ 0.0,
611
+ 0.0,
612
+ 0.0,
613
+ 0.0,
614
+ 0.0,
615
+ 0.0,
616
+ 0.0,
617
+ 0.0,
618
+ 0.0,
619
+ 0.0,
620
+ 0.0,
621
+ 0.0,
622
+ 0.0,
623
+ 0.0,
624
+ 0.0,
625
+ 0.0,
626
+ 0.0,
627
+ 0.0,
628
+ 0.0,
629
+ 0.0,
630
+ 0.0,
631
+ 0.0,
632
+ 0.0,
633
+ 0.0,
634
+ 0.0,
635
+ 0.0,
636
+ 0.0,
637
+ 0.0,
638
+ 0.0,
639
+ 0.0,
640
+ 0.0,
641
+ 0.0,
642
+ 0.0,
643
+ 0.0,
644
+ 0.0,
645
+ 0.0,
646
+ 0.0,
647
+ 0.0,
648
+ 0.0,
649
+ 0.0,
650
+ 0.0,
651
+ 0.0,
652
+ 0.0,
653
+ 0.0,
654
+ 0.0,
655
+ 0.0,
656
+ 0.0,
657
+ 0.0,
658
+ 0.0,
659
+ 0.0,
660
+ 0.0,
661
+ 0.0,
662
+ 0.0,
663
+ 0.0,
664
+ 0.0,
665
+ 0.0,
666
+ 0.0,
667
+ 0.0,
668
+ 0.0,
669
+ 0.0,
670
+ 0.0,
671
+ 0.0,
672
+ 0.0,
673
+ 0.0,
674
+ 0.0,
675
+ 0.0,
676
+ 0.0,
677
+ 0.0
678
+ ],
679
+ "q99": [
680
+ 1.0,
681
+ 1.0,
682
+ 1.0,
683
+ 1.0,
684
+ 0.0,
685
+ 1.0,
686
+ 1.0,
687
+ 1.0,
688
+ 1.0,
689
+ 1.0,
690
+ 1.0,
691
+ 0.0,
692
+ 1.0,
693
+ 1.0,
694
+ 1.0,
695
+ 1.0,
696
+ 1.0,
697
+ 1.0,
698
+ 1.0,
699
+ 0.0,
700
+ 1.0,
701
+ 1.0,
702
+ 1.0,
703
+ 1.0,
704
+ 1.0,
705
+ 1.0,
706
+ 0.0,
707
+ 1.0,
708
+ 1.0,
709
+ 1.0,
710
+ 1.0,
711
+ 1.0,
712
+ 1.0,
713
+ 1.0,
714
+ 0.0,
715
+ 1.0,
716
+ 1.0,
717
+ 1.0,
718
+ 1.0,
719
+ 1.0,
720
+ 1.0,
721
+ 0.0,
722
+ 1.0,
723
+ 1.0,
724
+ 1.0,
725
+ 1.0,
726
+ 1.0,
727
+ 1.0,
728
+ 1.0,
729
+ 0.0,
730
+ 1.0,
731
+ 1.0,
732
+ 1.0,
733
+ 1.0,
734
+ 1.0,
735
+ 1.0,
736
+ 0.0,
737
+ 1.0,
738
+ 1.0,
739
+ 1.0,
740
+ 1.0,
741
+ 1.0,
742
+ 1.0,
743
+ 1.0,
744
+ 0.0,
745
+ 1.0,
746
+ 1.0,
747
+ 1.0,
748
+ 1.0,
749
+ 1.0,
750
+ 1.0,
751
+ 0.0,
752
+ 1.0,
753
+ 1.0,
754
+ 1.0,
755
+ 1.0,
756
+ 1.0,
757
+ 1.0,
758
+ 1.0,
759
+ 0.0,
760
+ 1.0,
761
+ 1.0,
762
+ 1.0,
763
+ 1.0,
764
+ 1.0,
765
+ 1.0,
766
+ 0.0,
767
+ 1.0,
768
+ 1.0,
769
+ 1.0,
770
+ 1.0,
771
+ 1.0,
772
+ 1.0,
773
+ 1.0,
774
+ 0.0,
775
+ 1.0,
776
+ 1.0,
777
+ 1.0,
778
+ 1.0,
779
+ 1.0,
780
+ 1.0,
781
+ 0.0,
782
+ 1.0,
783
+ 1.0,
784
+ 1.0,
785
+ 1.0,
786
+ 1.0,
787
+ 1.0,
788
+ 1.0,
789
+ 0.0,
790
+ 1.0,
791
+ 1.0,
792
+ 1.0,
793
+ 1.0,
794
+ 1.0,
795
+ 1.0,
796
+ 0.0,
797
+ 1.0,
798
+ 1.0,
799
+ 1.0
800
+ ]
801
+ },
802
+ "num_transitions": 313925,
803
+ "num_trajectories": 7650
804
+ }
805
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/dataset_statistics_eval.json ADDED
@@ -0,0 +1,805 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "new_embodiment": {
3
+ "action": {
4
+ "mean": [
5
+ 0.990105926990509,
6
+ 0.0,
7
+ 0.141621932387352,
8
+ 0.6689975261688232,
9
+ 0.22936312854290009,
10
+ 0.1096474677324295,
11
+ 0.7722617387771606
12
+ ],
13
+ "std": [
14
+ 0.09895878285169574,
15
+ 0.0,
16
+ 0.34863075613975525,
17
+ 0.47055235505104065,
18
+ 0.4204241633415222,
19
+ 0.312391072511673,
20
+ 0.41930046677589417
21
+ ],
22
+ "max": [
23
+ 1.0,
24
+ 0.0,
25
+ 1.0,
26
+ 1.0,
27
+ 1.0,
28
+ 1.0,
29
+ 1.0
30
+ ],
31
+ "min": [
32
+ 0.0,
33
+ 0.0,
34
+ 0.0,
35
+ 0.0,
36
+ 0.0,
37
+ 0.0,
38
+ 0.0
39
+ ],
40
+ "q01": [
41
+ 1.0,
42
+ 0.0,
43
+ 0.0,
44
+ 0.0,
45
+ 0.0,
46
+ 0.0,
47
+ 0.0
48
+ ],
49
+ "q99": [
50
+ 1.0,
51
+ 0.0,
52
+ 1.0,
53
+ 1.0,
54
+ 1.0,
55
+ 1.0,
56
+ 1.0
57
+ ],
58
+ "mask": [
59
+ true,
60
+ true,
61
+ true,
62
+ true,
63
+ true,
64
+ true,
65
+ true
66
+ ]
67
+ },
68
+ "state": {
69
+ "mean": [
70
+ 0.8034237623214722,
71
+ 0.17968954145908356,
72
+ 0.08718990534543991,
73
+ 0.793732762336731,
74
+ 0.0,
75
+ 0.1379370391368866,
76
+ 0.48156100511550903,
77
+ 0.6375453472137451,
78
+ 0.17968954145908356,
79
+ 0.08718990534543991,
80
+ 0.793732762336731,
81
+ 0.0,
82
+ 0.1379370391368866,
83
+ 0.48156100511550903,
84
+ 0.6375453472137451,
85
+ 0.8278833627700806,
86
+ 0.18296822905540466,
87
+ 0.08771216869354248,
88
+ 0.8181923627853394,
89
+ 0.0,
90
+ 0.13831423223018646,
91
+ 0.5052372217178345,
92
+ 0.6500797867774963,
93
+ 0.18296822905540466,
94
+ 0.08771216869354248,
95
+ 0.8181923627853394,
96
+ 0.0,
97
+ 0.13831423223018646,
98
+ 0.5052372217178345,
99
+ 0.6500797867774963,
100
+ 0.852342963218689,
101
+ 0.1830262541770935,
102
+ 0.08800232410430908,
103
+ 0.8426519632339478,
104
+ 0.0,
105
+ 0.13860438764095306,
106
+ 0.5288553833961487,
107
+ 0.666879415512085,
108
+ 0.1830262541770935,
109
+ 0.08800232410430908,
110
+ 0.8426519632339478,
111
+ 0.0,
112
+ 0.13860438764095306,
113
+ 0.5288553833961487,
114
+ 0.666879415512085,
115
+ 0.8768025636672974,
116
+ 0.18314231932163239,
117
+ 0.08849557489156723,
118
+ 0.8671115636825562,
119
+ 0.0,
120
+ 0.13898158073425293,
121
+ 0.5523574352264404,
122
+ 0.6813288927078247,
123
+ 0.18314231932163239,
124
+ 0.08849557489156723,
125
+ 0.8671115636825562,
126
+ 0.0,
127
+ 0.13898158073425293,
128
+ 0.5523574352264404,
129
+ 0.6813288927078247,
130
+ 0.9013782143592834,
131
+ 0.18505729734897614,
132
+ 0.08954011648893356,
133
+ 0.8916872143745422,
134
+ 0.0,
135
+ 0.13938778638839722,
136
+ 0.5758885741233826,
137
+ 0.697635293006897,
138
+ 0.18505729734897614,
139
+ 0.08954011648893356,
140
+ 0.8916872143745422,
141
+ 0.0,
142
+ 0.13938778638839722,
143
+ 0.5758885741233826,
144
+ 0.697635293006897,
145
+ 0.9260119199752808,
146
+ 0.19120846688747406,
147
+ 0.09307993948459625,
148
+ 0.9163209199905396,
149
+ 0.0,
150
+ 0.13982300460338593,
151
+ 0.5994777083396912,
152
+ 0.717829704284668,
153
+ 0.19120846688747406,
154
+ 0.09307993948459625,
155
+ 0.9163209199905396,
156
+ 0.0,
157
+ 0.13982300460338593,
158
+ 0.5994777083396912,
159
+ 0.717829704284668,
160
+ 0.9506745934486389,
161
+ 0.2039170116186142,
162
+ 0.09699695557355881,
163
+ 0.9409545660018921,
164
+ 0.0,
165
+ 0.1403452754020691,
166
+ 0.6229798197746277,
167
+ 0.7330625057220459,
168
+ 0.2039170116186142,
169
+ 0.09699695557355881,
170
+ 0.9409545660018921,
171
+ 0.0,
172
+ 0.1403452754020691,
173
+ 0.6229798197746277,
174
+ 0.7330625057220459,
175
+ 0.9753373265266418,
176
+ 0.2158711701631546,
177
+ 0.10346728563308716,
178
+ 0.9655882716178894,
179
+ 0.0,
180
+ 0.14095459878444672,
181
+ 0.646162748336792,
182
+ 0.7495720386505127,
183
+ 0.2158711701631546,
184
+ 0.10346728563308716,
185
+ 0.9655882716178894,
186
+ 0.0,
187
+ 0.14095459878444672,
188
+ 0.646162748336792,
189
+ 0.7495720386505127
190
+ ],
191
+ "std": [
192
+ 0.3973795771598816,
193
+ 0.38389143347740173,
194
+ 0.28209006786346436,
195
+ 0.404594361782074,
196
+ 0.0,
197
+ 0.3448529541492462,
198
+ 0.4996091425418854,
199
+ 0.4806591272354126,
200
+ 0.38389143347740173,
201
+ 0.28209006786346436,
202
+ 0.404594361782074,
203
+ 0.0,
204
+ 0.3448529541492462,
205
+ 0.4996091425418854,
206
+ 0.4806591272354126,
207
+ 0.37747922539711,
208
+ 0.38665321469306946,
209
+ 0.2829231023788452,
210
+ 0.38568517565727234,
211
+ 0.0,
212
+ 0.34517642855644226,
213
+ 0.4999774098396301,
214
+ 0.476959228515625,
215
+ 0.38665321469306946,
216
+ 0.2829231023788452,
217
+ 0.38568517565727234,
218
+ 0.0,
219
+ 0.34517642855644226,
220
+ 0.4999774098396301,
221
+ 0.476959228515625,
222
+ 0.35474687814712524,
223
+ 0.3867047429084778,
224
+ 0.2833026647567749,
225
+ 0.36409226059913635,
226
+ 0.0,
227
+ 0.3455602824687958,
228
+ 0.4992201328277588,
229
+ 0.47133031487464905,
230
+ 0.3867047429084778,
231
+ 0.2833026647567749,
232
+ 0.36409226059913635,
233
+ 0.0,
234
+ 0.3455602824687958,
235
+ 0.4992201328277588,
236
+ 0.47133031487464905,
237
+ 0.32862982153892517,
238
+ 0.3867926597595215,
239
+ 0.2839869260787964,
240
+ 0.3394205570220947,
241
+ 0.0,
242
+ 0.3459067940711975,
243
+ 0.49722298979759216,
244
+ 0.4659842252731323,
245
+ 0.3867926597595215,
246
+ 0.2839869260787964,
247
+ 0.3394205570220947,
248
+ 0.0,
249
+ 0.3459067940711975,
250
+ 0.49722298979759216,
251
+ 0.4659842252731323,
252
+ 0.29819053411483765,
253
+ 0.3883046805858612,
254
+ 0.28555458784103394,
255
+ 0.3107653260231018,
256
+ 0.0,
257
+ 0.34641167521476746,
258
+ 0.49412932991981506,
259
+ 0.4592491090297699,
260
+ 0.3883046805858612,
261
+ 0.28555458784103394,
262
+ 0.3107653260231018,
263
+ 0.0,
264
+ 0.34641167521476746,
265
+ 0.49412932991981506,
266
+ 0.4592491090297699,
267
+ 0.2617478370666504,
268
+ 0.39330387115478516,
269
+ 0.29049330949783325,
270
+ 0.27690601348876953,
271
+ 0.0,
272
+ 0.3467898964881897,
273
+ 0.4900676906108856,
274
+ 0.45002293586730957,
275
+ 0.39330387115478516,
276
+ 0.29049330949783325,
277
+ 0.27690601348876953,
278
+ 0.0,
279
+ 0.3467898964881897,
280
+ 0.4900676906108856,
281
+ 0.45002293586730957,
282
+ 0.21656277775764465,
283
+ 0.4028741121292114,
284
+ 0.29600322246551514,
285
+ 0.23574966192245483,
286
+ 0.0,
287
+ 0.3473797142505646,
288
+ 0.4846312701702118,
289
+ 0.44240280985832214,
290
+ 0.4028741121292114,
291
+ 0.29600322246551514,
292
+ 0.23574966192245483,
293
+ 0.0,
294
+ 0.3473797142505646,
295
+ 0.4846312701702118,
296
+ 0.44240280985832214,
297
+ 0.15510143339633942,
298
+ 0.4113645851612091,
299
+ 0.30459317564964294,
300
+ 0.18227136135101318,
301
+ 0.0,
302
+ 0.3479393422603607,
303
+ 0.47809022665023804,
304
+ 0.43321406841278076,
305
+ 0.4113645851612091,
306
+ 0.30459317564964294,
307
+ 0.18227136135101318,
308
+ 0.0,
309
+ 0.3479393422603607,
310
+ 0.47809022665023804,
311
+ 0.43321406841278076
312
+ ],
313
+ "max": [
314
+ 1.0,
315
+ 1.0,
316
+ 1.0,
317
+ 1.0,
318
+ 1.0,
319
+ 1.0,
320
+ 1.0,
321
+ 1.0,
322
+ 1.0,
323
+ 1.0,
324
+ 1.0,
325
+ 1.0,
326
+ 1.0,
327
+ 1.0,
328
+ 1.0,
329
+ 1.0,
330
+ 1.0,
331
+ 1.0,
332
+ 1.0,
333
+ 1.0,
334
+ 1.0,
335
+ 1.0,
336
+ 1.0,
337
+ 1.0,
338
+ 1.0,
339
+ 1.0,
340
+ 1.0,
341
+ 1.0,
342
+ 1.0,
343
+ 1.0,
344
+ 1.0,
345
+ 1.0,
346
+ 1.0,
347
+ 1.0,
348
+ 1.0,
349
+ 1.0,
350
+ 1.0,
351
+ 1.0,
352
+ 1.0,
353
+ 1.0,
354
+ 1.0,
355
+ 1.0,
356
+ 1.0,
357
+ 1.0,
358
+ 1.0,
359
+ 1.0,
360
+ 1.0,
361
+ 1.0,
362
+ 1.0,
363
+ 1.0,
364
+ 1.0,
365
+ 1.0,
366
+ 1.0,
367
+ 1.0,
368
+ 1.0,
369
+ 1.0,
370
+ 1.0,
371
+ 1.0,
372
+ 1.0,
373
+ 1.0,
374
+ 1.0,
375
+ 1.0,
376
+ 1.0,
377
+ 1.0,
378
+ 1.0,
379
+ 1.0,
380
+ 1.0,
381
+ 1.0,
382
+ 1.0,
383
+ 1.0,
384
+ 1.0,
385
+ 1.0,
386
+ 1.0,
387
+ 1.0,
388
+ 1.0,
389
+ 1.0,
390
+ 1.0,
391
+ 1.0,
392
+ 1.0,
393
+ 1.0,
394
+ 1.0,
395
+ 1.0,
396
+ 1.0,
397
+ 1.0,
398
+ 1.0,
399
+ 1.0,
400
+ 1.0,
401
+ 1.0,
402
+ 1.0,
403
+ 1.0,
404
+ 1.0,
405
+ 1.0,
406
+ 1.0,
407
+ 1.0,
408
+ 1.0,
409
+ 1.0,
410
+ 1.0,
411
+ 1.0,
412
+ 1.0,
413
+ 1.0,
414
+ 1.0,
415
+ 1.0,
416
+ 1.0,
417
+ 1.0,
418
+ 1.0,
419
+ 1.0,
420
+ 1.0,
421
+ 1.0,
422
+ 1.0,
423
+ 1.0,
424
+ 1.0,
425
+ 1.0,
426
+ 1.0,
427
+ 1.0,
428
+ 1.0,
429
+ 1.0,
430
+ 1.0,
431
+ 1.0,
432
+ 1.0,
433
+ 1.0
434
+ ],
435
+ "min": [
436
+ 0.0,
437
+ 0.0,
438
+ 0.0,
439
+ 0.0,
440
+ 0.0,
441
+ 0.0,
442
+ 0.0,
443
+ 0.0,
444
+ 0.0,
445
+ 0.0,
446
+ 0.0,
447
+ 0.0,
448
+ 0.0,
449
+ 0.0,
450
+ 0.0,
451
+ 0.0,
452
+ 0.0,
453
+ 0.0,
454
+ 0.0,
455
+ 0.0,
456
+ 0.0,
457
+ 0.0,
458
+ 0.0,
459
+ 0.0,
460
+ 0.0,
461
+ 0.0,
462
+ 0.0,
463
+ 0.0,
464
+ 0.0,
465
+ 0.0,
466
+ 0.0,
467
+ 0.0,
468
+ 0.0,
469
+ 0.0,
470
+ 0.0,
471
+ 0.0,
472
+ 0.0,
473
+ 0.0,
474
+ 0.0,
475
+ 0.0,
476
+ 0.0,
477
+ 0.0,
478
+ 0.0,
479
+ 0.0,
480
+ 0.0,
481
+ 0.0,
482
+ 0.0,
483
+ 0.0,
484
+ 0.0,
485
+ 0.0,
486
+ 0.0,
487
+ 0.0,
488
+ 0.0,
489
+ 0.0,
490
+ 0.0,
491
+ 0.0,
492
+ 0.0,
493
+ 0.0,
494
+ 0.0,
495
+ 0.0,
496
+ 0.0,
497
+ 0.0,
498
+ 0.0,
499
+ 0.0,
500
+ 0.0,
501
+ 0.0,
502
+ 0.0,
503
+ 0.0,
504
+ 0.0,
505
+ 0.0,
506
+ 0.0,
507
+ 0.0,
508
+ 0.0,
509
+ 0.0,
510
+ 0.0,
511
+ 0.0,
512
+ 0.0,
513
+ 0.0,
514
+ 0.0,
515
+ 0.0,
516
+ 0.0,
517
+ 0.0,
518
+ 0.0,
519
+ 0.0,
520
+ 0.0,
521
+ 0.0,
522
+ 0.0,
523
+ 0.0,
524
+ 0.0,
525
+ 0.0,
526
+ 0.0,
527
+ 0.0,
528
+ 0.0,
529
+ 0.0,
530
+ 0.0,
531
+ 0.0,
532
+ 0.0,
533
+ 0.0,
534
+ 0.0,
535
+ 0.0,
536
+ 0.0,
537
+ 0.0,
538
+ 0.0,
539
+ 0.0,
540
+ 0.0,
541
+ 0.0,
542
+ 0.0,
543
+ 0.0,
544
+ 0.0,
545
+ 0.0,
546
+ 0.0,
547
+ 0.0,
548
+ 0.0,
549
+ 0.0,
550
+ 0.0,
551
+ 0.0,
552
+ 0.0,
553
+ 0.0,
554
+ 0.0,
555
+ 0.0
556
+ ],
557
+ "q01": [
558
+ 0.0,
559
+ 0.0,
560
+ 0.0,
561
+ 0.0,
562
+ 0.0,
563
+ 0.0,
564
+ 0.0,
565
+ 0.0,
566
+ 0.0,
567
+ 0.0,
568
+ 0.0,
569
+ 0.0,
570
+ 0.0,
571
+ 0.0,
572
+ 0.0,
573
+ 0.0,
574
+ 0.0,
575
+ 0.0,
576
+ 0.0,
577
+ 0.0,
578
+ 0.0,
579
+ 0.0,
580
+ 0.0,
581
+ 0.0,
582
+ 0.0,
583
+ 0.0,
584
+ 0.0,
585
+ 0.0,
586
+ 0.0,
587
+ 0.0,
588
+ 0.0,
589
+ 0.0,
590
+ 0.0,
591
+ 0.0,
592
+ 0.0,
593
+ 0.0,
594
+ 0.0,
595
+ 0.0,
596
+ 0.0,
597
+ 0.0,
598
+ 0.0,
599
+ 0.0,
600
+ 0.0,
601
+ 0.0,
602
+ 0.0,
603
+ 0.0,
604
+ 0.0,
605
+ 0.0,
606
+ 0.0,
607
+ 0.0,
608
+ 0.0,
609
+ 0.0,
610
+ 0.0,
611
+ 0.0,
612
+ 0.0,
613
+ 0.0,
614
+ 0.0,
615
+ 0.0,
616
+ 0.0,
617
+ 0.0,
618
+ 0.0,
619
+ 0.0,
620
+ 0.0,
621
+ 0.0,
622
+ 0.0,
623
+ 0.0,
624
+ 0.0,
625
+ 0.0,
626
+ 0.0,
627
+ 0.0,
628
+ 0.0,
629
+ 0.0,
630
+ 0.0,
631
+ 0.0,
632
+ 0.0,
633
+ 0.0,
634
+ 0.0,
635
+ 0.0,
636
+ 0.0,
637
+ 0.0,
638
+ 0.0,
639
+ 0.0,
640
+ 0.0,
641
+ 0.0,
642
+ 0.0,
643
+ 0.0,
644
+ 0.0,
645
+ 0.0,
646
+ 0.0,
647
+ 0.0,
648
+ 0.0,
649
+ 0.0,
650
+ 0.0,
651
+ 0.0,
652
+ 0.0,
653
+ 0.0,
654
+ 0.0,
655
+ 0.0,
656
+ 0.0,
657
+ 0.0,
658
+ 0.0,
659
+ 0.0,
660
+ 0.0,
661
+ 0.0,
662
+ 0.0,
663
+ 0.0,
664
+ 0.0,
665
+ 0.0,
666
+ 0.0,
667
+ 0.0,
668
+ 0.0,
669
+ 0.0,
670
+ 0.0,
671
+ 0.0,
672
+ 0.0,
673
+ 0.0,
674
+ 0.0,
675
+ 0.0,
676
+ 0.0,
677
+ 0.0
678
+ ],
679
+ "q99": [
680
+ 1.0,
681
+ 1.0,
682
+ 1.0,
683
+ 1.0,
684
+ 0.0,
685
+ 1.0,
686
+ 1.0,
687
+ 1.0,
688
+ 1.0,
689
+ 1.0,
690
+ 1.0,
691
+ 0.0,
692
+ 1.0,
693
+ 1.0,
694
+ 1.0,
695
+ 1.0,
696
+ 1.0,
697
+ 1.0,
698
+ 1.0,
699
+ 0.0,
700
+ 1.0,
701
+ 1.0,
702
+ 1.0,
703
+ 1.0,
704
+ 1.0,
705
+ 1.0,
706
+ 0.0,
707
+ 1.0,
708
+ 1.0,
709
+ 1.0,
710
+ 1.0,
711
+ 1.0,
712
+ 1.0,
713
+ 1.0,
714
+ 0.0,
715
+ 1.0,
716
+ 1.0,
717
+ 1.0,
718
+ 1.0,
719
+ 1.0,
720
+ 1.0,
721
+ 0.0,
722
+ 1.0,
723
+ 1.0,
724
+ 1.0,
725
+ 1.0,
726
+ 1.0,
727
+ 1.0,
728
+ 1.0,
729
+ 0.0,
730
+ 1.0,
731
+ 1.0,
732
+ 1.0,
733
+ 1.0,
734
+ 1.0,
735
+ 1.0,
736
+ 0.0,
737
+ 1.0,
738
+ 1.0,
739
+ 1.0,
740
+ 1.0,
741
+ 1.0,
742
+ 1.0,
743
+ 1.0,
744
+ 0.0,
745
+ 1.0,
746
+ 1.0,
747
+ 1.0,
748
+ 1.0,
749
+ 1.0,
750
+ 1.0,
751
+ 0.0,
752
+ 1.0,
753
+ 1.0,
754
+ 1.0,
755
+ 1.0,
756
+ 1.0,
757
+ 1.0,
758
+ 1.0,
759
+ 0.0,
760
+ 1.0,
761
+ 1.0,
762
+ 1.0,
763
+ 1.0,
764
+ 1.0,
765
+ 1.0,
766
+ 0.0,
767
+ 1.0,
768
+ 1.0,
769
+ 1.0,
770
+ 1.0,
771
+ 1.0,
772
+ 1.0,
773
+ 1.0,
774
+ 0.0,
775
+ 1.0,
776
+ 1.0,
777
+ 1.0,
778
+ 1.0,
779
+ 1.0,
780
+ 1.0,
781
+ 0.0,
782
+ 1.0,
783
+ 1.0,
784
+ 1.0,
785
+ 1.0,
786
+ 1.0,
787
+ 1.0,
788
+ 1.0,
789
+ 0.0,
790
+ 1.0,
791
+ 1.0,
792
+ 1.0,
793
+ 1.0,
794
+ 1.0,
795
+ 1.0,
796
+ 0.0,
797
+ 1.0,
798
+ 1.0,
799
+ 1.0
800
+ ]
801
+ },
802
+ "num_transitions": 34465,
803
+ "num_trajectories": 850
804
+ }
805
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/files.sha256.json ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "README.md": {
3
+ "bytes": 1157,
4
+ "sha256": "a8a9b178c8064c75e4355a78f91eb3f582b0813a02ed087bccceec1aae41fa65"
5
+ },
6
+ "checkpoints/model.pt": {
7
+ "bytes": 9785680289,
8
+ "sha256": "a756924b1f9a93cc4f278e03535dd61535977037f9484957672336e6b9c9265c"
9
+ },
10
+ "collection_quality_report.json": {
11
+ "bytes": 452,
12
+ "sha256": "244d67ae4831598951770ecf4b95f8d89799305adfa7eb743095541e58277a62"
13
+ },
14
+ "config.full.yaml": {
15
+ "bytes": 6770,
16
+ "sha256": "c080e2c9d2b3c8bc3fe8c36c21ce0d7bd757d853d9fb148e6d9ebe2380b3050e"
17
+ },
18
+ "config.yaml": {
19
+ "bytes": 983,
20
+ "sha256": "e4882ebbfb62427c9b0484f83c47b88ffaa0d991ea00674501ebb97b194f7959"
21
+ },
22
+ "dataset_statistics.json": {
23
+ "bytes": 13822,
24
+ "sha256": "4269d27e69b4925601b2f6d62cdbf4ad1279e0863e25f001f1e0b5eec8da7556"
25
+ },
26
+ "dataset_statistics_eval.json": {
27
+ "bytes": 13810,
28
+ "sha256": "13718c59677e654a9d8a78ed04b3a71aeff7dee27056dc8f30c727d476fdddce"
29
+ },
30
+ "latency_prompt_map.json": {
31
+ "bytes": 421,
32
+ "sha256": "2481741b4c1acb83248f039abc485c4f4729631f9951d134ff35b858f1a2554a"
33
+ },
34
+ "launch_audit.json": {
35
+ "bytes": 1220,
36
+ "sha256": "df5b02aa77f7e4ef62e721b57699bd0ef5cf7f46e45a8b07dccfc2081b3413f0"
37
+ },
38
+ "manifest.json": {
39
+ "bytes": 7393,
40
+ "sha256": "7168be7a6a3829b581c15a81af4afb5509bab7c466e05b8a62cfe24c80c72bd9"
41
+ },
42
+ "profile.source.json": {
43
+ "bytes": 2115,
44
+ "sha256": "bbfb93cef9f63750a9a159ec10a93a9fc6c25e4cb0cac3b39532663b4dc11eba"
45
+ },
46
+ "provenance.json": {
47
+ "bytes": 5089,
48
+ "sha256": "492e8162587dbb01279475c93cb39eaee54f1bb4893062a4c1a847477e91c679"
49
+ },
50
+ "startup_verified.json": {
51
+ "bytes": 1402,
52
+ "sha256": "e8f80f6020171df621feb397a7cc0ebe2cb2ece05693c7d4a763ce2f800bc52e"
53
+ },
54
+ "summary.jsonl": {
55
+ "bytes": 159,
56
+ "sha256": "2905acb79c5fffb33fd4689d87af3bd05d74f4184b9d36ff3eae0c64deecd930"
57
+ },
58
+ "task_contract.json": {
59
+ "bytes": 1632,
60
+ "sha256": "c3d3909b6a18abb6bd4d356c67d4813d88e38e49a1aea58b25fb5346732804c6"
61
+ },
62
+ "training-code/QWen3.py": {
63
+ "bytes": 17586,
64
+ "sha256": "5fe76fc98eaa84e215c3c25c11326815499d2a4b0683c6ab95382b881f535370"
65
+ },
66
+ "training-code/QwenOFT.py": {
67
+ "bytes": 62854,
68
+ "sha256": "acad1b0dcde6e9fed6e2912b6534db0f8e33a74ec7f6630bbf1b0161fc298b0d"
69
+ },
70
+ "training-code/datasets.py": {
71
+ "bytes": 154347,
72
+ "sha256": "33e22556471128a2bad18a1ef8b84c399847b4d98b2979d785d139de0cdf36df"
73
+ },
74
+ "training-code/doom-mean-reset.patch": {
75
+ "bytes": 9569,
76
+ "sha256": "4113989e16c547bd1f02f5f10f285c4d511be3a3c18d10a0aa3316bd8ff3175d"
77
+ },
78
+ "training-code/gym-language-contract.patch": {
79
+ "bytes": 688,
80
+ "sha256": "9f5dee2c5b52d5507aff27373a8cf6def4959361d2c5264d5079b416f28a4c49"
81
+ },
82
+ "training-code/loader-spawn-cache.patch": {
83
+ "bytes": 711,
84
+ "sha256": "24532ce84e5aa9aef381493fe699b4bb4987afd954422191ae852b0f5eb5b2cd"
85
+ },
86
+ "training-code/loader-spawn-test.patch": {
87
+ "bytes": 1500,
88
+ "sha256": "a36db15b13d68defeecb75ddc9efa1ac202d9aa0a40f66ba5baaee2dcaef21f1"
89
+ },
90
+ "training-code/mean-profile-preparation.patch": {
91
+ "bytes": 7053,
92
+ "sha256": "de5fe558376c98515a1cfb186ffdc09b618acc207eb8a5f667b0cbb303767c09"
93
+ },
94
+ "training-code/train_starvla.py": {
95
+ "bytes": 125159,
96
+ "sha256": "f872648f941cec272af724772e9d6fc3721e9ed6eaf0c8683ab285eb9396212e"
97
+ },
98
+ "training-code/trainer_tools.py": {
99
+ "bytes": 29144,
100
+ "sha256": "9a48bdfb99b405b03fececfc1e051d3ebb179eb423c15141f02b9be62e2e1791"
101
+ },
102
+ "training-code/worker_context.py": {
103
+ "bytes": 2279,
104
+ "sha256": "8493631104269f0630655ee2faae592a84ebfb3119aca142c8ac2701f5214464"
105
+ },
106
+ "training_results.json": {
107
+ "bytes": 573,
108
+ "sha256": "3aba30a0e61d361dad712f51bd67eb9faabb17967d03922f4ec3a22edcdf53f1"
109
+ }
110
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/latency_prompt_map.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "3": {
3
+ "prompt": "You are playing Deadly Corridor in VizDoom. Your goal is to survive the corridor, fight enemies, and reach the green armor vest at the far end. The available actions are: MOVE_FORWARD, MOVE_BACKWARD, MOVE_LEFT, MOVE_RIGHT, TURN_LEFT, TURN_RIGHT, and ATTACK. Choose the best next action from the current visual observation.",
4
+ "latency_raw_frames": 3,
5
+ "latency_ms": 85.71428571428572
6
+ }
7
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/launch_audit.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "reference": "/home/ubuntu/lzj/mean-profiling/reference/checkpoint-configs/latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-hist8-scratch-s42-v2/config.full.yaml",
3
+ "reference_sha256": "4a8181489f1734ed981d345006b7a33473e29d41f74ab5d6dff3b0997ec263ed",
4
+ "scientific_trainer_fields_equal": [
5
+ "max_train_steps",
6
+ "num_warmup_steps",
7
+ "learning_rate",
8
+ "lr_scheduler_type",
9
+ "scheduler_specific_kwargs",
10
+ "optimizer",
11
+ "eval_interval",
12
+ "eval_num_batches",
13
+ "save_interval"
14
+ ],
15
+ "seed": 42,
16
+ "horizon": 1,
17
+ "state_dim": 120,
18
+ "action_dim": 7,
19
+ "global_batch": 128,
20
+ "micro_per_gpu": 64,
21
+ "accumulation": 1,
22
+ "gradient_checkpointing": true,
23
+ "profiling_difference": "fixedmean RTX3090 versus source temporaldistribution",
24
+ "formal_optimizer_updates": 5000,
25
+ "preflight_updates_discarded": 20,
26
+ "post_train_rollout_eval": false,
27
+ "physical_gpus": [
28
+ 2,
29
+ 3
30
+ ],
31
+ "previous_failed_runtime": "GCfalse CUDAOOM, noformalupdates",
32
+ "user_authorization": "GPU2/3 nowempty, userexplicitlyrequestsDeadlyVLA there",
33
+ "startup_verified": true,
34
+ "formal_startup_evidence": "/home/ubuntu/lzj/mean-profiling/deadly_corridor/vla.startup-verified.json"
35
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/manifest.json ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "dataset_name": "lerobot",
3
+ "env_name": "deadly_corridor",
4
+ "episodes": 7650,
5
+ "frames": 313925,
6
+ "task_prompts": [
7
+ "You are playing Deadly Corridor in VizDoom. Your goal is to survive the corridor, fight enemies, and reach the green armor vest at the far end. The available actions are: MOVE_FORWARD, MOVE_BACKWARD, MOVE_LEFT, MOVE_RIGHT, TURN_LEFT, TURN_RIGHT, and ATTACK. Choose the best next action from the current visual observation."
8
+ ],
9
+ "format": "starvla_lerobot_v2_decision_v1",
10
+ "source": "/home/ubuntu/lzj/mean-profiling/deadly_corridor/data/raw",
11
+ "robot_type": "rl_games_deadly_corridor",
12
+ "action_layout": "multibinary_7",
13
+ "source_action_layout": "deadly_corridor_joint_54",
14
+ "action_labels": [
15
+ "MOVE_FORWARD",
16
+ "MOVE_BACKWARD",
17
+ "MOVE_LEFT",
18
+ "MOVE_RIGHT",
19
+ "TURN_LEFT",
20
+ "TURN_RIGHT",
21
+ "ATTACK"
22
+ ],
23
+ "action_dim": 7,
24
+ "active_action_dim": 7,
25
+ "state_source": "decision_v1",
26
+ "state_dim": 120,
27
+ "state_labels": [
28
+ "decision_history_0",
29
+ "decision_history_1",
30
+ "decision_history_2",
31
+ "decision_history_3",
32
+ "decision_history_4",
33
+ "decision_history_5",
34
+ "decision_history_6",
35
+ "decision_history_7",
36
+ "decision_history_8",
37
+ "decision_history_9",
38
+ "decision_history_10",
39
+ "decision_history_11",
40
+ "decision_history_12",
41
+ "decision_history_13",
42
+ "decision_history_14",
43
+ "decision_history_15",
44
+ "decision_history_16",
45
+ "decision_history_17",
46
+ "decision_history_18",
47
+ "decision_history_19",
48
+ "decision_history_20",
49
+ "decision_history_21",
50
+ "decision_history_22",
51
+ "decision_history_23",
52
+ "decision_history_24",
53
+ "decision_history_25",
54
+ "decision_history_26",
55
+ "decision_history_27",
56
+ "decision_history_28",
57
+ "decision_history_29",
58
+ "decision_history_30",
59
+ "decision_history_31",
60
+ "decision_history_32",
61
+ "decision_history_33",
62
+ "decision_history_34",
63
+ "decision_history_35",
64
+ "decision_history_36",
65
+ "decision_history_37",
66
+ "decision_history_38",
67
+ "decision_history_39",
68
+ "decision_history_40",
69
+ "decision_history_41",
70
+ "decision_history_42",
71
+ "decision_history_43",
72
+ "decision_history_44",
73
+ "decision_history_45",
74
+ "decision_history_46",
75
+ "decision_history_47",
76
+ "decision_history_48",
77
+ "decision_history_49",
78
+ "decision_history_50",
79
+ "decision_history_51",
80
+ "decision_history_52",
81
+ "decision_history_53",
82
+ "decision_history_54",
83
+ "decision_history_55",
84
+ "decision_history_56",
85
+ "decision_history_57",
86
+ "decision_history_58",
87
+ "decision_history_59",
88
+ "decision_history_60",
89
+ "decision_history_61",
90
+ "decision_history_62",
91
+ "decision_history_63",
92
+ "decision_history_64",
93
+ "decision_history_65",
94
+ "decision_history_66",
95
+ "decision_history_67",
96
+ "decision_history_68",
97
+ "decision_history_69",
98
+ "decision_history_70",
99
+ "decision_history_71",
100
+ "decision_history_72",
101
+ "decision_history_73",
102
+ "decision_history_74",
103
+ "decision_history_75",
104
+ "decision_history_76",
105
+ "decision_history_77",
106
+ "decision_history_78",
107
+ "decision_history_79",
108
+ "decision_history_80",
109
+ "decision_history_81",
110
+ "decision_history_82",
111
+ "decision_history_83",
112
+ "decision_history_84",
113
+ "decision_history_85",
114
+ "decision_history_86",
115
+ "decision_history_87",
116
+ "decision_history_88",
117
+ "decision_history_89",
118
+ "decision_history_90",
119
+ "decision_history_91",
120
+ "decision_history_92",
121
+ "decision_history_93",
122
+ "decision_history_94",
123
+ "decision_history_95",
124
+ "decision_history_96",
125
+ "decision_history_97",
126
+ "decision_history_98",
127
+ "decision_history_99",
128
+ "decision_history_100",
129
+ "decision_history_101",
130
+ "decision_history_102",
131
+ "decision_history_103",
132
+ "decision_history_104",
133
+ "decision_history_105",
134
+ "decision_history_106",
135
+ "decision_history_107",
136
+ "decision_history_108",
137
+ "decision_history_109",
138
+ "decision_history_110",
139
+ "decision_history_111",
140
+ "decision_history_112",
141
+ "decision_history_113",
142
+ "decision_history_114",
143
+ "decision_history_115",
144
+ "decision_history_116",
145
+ "decision_history_117",
146
+ "decision_history_118",
147
+ "decision_history_119"
148
+ ],
149
+ "state_normalization": {
150
+ "min": [
151
+ 0.0,
152
+ 0.0,
153
+ 0.0,
154
+ 0.0,
155
+ 0.0,
156
+ 0.0,
157
+ 0.0,
158
+ 0.0,
159
+ 0.0,
160
+ 0.0,
161
+ 0.0,
162
+ 0.0,
163
+ 0.0,
164
+ 0.0,
165
+ 0.0,
166
+ 0.0,
167
+ 0.0,
168
+ 0.0,
169
+ 0.0,
170
+ 0.0,
171
+ 0.0,
172
+ 0.0,
173
+ 0.0,
174
+ 0.0,
175
+ 0.0,
176
+ 0.0,
177
+ 0.0,
178
+ 0.0,
179
+ 0.0,
180
+ 0.0,
181
+ 0.0,
182
+ 0.0,
183
+ 0.0,
184
+ 0.0,
185
+ 0.0,
186
+ 0.0,
187
+ 0.0,
188
+ 0.0,
189
+ 0.0,
190
+ 0.0,
191
+ 0.0,
192
+ 0.0,
193
+ 0.0,
194
+ 0.0,
195
+ 0.0,
196
+ 0.0,
197
+ 0.0,
198
+ 0.0,
199
+ 0.0,
200
+ 0.0,
201
+ 0.0,
202
+ 0.0,
203
+ 0.0,
204
+ 0.0,
205
+ 0.0,
206
+ 0.0,
207
+ 0.0,
208
+ 0.0,
209
+ 0.0,
210
+ 0.0,
211
+ 0.0,
212
+ 0.0,
213
+ 0.0,
214
+ 0.0,
215
+ 0.0,
216
+ 0.0,
217
+ 0.0,
218
+ 0.0,
219
+ 0.0,
220
+ 0.0,
221
+ 0.0,
222
+ 0.0,
223
+ 0.0,
224
+ 0.0,
225
+ 0.0,
226
+ 0.0,
227
+ 0.0,
228
+ 0.0,
229
+ 0.0,
230
+ 0.0,
231
+ 0.0,
232
+ 0.0,
233
+ 0.0,
234
+ 0.0,
235
+ 0.0,
236
+ 0.0,
237
+ 0.0,
238
+ 0.0,
239
+ 0.0,
240
+ 0.0,
241
+ 0.0,
242
+ 0.0,
243
+ 0.0,
244
+ 0.0,
245
+ 0.0,
246
+ 0.0,
247
+ 0.0,
248
+ 0.0,
249
+ 0.0,
250
+ 0.0,
251
+ 0.0,
252
+ 0.0,
253
+ 0.0,
254
+ 0.0,
255
+ 0.0,
256
+ 0.0,
257
+ 0.0,
258
+ 0.0,
259
+ 0.0,
260
+ 0.0,
261
+ 0.0,
262
+ 0.0,
263
+ 0.0,
264
+ 0.0,
265
+ 0.0,
266
+ 0.0,
267
+ 0.0,
268
+ 0.0,
269
+ 0.0,
270
+ 0.0
271
+ ],
272
+ "max": [
273
+ 1.0,
274
+ 1.0,
275
+ 1.0,
276
+ 1.0,
277
+ 1.0,
278
+ 1.0,
279
+ 1.0,
280
+ 1.0,
281
+ 1.0,
282
+ 1.0,
283
+ 1.0,
284
+ 1.0,
285
+ 1.0,
286
+ 1.0,
287
+ 1.0,
288
+ 1.0,
289
+ 1.0,
290
+ 1.0,
291
+ 1.0,
292
+ 1.0,
293
+ 1.0,
294
+ 1.0,
295
+ 1.0,
296
+ 1.0,
297
+ 1.0,
298
+ 1.0,
299
+ 1.0,
300
+ 1.0,
301
+ 1.0,
302
+ 1.0,
303
+ 1.0,
304
+ 1.0,
305
+ 1.0,
306
+ 1.0,
307
+ 1.0,
308
+ 1.0,
309
+ 1.0,
310
+ 1.0,
311
+ 1.0,
312
+ 1.0,
313
+ 1.0,
314
+ 1.0,
315
+ 1.0,
316
+ 1.0,
317
+ 1.0,
318
+ 1.0,
319
+ 1.0,
320
+ 1.0,
321
+ 1.0,
322
+ 1.0,
323
+ 1.0,
324
+ 1.0,
325
+ 1.0,
326
+ 1.0,
327
+ 1.0,
328
+ 1.0,
329
+ 1.0,
330
+ 1.0,
331
+ 1.0,
332
+ 1.0,
333
+ 1.0,
334
+ 1.0,
335
+ 1.0,
336
+ 1.0,
337
+ 1.0,
338
+ 1.0,
339
+ 1.0,
340
+ 1.0,
341
+ 1.0,
342
+ 1.0,
343
+ 1.0,
344
+ 1.0,
345
+ 1.0,
346
+ 1.0,
347
+ 1.0,
348
+ 1.0,
349
+ 1.0,
350
+ 1.0,
351
+ 1.0,
352
+ 1.0,
353
+ 1.0,
354
+ 1.0,
355
+ 1.0,
356
+ 1.0,
357
+ 1.0,
358
+ 1.0,
359
+ 1.0,
360
+ 1.0,
361
+ 1.0,
362
+ 1.0,
363
+ 1.0,
364
+ 1.0,
365
+ 1.0,
366
+ 1.0,
367
+ 1.0,
368
+ 1.0,
369
+ 1.0,
370
+ 1.0,
371
+ 1.0,
372
+ 1.0,
373
+ 1.0,
374
+ 1.0,
375
+ 1.0,
376
+ 1.0,
377
+ 1.0,
378
+ 1.0,
379
+ 1.0,
380
+ 1.0,
381
+ 1.0,
382
+ 1.0,
383
+ 1.0,
384
+ 1.0,
385
+ 1.0,
386
+ 1.0,
387
+ 1.0,
388
+ 1.0,
389
+ 1.0,
390
+ 1.0,
391
+ 1.0,
392
+ 1.0
393
+ ]
394
+ },
395
+ "action_history_decisions": 8,
396
+ "rows_unit": "decision_step",
397
+ "obs_fps": 8.75,
398
+ "obs_stride_raw_frames": 4,
399
+ "latency_prompt_map_path": "/home/ubuntu/lzj/mean-profiling/deadly_corridor/data/lerobot/latency_prompt_map.json",
400
+ "custom_mixtures_path": "/home/ubuntu/lzj/mean-profiling/deadly_corridor/data/_generated_mixtures/lerobot.json",
401
+ "validation_dataset_name": "lerobot__val",
402
+ "validation_episodes": 850,
403
+ "validation_frames": 34465
404
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/profile.source.json ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "burst_model_path": "latency_burst_model.json",
3
+ "distribution_path": "latency_distribution.json",
4
+ "env_fps": 60,
5
+ "frame_ms": 16.666666666666668,
6
+ "gpu_class": "1x-rtx3090",
7
+ "instance_id": "instance_a5037b165aa0cedc",
8
+ "latency_kind": "observation_to_action_latency",
9
+ "latency_method": "temporal",
10
+ "model_id": "openvla",
11
+ "n_admitted_observations": 506,
12
+ "n_capacity_drops": 493,
13
+ "n_observation_attempts": 999,
14
+ "per_slot_summary": {
15
+ "0": {
16
+ "admitted_count": 506,
17
+ "mean_observation_to_action_latency_ms": 73.69250777493353,
18
+ "mean_worker_service_time_ms": 73.00619814047229,
19
+ "p95_observation_to_action_latency_ms": 78.0192643404007,
20
+ "p95_worker_service_time_ms": 76.60398542881012,
21
+ "p99_worker_service_time_ms": 93.66708476543427
22
+ }
23
+ },
24
+ "provenance": {
25
+ "base_config": "configs/experiments/deadly_corridor/starvla_profile.yaml",
26
+ "checkpoint_kind": "best",
27
+ "model_artifact": {
28
+ "checkpoint": "checkpoints/steps_500_state/model.safetensors",
29
+ "model_config": "config.full.yaml",
30
+ "path_in_repo": ".",
31
+ "repo_id": "talha15032/openvla_bridge_deadly_corridor_single_latency_clean_data_bce_exp2",
32
+ "source": "local"
33
+ },
34
+ "session_ids": [
35
+ 0,
36
+ 1,
37
+ 2,
38
+ 3,
39
+ 4
40
+ ]
41
+ },
42
+ "sample_model_type": "hidden_regime",
43
+ "source_run_id": "20260914T171446047509Z",
44
+ "summary": {
45
+ "frame_ms": 16.666666666666668,
46
+ "max_ms": 101.71253681182861,
47
+ "mean_effective_frames": 4.4215504664960115,
48
+ "mean_ms": 73.69250777493353,
49
+ "min_ms": 68.33836698532104,
50
+ "n_samples": 506,
51
+ "p50_frames": 4.3794349193572994,
52
+ "p50_ms": 72.99058198928833,
53
+ "p90_frames": 4.606898102760314,
54
+ "p90_ms": 76.78163504600525,
55
+ "p95_frames": 4.681155860424042,
56
+ "p95_ms": 78.0192643404007,
57
+ "p99_frames": 5.741582728385924,
58
+ "p99_ms": 95.69304547309875,
59
+ "prob_latency_gt_1_frame": 1.0,
60
+ "prob_latency_gt_2_frames": 1.0,
61
+ "prob_latency_gt_3_frames": 1.0,
62
+ "std_ms": 4.766097168829327
63
+ },
64
+ "visualization_path": "latency_profile.png",
65
+ "workload_id": "deadly_corridor"
66
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/provenance.json ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "task": "deadly_corridor",
3
+ "model": "QwenOFT",
4
+ "run_id": "deadly_corridor-qwenoft-mean-3090-s42",
5
+ "training_status": "complete",
6
+ "training_hardware": {
7
+ "gpu": "RTX PRO6000 Blackwell Server Edition",
8
+ "count": 2,
9
+ "physical_indices": [
10
+ 2,
11
+ 3
12
+ ]
13
+ },
14
+ "profile": {
15
+ "mean_ms": 73.69250777493353,
16
+ "profile": "/home/ubuntu/lzj/profiles/published/profiles/openvla/1x-rtx3090/deadly_corridor/instance_a5037b165aa0cedc/profile.json",
17
+ "sha256": "bbfb93cef9f63750a9a159ec10a93a9fc6c25e4cb0cac3b39532663b4dc11eba"
18
+ },
19
+ "profile_hardware": "RTX3090",
20
+ "condition": "fixed_mean_profile",
21
+ "horizon": 1,
22
+ "seed": 42,
23
+ "state_dim": 120,
24
+ "action_dim": 7,
25
+ "micro_per_gpu": 64,
26
+ "gradient_accumulation": 1,
27
+ "global_batch": 128,
28
+ "gradient_checkpointing": true,
29
+ "precision": "BF16",
30
+ "backend": "ZeRO2",
31
+ "teacher": {
32
+ "repo_id": "latency-sensitive-bench/benchmark-models",
33
+ "revision": "3ad793d76cee71c9043e696f7042d89c7cf7f7be",
34
+ "path": "latency-aware/deadly-corridor/small-policy/sample-factory-qwenoft-rtx3090-mean-hist8-capacity1-native35-s42-v1",
35
+ "local_checkpoint": "/home/ubuntu/lzj/mean-profiling/deadly_corridor/teacher-publication/checkpoint.pth",
36
+ "status": "complete_verified",
37
+ "completed_env_steps": 25006080,
38
+ "selected_env_steps": 22239232,
39
+ "selected_source_checkpoint": "/home/ubuntu/lzj/mean-profiling/deadly_corridor/teacher/deadly_corridor_mean_3090_s42/checkpoint_p0/best_000043436_22239232_reward_2141.427.pth",
40
+ "tensor_count": 25,
41
+ "weights_only_export": true,
42
+ "tensor_equality_verified": true,
43
+ "hash_readback_verified": true,
44
+ "url": "https://huggingface.co/latency-sensitive-bench/benchmark-models/tree/3ad793d76cee71c9043e696f7042d89c7cf7f7be/latency-aware/deadly-corridor/small-policy/sample-factory-qwenoft-rtx3090-mean-hist8-capacity1-native35-s42-v1",
45
+ "completed_utc": "2026-09-30T14:07:34.452490+00:00"
46
+ },
47
+ "dataset": {
48
+ "repo_id": "latency-sensitive-bench/Standard-Pipeline",
49
+ "repo_type": "dataset",
50
+ "path": "deadly_corridor/profile_latency/QwenOFT/mean_rtx3090_s42_8500ep_v1",
51
+ "revision": "f33126deefb1d4819a338281cfd4b6db07c8029b",
52
+ "data_uploaded_revision": "57d50aee763da85537762a9e11b0a83bdbe157d7",
53
+ "url": "https://huggingface.co/datasets/latency-sensitive-bench/Standard-Pipeline/tree/f33126deefb1d4819a338281cfd4b6db07c8029b/deadly_corridor/profile_latency/QwenOFT/mean_rtx3090_s42_8500ep_v1",
54
+ "status": "complete_verified",
55
+ "episodes": 8500,
56
+ "rows": 348390,
57
+ "action_history_decisions": 8,
58
+ "payload_files_verified": 26,
59
+ "checksum_manifest_verified": true,
60
+ "dataset_config": "deadly_corridor_profile_latency_mean_qwenoft",
61
+ "completed_utc": "2026-09-30T17:00:12.839189+00:00"
62
+ },
63
+ "collection": {
64
+ "task": "deadly_corridor",
65
+ "teacher_checkpoint": "/home/ubuntu/lzj/mean-profiling/deadly_corridor/teacher-publication/checkpoint.pth",
66
+ "teacher_sha256": "e631e9017634f799860c581761b5fa48601109393c11d20a35187c6f75d14b88",
67
+ "episodes": 8500,
68
+ "train_episodes": 7650,
69
+ "val_episodes": 850,
70
+ "train_rows": 313925,
71
+ "val_rows": 34465,
72
+ "fixed_latency_ms": 73.69250777493353,
73
+ "action_horizon": 1,
74
+ "unique_seeds": 8500,
75
+ "state_dim": 120
76
+ },
77
+ "runtime": {
78
+ "repo": "c3c6a39365a151e9b7a5e215452fd64e957c2b29",
79
+ "starvla": "ccca13c5177fe3d3c884b6e2de4965d916016649",
80
+ "runtime_fixes": [
81
+ "mean-profile-preparation.patch",
82
+ "gym-language-contract.patch",
83
+ "loader-spawn-cache.patch",
84
+ "loader-spawn-test.patch",
85
+ "doom-mean-reset.patch"
86
+ ],
87
+ "pytorch3d": {
88
+ "revision": "33824be3cbc87a7dd1db0f6a9a9de9ac81b2d0ba",
89
+ "build": "transforms-only, no native render extension; QwenOFT uses transforms only"
90
+ },
91
+ "decord": {
92
+ "version": "0.6.0",
93
+ "build": "official source CPU decoder CP310",
94
+ "wheel_sha256": "e193b356b1e984b4eff08d23b62e482c2c9e5037a6efdc0b1af47079ae2e4c47"
95
+ }
96
+ },
97
+ "source_reference_revision": "180da0effdaaaeacef218cf5fbaa4db41af67495",
98
+ "performance_configuration_policy": "User authorized throughput priority; reference scientific parameters and actual runtime differences are documented by full config/launch audit",
99
+ "training_results": {
100
+ "training_complete": true,
101
+ "optimizer_updates": 5000,
102
+ "selection": "final_5000",
103
+ "train_loss": 0.021038614213466644,
104
+ "validation_action_loss": 0.020563077181577682,
105
+ "validation_samples": 6400,
106
+ "final_learning_rates": {
107
+ "learning_rate/qwen_vl_interface": 1e-07,
108
+ "learning_rate/action_model": 3.3333333333333333e-06
109
+ },
110
+ "closed_loop_evaluation": "pending until all four VLA trainings complete",
111
+ "tensor_keys": 732,
112
+ "serialized_tensor_elements_including_tied_aliases": 4892704775,
113
+ "weights_only_load": "passed",
114
+ "all_tensors_finite": true
115
+ },
116
+ "optimizer_recovery_states": "retained on host; inference weights only in this bundle",
117
+ "wandb_url": "https://wandb.ai/dongqianyu99-zhejiang-university/starvla_tasks/runs/mean3090-deadly_corridor-vla-blackwell-20260930"
118
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/startup_verified.json ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "snapshot_utc": "2026-09-30T17:53:52Z",
3
+ "unit": "mean-profile-deadly-vla-20261001-g23-gc.service",
4
+ "wrapper_pid": 684260,
5
+ "rank_pids": [
6
+ 684642,
7
+ 684643
8
+ ],
9
+ "physical_gpus": [
10
+ 2,
11
+ 3
12
+ ],
13
+ "formal_optimizer_updates_completed": 60,
14
+ "formal_optimizer_budget": 5000,
15
+ "consecutive_logged_steps": [
16
+ 58,
17
+ 59,
18
+ 60
19
+ ],
20
+ "loss_at_steps": {
21
+ "58": 0.19479253888130188,
22
+ "59": 0.22210891544818878,
23
+ "60": 0.21452346444129944
24
+ },
25
+ "finite_loss_verified": true,
26
+ "micro_per_gpu": 64,
27
+ "gradient_accumulation": 1,
28
+ "global_batch": 128,
29
+ "gradient_checkpointing": true,
30
+ "gpu_used_mib": [
31
+ 62855,
32
+ 64315
33
+ ],
34
+ "gpu_utilization_percent": [
35
+ 100,
36
+ 100
37
+ ],
38
+ "host_memory_current_bytes": 17238425600,
39
+ "host_memory_peak_bytes": 38296047616,
40
+ "host_memory_high_gib": 128,
41
+ "host_memory_max_gib": 192,
42
+ "memory_events": {
43
+ "low": 0,
44
+ "high": 0,
45
+ "max": 0,
46
+ "oom": 0,
47
+ "oom_kill": 0,
48
+ "oom_group_kill": 0
49
+ },
50
+ "seconds_per_update_recent": 2.31,
51
+ "data_wait_seconds_recent": 0.00065365,
52
+ "estimated_remaining_hours_including_validation_saving": [
53
+ 3.5,
54
+ 4.0
55
+ ],
56
+ "estimated_completion_utc_range": [
57
+ "2026-09-30T21:25:00Z",
58
+ "2026-09-30T21:55:00Z"
59
+ ],
60
+ "completion_check_utc": "2026-09-30T22:15:00Z",
61
+ "training_complete": false,
62
+ "closed_loop_evaluation_complete": false,
63
+ "publication_complete": false
64
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/summary.jsonl ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {"steps": 500}
2
+ {"steps": 1000}
3
+ {"steps": 1500}
4
+ {"steps": 2000}
5
+ {"steps": 2500}
6
+ {"steps": 3000}
7
+ {"steps": 3500}
8
+ {"steps": 4000}
9
+ {"steps": 4500}
10
+ {"steps": 5000}
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/task_contract.json ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "task": "deadly_corridor",
3
+ "model": "qwenoft",
4
+ "action_horizon": 1,
5
+ "image_frames": 1,
6
+ "state_source": "transport",
7
+ "state_dim": 120,
8
+ "history_decisions": 8,
9
+ "history_encoding": "binary_0_1",
10
+ "history_normalization": "identity",
11
+ "history_reset": "all_zero",
12
+ "history_order": "oldest_to_newest",
13
+ "history_entry_fields": [
14
+ "admission_bit",
15
+ "admitted_command_non_noop_bits",
16
+ "last_applied_action_non_noop_bits"
17
+ ],
18
+ "history_action_bit_order": [
19
+ "TURN_LEFT",
20
+ "TURN_RIGHT",
21
+ "MOVE_FORWARD",
22
+ "MOVE_BACKWARD",
23
+ "MOVE_LEFT",
24
+ "MOVE_RIGHT",
25
+ "ATTACK"
26
+ ],
27
+ "action_dim": 7,
28
+ "action_layout": "multibinary_7",
29
+ "action_labels": [
30
+ "MOVE_FORWARD",
31
+ "MOVE_BACKWARD",
32
+ "MOVE_LEFT",
33
+ "MOVE_RIGHT",
34
+ "TURN_LEFT",
35
+ "TURN_RIGHT",
36
+ "ATTACK"
37
+ ],
38
+ "task_prompts": [
39
+ "You are playing Deadly Corridor in VizDoom. Your goal is to survive the corridor, fight enemies, and reach the green armor vest at the far end. The available actions are: MOVE_FORWARD, MOVE_BACKWARD, MOVE_LEFT, MOVE_RIGHT, TURN_LEFT, TURN_RIGHT, and ATTACK. Choose the best next action from the current visual observation."
40
+ ],
41
+ "env_fps": 35,
42
+ "obs_fps": 8.75,
43
+ "evaluation": {
44
+ "episodes": 100,
45
+ "seeds": [
46
+ 1000000,
47
+ 1000099
48
+ ],
49
+ "parallel_envs": 32,
50
+ "capacity": 1,
51
+ "max_raw_frames": 3600,
52
+ "protocol_version": "hist8-history01-sf-render-v4"
53
+ },
54
+ "rendering": {
55
+ "screen_resolution": "RES_160X120",
56
+ "render_hud": true,
57
+ "render_crosshair": false,
58
+ "render_weapon": true,
59
+ "render_decals": false,
60
+ "render_particles": false
61
+ }
62
+ }
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/QWen3.py ADDED
@@ -0,0 +1,444 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 starVLA community. All rights reserved.
2
+ # Licensed under the MIT License, Version 1.0 (the "License");
3
+ # Implemented by [Jinhui YE / HKUST University] in [2025].
4
+
5
+ import time
6
+ from collections import OrderedDict
7
+ from functools import wraps
8
+ from inspect import signature
9
+ from typing import Optional
10
+
11
+ import torch
12
+ from starVLA.model.profiling import stage_timer as _stage
13
+ from starVLA.training.trainer_utils import initialize_overwatch
14
+ from transformers import AutoProcessor, Qwen3VLForConditionalGeneration
15
+ from transformers.modeling_outputs import CausalLMOutputWithPast
16
+
17
+ logger = initialize_overwatch(__name__)
18
+
19
+ IGNORE_INDEX = -100
20
+ IMAGE_TOKEN_INDEX = 151655
21
+ VIDEO_TOKEN_INDEX = 151656
22
+ DEFAULT_IMAGE_TOKEN = "<image>"
23
+ DEFAULT_VIDEO_TOKEN = "<video>"
24
+
25
+ _ACTION_TOKEN_MIN = 151669 # how can we know this range? check how you add fast tokens into VLM
26
+ _ACTION_TOKEN_MAX = (
27
+ 153716 # here only for fast_tokenizer, see starVLA/model/modules/vlm/tools/add_qwen_special_tokens/README.md
28
+ )
29
+
30
+
31
+ import torch.nn as nn
32
+
33
+
34
+ def _patch_qwen3vl_flash_attention_position_ids() -> None:
35
+ from transformers.models.qwen3_vl import modeling_qwen3_vl as qwen3_vl
36
+
37
+ text_attention_cls = qwen3_vl.Qwen3VLTextAttention
38
+ if hasattr(text_attention_cls, "_starvla_flash_attention_position_ids_patched"):
39
+ return
40
+
41
+ original_forward = text_attention_cls.forward
42
+
43
+ def forward_without_flash_attention_position_ids(self, *args, **kwargs):
44
+ # Qwen3-VL already applies M-RoPE through position_embeddings before
45
+ # attention. Passing the repeated temporal M-RoPE ids into HF's FA2
46
+ # wrapper makes Transformers 4.57 mis-detect packed sequences and build
47
+ # empty cu_seqlens on KV-memory cache steps.
48
+ if self.config._attn_implementation == "flash_attention_2" and "position_ids" in kwargs:
49
+ del kwargs["position_ids"]
50
+ return original_forward(self, *args, **kwargs)
51
+
52
+ text_attention_cls.forward = forward_without_flash_attention_position_ids
53
+ text_attention_cls._starvla_flash_attention_position_ids_patched = True
54
+
55
+
56
+ # The fixed Triton stage counts keep the PyTorch 2.11 CUDA 12.8 kernel
57
+ # within the shared-memory budget on sm_120.
58
+ _FLEX_KERNEL_OPTIONS = {
59
+ "BACKEND": "TRITON",
60
+ "fwd_num_stages": 2,
61
+ "bwd_num_stages": 1,
62
+ }
63
+
64
+
65
+ def _patch_qwen3vl_flex_attention_support() -> None:
66
+ """Allow loading Qwen3-VL with ``attn_implementation='flex_attention'``.
67
+
68
+ Qwen3-VL's attention already dispatches through the generic
69
+ ``ALL_ATTENTION_FUNCTIONS`` interface (which includes the ``flex_attention``
70
+ integration), but the model classes conservatively declare
71
+ ``_supports_flex_attn = False``, so Transformers 4.57 refuses to load with
72
+ flex at __init__. Flipping the flag lets the official dispatch path run; the
73
+ packed KV-memory training (`QwenOFT._forward_memory_packed`) passes a
74
+ BlockMask that FlexAttention consumes natively.
75
+
76
+ Also wraps the registered ``flex_attention`` interface to inject the fixed
77
+ Triton kernel options. Wrapping the dispatch entry — rather than threading
78
+ ``kernel_options`` through the top-level forward kwargs — guarantees both the
79
+ forward and the gradient-checkpointing backward recompile pick it up.
80
+ """
81
+ from transformers.models.qwen3_vl import modeling_qwen3_vl as qwen3_vl
82
+
83
+ for cls_name in (
84
+ "Qwen3VLForConditionalGeneration",
85
+ "Qwen3VLModel",
86
+ "Qwen3VLTextModel",
87
+ "Qwen3VLPreTrainedModel",
88
+ ):
89
+ cls = getattr(qwen3_vl, cls_name, None)
90
+ if cls is not None:
91
+ cls._supports_flex_attn = True
92
+
93
+ from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
94
+
95
+ base_flex = ALL_ATTENTION_FUNCTIONS["flex_attention"]
96
+ if getattr(base_flex, "_starvla_kernel_options_patched", False):
97
+ return
98
+
99
+ def flex_attention_with_kernel_options(*args, **kwargs):
100
+ kwargs["kernel_options"] = _FLEX_KERNEL_OPTIONS
101
+ return base_flex(*args, **kwargs)
102
+
103
+ flex_attention_with_kernel_options._starvla_kernel_options_patched = True
104
+ ALL_ATTENTION_FUNCTIONS["flex_attention"] = flex_attention_with_kernel_options
105
+
106
+
107
+ def _position_tensor_key(tensor):
108
+ if tensor is None:
109
+ return None
110
+ return (tensor.device, tensor.dtype, tuple(tensor.shape),
111
+ tuple(tensor.detach().cpu().reshape(-1).tolist()))
112
+
113
+
114
+ def _cache_position_method(module, name, weight):
115
+ """Cache layout-only outputs on one native model instance, never image features."""
116
+ original = getattr(module, name)
117
+ parameters = signature(original)
118
+ cache = OrderedDict()
119
+
120
+ @wraps(original)
121
+ def cached(*args, **kwargs):
122
+ if module.training or torch.is_grad_enabled():
123
+ cache.clear()
124
+ return original(*args, **kwargs)
125
+ arguments = parameters.bind(*args, **kwargs)
126
+ arguments.apply_defaults()
127
+ parameter = weight()
128
+ key = (
129
+ parameter.device, parameter.dtype, parameter._version,
130
+ tuple(_position_tensor_key(value) for value in arguments.arguments.values()),
131
+ )
132
+ if key not in cache:
133
+ cache[key] = original(*args, **kwargs)
134
+ if len(cache) > 8:
135
+ cache.popitem(last=False)
136
+ cache.move_to_end(key)
137
+ return cache[key]
138
+
139
+ setattr(module, name, cached)
140
+ return cache
141
+
142
+
143
+ class _QWen3_VL_Interface(nn.Module):
144
+ """
145
+ This exists because of the diversity of VLMs, so we encapsulate the changes here.
146
+ Lightweight wrapper around Qwen3-VL (Qwen3VLForConditionalGeneration).
147
+
148
+ Purpose:
149
+ - Unify interface with other VLM backends (CausalLM-like usage).
150
+ - Centralize preprocessing (tokenization + multimodal packing).
151
+ - Provide consistent forward / generate signatures.
152
+
153
+ """
154
+
155
+ def __init__(self, config: Optional[dict] = None, **kwargs):
156
+ """
157
+ Initialize the Qwen3-VL wrapper.
158
+ Following https://huggingface.co/Qwen/Qwen3-VL-4B-Instruct
159
+
160
+ """
161
+ super().__init__()
162
+
163
+ qwenvl_config = config.framework.get("qwenvl", {})
164
+ model_id = qwenvl_config.get("base_vlm", "Qwen/Qwen3-VL-4B-Instruct")
165
+ attn_implementation = qwenvl_config.get("attn_implementation", "sdpa")
166
+ enable_grad_ckpt = qwenvl_config.get("enable_gradient_checkpointing", False)
167
+ print(
168
+ f"[QWen3] loading {model_id} with gradient_checkpointing={enable_grad_ckpt}",
169
+ flush=True,
170
+ )
171
+
172
+ if attn_implementation == "flash_attention_2":
173
+ import flash_attn_2_cuda # noqa: F401
174
+
175
+ _patch_qwen3vl_flash_attention_position_ids()
176
+
177
+ if attn_implementation == "flex_attention":
178
+ _patch_qwen3vl_flex_attention_support()
179
+
180
+ model = Qwen3VLForConditionalGeneration.from_pretrained(
181
+ model_id,
182
+ attn_implementation=attn_implementation,
183
+ dtype=torch.bfloat16,
184
+ ignore_mismatched_sizes=True, # resize image no longer needed? @TODO check bug
185
+ )
186
+ processor = AutoProcessor.from_pretrained(model_id)
187
+ processor.tokenizer.padding_side = "left"
188
+
189
+ if enable_grad_ckpt:
190
+ model.config.text_config.use_cache = False
191
+ model.gradient_checkpointing_enable(
192
+ gradient_checkpointing_kwargs={"use_reentrant": False}
193
+ )
194
+ model.enable_input_require_grads()
195
+ print(
196
+ "[QWen3] gradient_checkpointing ENABLED "
197
+ f"(use_reentrant=False, active={model.is_gradient_checkpointing}, "
198
+ f"text_use_cache={model.config.text_config.use_cache})",
199
+ flush=True,
200
+ )
201
+
202
+ self.model = model
203
+ self.processor = processor
204
+ self.config = config
205
+ # align qwen3 with qwen2.5
206
+ self.model.config.hidden_size = self.model.config.text_config.hidden_size
207
+ self._last_build_timing = {}
208
+ visual = model.model.visual
209
+ self._position_caches = [
210
+ _cache_position_method(model.model, "get_rope_index", lambda: visual.rotary_pos_emb.inv_freq),
211
+ _cache_position_method(visual, "rot_pos_emb", lambda: visual.rotary_pos_emb.inv_freq),
212
+ _cache_position_method(visual, "fast_pos_embed_interpolate", lambda: visual.pos_embed.weight),
213
+ ]
214
+
215
+ # only for fast base model
216
+ if "-Action" in model_id:
217
+ self._ACTION_TOKEN_MIN = _ACTION_TOKEN_MIN
218
+ self._ACTION_TOKEN_MAX = _ACTION_TOKEN_MAX
219
+
220
+ def _clear_position_caches(self):
221
+ for cache in self._position_caches:
222
+ cache.clear()
223
+
224
+ def train(self, mode=True):
225
+ self._clear_position_caches()
226
+ return super().train(mode)
227
+
228
+ def _apply(self, fn, recurse=True):
229
+ self._clear_position_caches()
230
+ return super()._apply(fn, recurse=recurse)
231
+
232
+ def _load_from_state_dict(self, *args, **kwargs):
233
+ self._clear_position_caches()
234
+ return super()._load_from_state_dict(*args, **kwargs)
235
+
236
+ def _profile_timing_enabled(self) -> bool:
237
+ return self.config.trainer.profile_timing.enabled
238
+
239
+ def _profile_sync(self) -> None:
240
+ if self._profile_timing_enabled() and torch.cuda.is_available():
241
+ torch.cuda.synchronize()
242
+
243
+ def forward(
244
+ self,
245
+ **kwargs,
246
+ ) -> CausalLMOutputWithPast:
247
+ """
248
+ Forward pass delegating to underlying Qwen2.5-VL backbone.
249
+ """
250
+
251
+ with torch.autocast("cuda", dtype=torch.bfloat16):
252
+ outputs = self.model(
253
+ **kwargs,
254
+ )
255
+
256
+ return outputs
257
+
258
+ def forward_last_hidden(self, **kwargs) -> torch.Tensor:
259
+ """
260
+ Run the Qwen3-VL backbone and return only the final hidden state.
261
+
262
+ OFT-style action heads only consume the last hidden layer. Calling the
263
+ full conditional-generation wrapper with ``output_hidden_states=True``
264
+ returns every layer's activations, which can largely erase the memory
265
+ benefit of gradient checkpointing.
266
+ """
267
+
268
+ kwargs = dict(kwargs)
269
+ kwargs.pop("output_hidden_states", None)
270
+ kwargs.pop("output_attentions", None)
271
+ kwargs.setdefault("return_dict", True)
272
+ kwargs.setdefault("use_cache", False)
273
+
274
+ def _wrapper_forward_last_hidden() -> torch.Tensor:
275
+ lm_head = getattr(self.model, "lm_head", None)
276
+ captured = {}
277
+ handle = None
278
+ if lm_head is not None:
279
+ def _capture_lm_head_input(_module, inputs):
280
+ captured["last_hidden"] = inputs[0]
281
+
282
+ handle = lm_head.register_forward_pre_hook(_capture_lm_head_input)
283
+
284
+ with torch.autocast("cuda", dtype=torch.bfloat16):
285
+ try:
286
+ outputs = self.model(
287
+ **kwargs,
288
+ output_attentions=False,
289
+ output_hidden_states=False,
290
+ return_dict=True,
291
+ )
292
+ finally:
293
+ if handle is not None:
294
+ handle.remove()
295
+
296
+ if "last_hidden" in captured:
297
+ return captured["last_hidden"]
298
+
299
+ # Last-resort compatibility path for unusual model wrappers that do
300
+ # not expose lm_head. This preserves correctness, but returns every
301
+ # layer and therefore saves less memory.
302
+ with torch.autocast("cuda", dtype=torch.bfloat16):
303
+ outputs = self.model(
304
+ **kwargs,
305
+ output_attentions=False,
306
+ output_hidden_states=True,
307
+ return_dict=True,
308
+ )
309
+ return outputs.hidden_states[-1]
310
+
311
+ backbone = getattr(self.model, "model", None)
312
+ if backbone is None:
313
+ return _wrapper_forward_last_hidden()
314
+
315
+ try:
316
+ with torch.autocast("cuda", dtype=torch.bfloat16):
317
+ outputs = backbone(**kwargs)
318
+ except TypeError:
319
+ # Some Transformers Qwen-VL wrappers inject visual embeddings before
320
+ # calling the text backbone, so the backbone itself may not accept
321
+ # pixel_values/image_grid_thw. Keep those versions working.
322
+ return _wrapper_forward_last_hidden()
323
+
324
+ if hasattr(outputs, "last_hidden_state"):
325
+ return outputs.last_hidden_state
326
+ return outputs[0]
327
+
328
+ def generate(
329
+ self,
330
+ **kwargs,
331
+ ):
332
+ """
333
+ High-level generation interface (auto-regressive decoding), optionally vision-conditioned.
334
+
335
+ Args:
336
+ **kwargs: fully follow raw model.generate() signature.
337
+ Returns:
338
+ GenerateOutput | Model-dependent generation return.
339
+ """
340
+ with torch.autocast("cuda", dtype=torch.float16):
341
+ generation_output = self.model.generate(
342
+ **kwargs,
343
+ )
344
+ return generation_output
345
+
346
+ def build_qwenvl_inputs(self, images, instructions, solutions=None, profiler=None, **kwargs):
347
+ """
348
+ Build model inputs from raw data (images + instructions + optional solutions).
349
+ Follow Oficial Qwen3-VL Instruct format: https://huggingface.co/Qwen/Qwen3-VL-4B-Instruct
350
+ """
351
+
352
+ # Create messages: one message per sample
353
+ with _stage(profiler, "starvla_qwen_message_build_ms"):
354
+ messages = []
355
+ assert len(images) == len(instructions), "Images and instructions must have the same length"
356
+ for imgs, instruction in zip(images, instructions):
357
+ content = [{"type": "image", "image": img} for img in imgs]
358
+
359
+ if "CoT_prompt" in self.config.datasets.vla_data: # If using a grounding prompt to task
360
+ CoT_prompt = self.config.datasets.vla_data.get("CoT_prompt", "")
361
+ prompt = CoT_prompt.replace("{instruction}", instruction)
362
+ else:
363
+ prompt = instruction
364
+
365
+ content.append({"type": "text", "text": prompt})
366
+ msg = [{"role": "user", "content": content}]
367
+
368
+ if solutions is not None:
369
+ solution = solutions[len(messages)]
370
+ msg.append({"role": "assistant", "content": [{"type": "text", "text": solution}]})
371
+ messages.append(msg)
372
+
373
+ profile_timing = self._profile_timing_enabled()
374
+ build_timing = {}
375
+
376
+ t_processor = time.perf_counter() if profile_timing else None
377
+ with _stage(profiler, "starvla_qwen_processor_ms"):
378
+ batch_inputs = self.processor.apply_chat_template(
379
+ messages, tokenize=True, padding=True, add_generation_prompt=True, return_dict=True, return_tensors="pt"
380
+ )
381
+ if profile_timing:
382
+ build_timing["timing/qwen_processor"] = time.perf_counter() - t_processor
383
+
384
+ # if solutions, mask out the solution tokens in labels
385
+ if solutions is not None: # here only for fast_tokenizer now.
386
+ action_token_min = _ACTION_TOKEN_MIN # how can we know this range? --> we has other way for this, but is slower see qwenhelix branch
387
+ action_token_max = _ACTION_TOKEN_MAX # here only for fast_tokenizer, see starVLA/model/modules/vlm/tools/add_qwen_special_tokens/README.md
388
+ labels = batch_inputs["input_ids"].clone()
389
+ # For each sequence in the batch, find the first occurrence of an action token.
390
+ for i in range(labels.size(0)):
391
+ seq = labels[i]
392
+ # Create a mask for tokens within the action token range.
393
+ mask_seq = (seq >= action_token_min) & (seq <= action_token_max)
394
+ nonzero_indices = torch.nonzero(mask_seq, as_tuple=False)
395
+ if nonzero_indices.numel() > 0:
396
+ first_action_index = nonzero_indices[0].item()
397
+ # Mask out all tokens before the first action token.
398
+ seq[:first_action_index] = IGNORE_INDEX
399
+ else:
400
+ # If no action token is found, mask the entire sequence.
401
+ seq[:] = IGNORE_INDEX
402
+ RuntimeWarning(
403
+ "action token are on in yout tokenizer, plz see starVLA/model/modules/vlm/tools/add_qwen_special_tokens/README.md."
404
+ )
405
+
406
+ labels[labels == self.processor.tokenizer.pad_token_id] = -100 ## mask out pad tokens as well
407
+ batch_inputs["labels"] = labels
408
+
409
+ t_h2d = time.perf_counter() if profile_timing else None
410
+ with _stage(profiler, "starvla_qwen_h2d_ms"):
411
+ batch_inputs = batch_inputs.to(self.model.device)
412
+ if profile_timing:
413
+ self._profile_sync()
414
+ build_timing["timing/qwen_h2d"] = time.perf_counter() - t_h2d
415
+ self._last_build_timing = build_timing
416
+ return batch_inputs
417
+
418
+
419
+ if __name__ == "__main__":
420
+ import argparse
421
+ import os
422
+
423
+ from omegaconf import OmegaConf
424
+
425
+ parser = argparse.ArgumentParser()
426
+ parser.add_argument(
427
+ "--config_yaml",
428
+ type=str,
429
+ default="examples/SimplerEnv/train_files/starvla_cotrain_oxe.yaml",
430
+ help="Path to YAML config",
431
+ )
432
+ args, clipargs = parser.parse_known_args()
433
+
434
+ if os.getenv("DEBUGPY_ENABLE", "0") == "1":
435
+ import debugpy
436
+ debugpy.listen(("0.0.0.0", 10092))
437
+ print("Rank 0 waiting for debugger attach on port 10092...")
438
+ debugpy.wait_for_client()
439
+
440
+ cfg = OmegaConf.load(args.config_yaml)
441
+
442
+ cfg.framework.qwenvl.base_vlm = "./playground/Pretrained_models/Qwen3-VL-4B-Instruct"
443
+ qwen_vl = _QWen3_VL_Interface(cfg)
444
+ pass
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/QwenOFT.py ADDED
@@ -0,0 +1,1244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 starVLA community. All rights reserved.
2
+ # Licensed under the MIT License, Version 1.0 (the "License");
3
+ # Implemented by [Jinhui YE / HKUST University] in [2025].
4
+
5
+ """
6
+ Qwen-OFT Framework
7
+
8
+ A lightweight implementation that uses an action special token to parallelly predict continuous actions
9
+ conditioned on multi-view images plus a language instruction (shares parameters with the VLM).
10
+ Inspired by OpenVLA-OFT
11
+ Key Points:
12
+ - Qwen2.5 vision-language backbone
13
+ - Injects an action special token into the VLM
14
+ - Continuous action prediction via L1 regression over the action special token hidden states
15
+
16
+
17
+ Note: How to add special tokens to Qwen2.5:
18
+ download our model checkpoint with special tokens added: https://huggingface.co/StarVLA/Qwen2.5-VL-3B-Instruct-Action
19
+ or /starVLA/model/modules/vlm/tools/add_qwen_special_tokens/README.md (adpat a little code)
20
+
21
+ """
22
+
23
+ from dataclasses import dataclass, field
24
+ import time
25
+ from typing import Any, List, Optional, Tuple
26
+
27
+ import numpy as np
28
+ import torch
29
+ import torch.nn as nn
30
+ import torch.nn.functional as F
31
+ from PIL import Image
32
+
33
+ from deployment.model_server.tools.image_tools import to_pil_preserve
34
+ from starVLA.model.tools import FRAMEWORK_REGISTRY
35
+ from starVLA.training.trainer_utils import initialize_overwatch
36
+
37
+ logger = initialize_overwatch(__name__)
38
+
39
+ # HuggingFace Default / LLaMa-2 IGNORE_INDEX (for labels)
40
+ IGNORE_INDEX = -100
41
+
42
+ from starVLA.model.framework.base_framework import baseframework
43
+ from starVLA.model.framework.share_tools import add_discretized_state_to_instruction, merge_framework_config
44
+ from starVLA.model.modules.action_model.MLP_ActionHeader import get_action_model
45
+ from starVLA.model.modules.vlm import get_vlm_model
46
+ from starVLA.training.trainer_utils.trainer_tools import resize_images
47
+
48
+
49
+ # ──────────────────────────────────────────────────────────────────────
50
+ # Default Config for QwenOFT
51
+ # - Documents every framework-level parameter with type + description
52
+ # - YAML values override these defaults; extra YAML keys are preserved
53
+ # ──────────────────────────────────────────────────────────────────────
54
+ @dataclass
55
+ class QwenOFTDefaultConfig:
56
+ """QwenOFT framework default parameters.
57
+
58
+ All fields can be overridden by the corresponding key in the YAML
59
+ ``framework:`` section. Extra YAML keys not listed here are kept
60
+ as-is (Config-as-API flexibility).
61
+ """
62
+
63
+ # --- Registry identifier (must match @FRAMEWORK_REGISTRY.register) ---
64
+ name: str = "QwenOFT"
65
+
66
+ # === VLM backbone (Qwen2.5-VL / Qwen3-VL) ===
67
+ qwenvl: dict = field(
68
+ default_factory=lambda: {
69
+ # Path to base VLM checkpoint (local or HF hub id)
70
+ "base_vlm": "./playground/Pretrained_models/Qwen3-VL-4B-Instruct-Action",
71
+ # Attention implementation: "flash_attention_2" | "eager" | "sdpa"
72
+ "attn_implementation": "flash_attention_2",
73
+ }
74
+ )
75
+
76
+ # === Action head (MLP regression over action special tokens) ===
77
+ action_model: dict = field(
78
+ default_factory=lambda: {
79
+ # Action head architecture type
80
+ "action_model_type": "MLP",
81
+ # Dimensionality of each action vector (e.g., 7 for 6-DoF + gripper)
82
+ "action_dim": 7,
83
+ # Proprioceptive state dimension for continuous_projector mode
84
+ "state_dim": 7,
85
+ # Hidden dim for the action MLP (auto-set from VLM hidden_size at runtime)
86
+ "action_hidden_dim": 2560,
87
+ # How many future steps to predict
88
+ "future_action_window_size": 8,
89
+ # How many past steps included in action chunk (usually 0)
90
+ "past_action_window_size": 0,
91
+ # Loss over predicted actions. Supported: "l1", "discrete_ce",
92
+ # "multibinary_bce", "asterix_factorized_ce".
93
+ # "multibinary_ce" is accepted as a CLI alias for "multibinary_bce".
94
+ "loss_type": "l1",
95
+ # State conditioning: preserve the existing text-bin path by default.
96
+ "state_encoding": "discretized_text",
97
+ }
98
+ )
99
+
100
+
101
+ @FRAMEWORK_REGISTRY.register("QwenOFT")
102
+ class Qwenvl_OFT(baseframework):
103
+ """
104
+ Multimodal vision-language-action model (OFT variant).
105
+
106
+ Components:
107
+ - Qwen2.5-VL / Qwen3-VL backbone for fused language/vision token embeddings
108
+ - Action special token injected into the VLM sequence
109
+ - MLP regression head over action token hidden states (L1 loss)
110
+
111
+ Focus: Predict future continuous actions conditioned on images + instruction.
112
+ """
113
+
114
+ def __init__(
115
+ self,
116
+ config: Optional[dict] = None,
117
+ **kwargs,
118
+ ) -> None:
119
+ """
120
+ Construct all submodules and cache key configuration values.
121
+
122
+ Args:
123
+ config: Hierarchical configuration (OmegaConf/dict) containing framework + trainer sections.
124
+ **kwargs: Reserved for future overrides (unused).
125
+ """
126
+ super().__init__()
127
+ # Merge framework defaults with YAML config (YAML wins on conflicts)
128
+ self.config = merge_framework_config(QwenOFTDefaultConfig, config)
129
+ self.qwen_vl_interface = get_vlm_model(config=self.config)
130
+ # align action_hidden_dim to VLM hidden_size at runtime
131
+ self.config.framework.action_model.action_hidden_dim = self.qwen_vl_interface.model.config.hidden_size
132
+ self.action_model = get_action_model(config=self.config)
133
+
134
+ # `action_horizon` is the single source of truth for chunk length.
135
+ # Legacy aliases (`future_action_window_size`, `past_action_window_size`)
136
+ # are normalised upstream by `share_tools.apply_config_compat`, so we
137
+ # only ever read `action_horizon` here.
138
+ self.action_horizon = int(self.config.framework.action_model.action_horizon)
139
+ self.chunk_len = self.action_horizon
140
+ self.action_dim = int(self.config.framework.action_model.action_dim)
141
+ self.action_env_dim = int(getattr(self.config.framework.action_model, "action_env_dim", self.action_dim))
142
+ self.action_loss_type = str(getattr(self.config.framework.action_model, "loss_type", "l1")).lower()
143
+ self.state_encoding = str(self.config.framework.action_model.state_encoding)
144
+ if self.state_encoding not in {"discretized_text", "continuous_projector"}:
145
+ raise ValueError(f"Unsupported state_encoding: {self.state_encoding}")
146
+ if self.state_encoding == "continuous_projector":
147
+ self.action_model.state_projector = nn.Linear(
148
+ int(self.config.framework.action_model.state_dim),
149
+ int(self.config.framework.action_model.action_hidden_dim),
150
+ )
151
+ cross_task_cfg = getattr(getattr(self.config, "rl_games", None), "cross_task", None)
152
+ self.loss_by_task = self._to_plain_dict(getattr(cross_task_cfg, "loss_by_task", None))
153
+ self.loss_weight_by_task = self._to_plain_dict(getattr(cross_task_cfg, "loss_weight_by_task", None))
154
+ # self.hidden_dim = config.framework.action_model.action_hidden_dim
155
+
156
+ self.action_token = "🔍" # TODO also can add spacail token to Qwen, but too complex
157
+ self.action_token_id = self.qwen_vl_interface.processor.tokenizer("🔍", add_special_tokens=False)["input_ids"][0]
158
+
159
+ # --- Fixed-size KV memory; default OFF so existing paths are untouched. ---
160
+ kv_cfg = getattr(self.config.framework, "kv_memory", None)
161
+ self.kv_memory_enabled = bool(getattr(kv_cfg, "enabled", False)) if kv_cfg is not None else False
162
+ self.kv_window = int(getattr(kv_cfg, "window", 4)) if kv_cfg is not None else 4
163
+ self.kv_rollout_len = int(getattr(kv_cfg, "rollout_len", max(self.kv_window + 1, 2))) if kv_cfg is not None else self.kv_window + 1
164
+ # Packed single-forward training path (StreamingLLM-style sliding-window+sink
165
+ # mask via FlexAttention) — replaces the per-frame Python loop. Eval/live still
166
+ # uses the streaming KV memory (`_predict_action_memory`). OFF by default so the
167
+ # legacy loop stays the reference; enable per experiment via
168
+ # `framework.kv_memory.packed_train: true`.
169
+ self.kv_train_packed = bool(getattr(kv_cfg, "packed_train", False)) if kv_cfg is not None else False
170
+ # Per-step re-based sink for the packed path: replicate the (short) text
171
+ # prefix once per step and re-base its M-RoPE positions so the sink→frame
172
+ # distance matches the eval rolling-KV layout exactly (StreamingLLM
173
+ # "positions within the cache"), instead of one global sink whose distance
174
+ # grows with the step index. ON by default — the growing-distance sink was
175
+ # the train/eval forward mismatch behind the packed run's eval collapse.
176
+ # Set false to fall back to the single global sink for A/B.
177
+ self.kv_rebased_sink = bool(getattr(kv_cfg, "rebased_sink", True)) if kv_cfg is not None else True
178
+ if self.state_encoding == "continuous_projector" and self.kv_memory_enabled:
179
+ raise ValueError("continuous_projector requires framework.kv_memory.enabled=false")
180
+ # Per-stream (eval slot) memories; rebuilt per sample during training.
181
+ self._kv_memories: dict = {}
182
+
183
+ # L1 loss
184
+ self.l1_loss = nn.L1Loss()
185
+
186
+ def _profile_timing_enabled(self) -> bool:
187
+ return self.config.trainer.profile_timing.enabled
188
+
189
+ def _profile_sync(self) -> None:
190
+ if self._profile_timing_enabled() and torch.cuda.is_available():
191
+ torch.cuda.synchronize()
192
+
193
+ def _profile_start(self) -> float:
194
+ self._profile_sync()
195
+ return time.perf_counter()
196
+
197
+ def _profile_elapsed(self, start: float) -> float:
198
+ self._profile_sync()
199
+ return time.perf_counter() - start
200
+
201
+ @staticmethod
202
+ def _to_plain_dict(value: Any) -> dict[str, Any]:
203
+ if value is None or value == "":
204
+ return {}
205
+ if isinstance(value, dict):
206
+ return {str(key): item for key, item in value.items()}
207
+ if hasattr(value, "items"):
208
+ return {str(key): item for key, item in value.items()}
209
+ return {}
210
+
211
+ def _prepare_action_array(self, action: Any) -> np.ndarray:
212
+ values = np.asarray(action)
213
+ if values.ndim == 1:
214
+ values = values[None, :]
215
+ if values.shape[-1] == self.action_dim:
216
+ return values
217
+ if values.shape[-1] > self.action_dim:
218
+ return values[..., : self.action_dim]
219
+ pad_width = [(0, 0)] * values.ndim
220
+ pad_width[-1] = (0, self.action_dim - values.shape[-1])
221
+ return np.pad(values, pad_width, mode="constant")
222
+
223
+ def _compute_action_loss_for_type(
224
+ self,
225
+ pred_actions: torch.Tensor,
226
+ actions_target: torch.Tensor,
227
+ *,
228
+ loss_type: str,
229
+ action_env_dims: Optional[List[int]] = None,
230
+ ) -> torch.Tensor:
231
+ loss_type = str(loss_type).lower()
232
+ effective_dim = min(self.action_env_dim, pred_actions.shape[-1], actions_target.shape[-1])
233
+ if effective_dim <= 0:
234
+ raise ValueError(
235
+ f"Invalid action_env_dim={self.action_env_dim} for predicted shape={pred_actions.shape} "
236
+ f"and target shape={actions_target.shape}"
237
+ )
238
+
239
+ if loss_type in {"discrete_ce", "ce", "cross_entropy"}:
240
+ if action_env_dims is not None:
241
+ dims = torch.as_tensor(action_env_dims, device=pred_actions.device, dtype=torch.long)
242
+ if dims.numel() != pred_actions.shape[0]:
243
+ raise ValueError(f"Expected {pred_actions.shape[0]} action_env_dims, got {dims.numel()}")
244
+ losses = []
245
+ weights = []
246
+ for dim_value in torch.unique(dims).tolist():
247
+ dim = int(min(dim_value, pred_actions.shape[-1], actions_target.shape[-1]))
248
+ if dim < 2:
249
+ raise ValueError(f"discrete_ce requires at least 2 classes, got action_env_dim={dim}")
250
+ mask = dims == int(dim_value)
251
+ logits = pred_actions[mask, ..., :dim]
252
+ target_class = actions_target[mask, ..., :dim].argmax(dim=-1).long()
253
+ losses.append(F.cross_entropy(logits.reshape(-1, dim), target_class.reshape(-1), reduction="sum"))
254
+ weights.append(target_class.numel())
255
+ total_weight = max(1, int(sum(weights)))
256
+ return sum(losses) / total_weight
257
+
258
+ if effective_dim < 2:
259
+ raise ValueError(
260
+ f"action_model.loss_type={loss_type!r} requires at least 2 action classes, "
261
+ f"got effective_dim={effective_dim}"
262
+ )
263
+ logits = pred_actions[..., :effective_dim]
264
+ target_class = actions_target[..., :effective_dim].argmax(dim=-1).long()
265
+ return F.cross_entropy(
266
+ logits.reshape(-1, effective_dim),
267
+ target_class.reshape(-1),
268
+ )
269
+
270
+ if loss_type in {"asterix_factorized_ce", "factorized_6_ce", "factorized_ce"}:
271
+ if effective_dim < 6:
272
+ raise ValueError(
273
+ f"action_model.loss_type={loss_type!r} requires at least 6 action logits, "
274
+ f"got effective_dim={effective_dim}"
275
+ )
276
+ vertical_logits = pred_actions[..., 0:3]
277
+ vertical_target = actions_target[..., 0:3].argmax(dim=-1).long()
278
+ horizontal_logits = pred_actions[..., 3:6]
279
+ horizontal_target = actions_target[..., 3:6].argmax(dim=-1).long()
280
+ vertical_loss = F.cross_entropy(
281
+ vertical_logits.reshape(-1, 3),
282
+ vertical_target.reshape(-1),
283
+ )
284
+ horizontal_loss = F.cross_entropy(
285
+ horizontal_logits.reshape(-1, 3),
286
+ horizontal_target.reshape(-1),
287
+ )
288
+ return 0.5 * (vertical_loss + horizontal_loss)
289
+
290
+ if loss_type in {"multibinary_bce", "multibinary_ce", "bce", "binary_cross_entropy"}:
291
+ logits = pred_actions[..., :effective_dim]
292
+ targets = (actions_target[..., :effective_dim] > 0).to(dtype=logits.dtype)
293
+ return F.binary_cross_entropy_with_logits(logits, targets)
294
+
295
+ if loss_type in {"mse", "l2"}:
296
+ return F.mse_loss(
297
+ pred_actions[..., :effective_dim],
298
+ actions_target[..., :effective_dim],
299
+ )
300
+
301
+ if loss_type not in {"l1", "mae"}:
302
+ raise ValueError(
303
+ f"Unsupported action_model.loss_type={loss_type!r}; "
304
+ "expected one of: l1, discrete_ce, multibinary_bce, asterix_factorized_ce"
305
+ )
306
+
307
+ return self.l1_loss(
308
+ pred_actions[..., :effective_dim],
309
+ actions_target[..., :effective_dim],
310
+ )
311
+
312
+ def _compute_action_loss(
313
+ self,
314
+ pred_actions: torch.Tensor,
315
+ actions_target: torch.Tensor,
316
+ action_env_dims: Optional[List[int]] = None,
317
+ rl_games_tasks: Optional[List[str]] = None,
318
+ action_loss_mask: Optional[torch.Tensor] = None,
319
+ ) -> torch.Tensor:
320
+ if action_loss_mask is not None:
321
+ error = (pred_actions[..., :self.action_env_dim] - actions_target[..., :self.action_env_dim]).abs().mean(dim=-1)
322
+ error = error.masked_fill(~action_loss_mask, 0)
323
+ return (error.sum(dim=-1) / action_loss_mask.sum(dim=-1)).mean()
324
+ if self.loss_by_task and rl_games_tasks is not None:
325
+ if len(rl_games_tasks) != pred_actions.shape[0]:
326
+ raise ValueError(f"Expected {pred_actions.shape[0]} task labels, got {len(rl_games_tasks)}")
327
+ losses = []
328
+ weights = []
329
+ for task_name in sorted(set(str(task) for task in rl_games_tasks)):
330
+ mask_values = [str(task) == task_name for task in rl_games_tasks]
331
+ mask = torch.as_tensor(mask_values, device=pred_actions.device, dtype=torch.bool)
332
+ if not bool(mask.any()):
333
+ continue
334
+ task_loss_type = str(self.loss_by_task.get(task_name, self.action_loss_type)).lower()
335
+ task_dims = (
336
+ [int(dim) for dim, keep in zip(action_env_dims, mask_values) if keep]
337
+ if action_env_dims is not None
338
+ else None
339
+ )
340
+ task_loss = self._compute_action_loss_for_type(
341
+ pred_actions[mask],
342
+ actions_target[mask],
343
+ loss_type=task_loss_type,
344
+ action_env_dims=task_dims,
345
+ )
346
+ task_weight = float(self.loss_weight_by_task.get(task_name, 1.0))
347
+ sample_count = int(mask.sum().item())
348
+ losses.append(task_loss * task_weight * sample_count)
349
+ weights.append(task_weight * sample_count)
350
+ if losses:
351
+ return sum(losses) / max(1.0, float(sum(weights)))
352
+
353
+ return self._compute_action_loss_for_type(
354
+ pred_actions,
355
+ actions_target,
356
+ loss_type=self.action_loss_type,
357
+ action_env_dims=action_env_dims,
358
+ )
359
+
360
+ def _forward_qwen_last_hidden(self, qwen_inputs: dict) -> torch.Tensor:
361
+ """
362
+ Return only the final VLM hidden state when the interface supports it.
363
+
364
+ Requesting ``output_hidden_states=True`` from Hugging Face materializes
365
+ every layer's activations. For OFT we only need the last layer, so the
366
+ Qwen3 interface exposes a leaner path that preserves the practical memory
367
+ savings from gradient checkpointing.
368
+ """
369
+
370
+ if hasattr(self.qwen_vl_interface, "forward_last_hidden"):
371
+ return self.qwen_vl_interface.forward_last_hidden(**qwen_inputs)
372
+
373
+ qwenvl_outputs = self.qwen_vl_interface(
374
+ **qwen_inputs,
375
+ output_attentions=False,
376
+ output_hidden_states=True,
377
+ return_dict=True,
378
+ use_cache=False,
379
+ )
380
+ return qwenvl_outputs.hidden_states[-1]
381
+
382
+ def _state_conditioned_instructions(self, instructions, state):
383
+ if state is not None and self.state_encoding == "discretized_text":
384
+ return self.add_discretized_state_to_instruction(instructions, state)
385
+ return instructions
386
+
387
+ def _condition_action_queries(self, action_queries, state):
388
+ if self.state_encoding == "discretized_text":
389
+ return action_queries
390
+ state_tensor = torch.as_tensor(
391
+ np.stack(state), device=action_queries.device, dtype=action_queries.dtype
392
+ ).squeeze(1)
393
+ return action_queries + self.action_model.state_projector(state_tensor).unsqueeze(1)
394
+
395
+ def forward(
396
+ self,
397
+ examples: List[dict] = None,
398
+ **kwargs,
399
+ ) -> Tuple:
400
+ """
401
+ Training forward: directly regress future actions (no diffusion).
402
+
403
+ Flow:
404
+ 1. Build QwenVL inputs (images + instruction tokens)
405
+ 2. Extract hidden states from configured layer range
406
+ 7. Predict action and compute L1 loss
407
+
408
+ Args:
409
+ examples: List[dict], each dict requires:
410
+ - image: List[PIL.Image] (multi-view)
411
+ - lang: str instruction
412
+ - action: np.ndarray or list shaped [T, action_dim]
413
+ **kwargs: Reserved.
414
+
415
+ Returns:
416
+ dict:
417
+ action_loss (torch.Tensor): Scalar diffusion noise prediction loss.
418
+ """
419
+ if self.kv_memory_enabled:
420
+ if self.kv_train_packed:
421
+ return self._forward_memory_packed(examples)
422
+ return self._forward_memory(examples)
423
+
424
+ batch_images = [example["image"] for example in examples] # [B,[PLT]]
425
+ instructions = [example["lang"] for example in examples] # [B, str]
426
+ actions = [self._prepare_action_array(example["action"]) for example in examples] # label [B, len, action_dim]
427
+ action_env_dims = [int(example.get("action_env_dim", self.action_env_dim)) for example in examples]
428
+ rl_games_tasks = [str(example.get("rl_games_task", "")) for example in examples]
429
+ if not any(rl_games_tasks):
430
+ rl_games_tasks = None
431
+ state = (
432
+ [example["state"] for example in examples] if "state" in examples[0] else None
433
+ ) # List[ndarray (1, state_dim)] or None
434
+
435
+ instructions = self._state_conditioned_instructions(instructions, state)
436
+
437
+ # step 0: add special action token to instruction
438
+ action_tokens = (
439
+ self.action_token * self.chunk_len
440
+ ) # can't add " " between two tokens, otherwise will be tokenized to multiple tokens
441
+ prompt_suffix = f" Please predict the next {self.chunk_len} robot actions: <action>{action_tokens}<action>."
442
+ instructions = [instruction + prompt_suffix for instruction in instructions]
443
+
444
+ profile_timing = self._profile_timing_enabled()
445
+ timing_metrics = {}
446
+ batch_stats = {}
447
+
448
+ # Step 1: QWenVL input format
449
+ t_inputs = self._profile_start() if profile_timing else None
450
+ qwen_inputs = self.qwen_vl_interface.build_qwenvl_inputs(images=batch_images, instructions=instructions)
451
+ if profile_timing:
452
+ timing_metrics["timing/qwen_input_build_total"] = self._profile_elapsed(t_inputs)
453
+ timing_metrics.update(self.qwen_vl_interface._last_build_timing)
454
+ input_ids = qwen_inputs["input_ids"]
455
+ attention_mask = qwen_inputs["attention_mask"]
456
+ effective_tokens = attention_mask.sum()
457
+ effective_token_count = effective_tokens.detach().float().item()
458
+ batch_stats["batch/size"] = float(len(examples))
459
+ batch_stats["batch/input_len_max"] = float(input_ids.shape[1])
460
+ batch_stats["batch/input_len_mean"] = float(effective_token_count / input_ids.shape[0])
461
+ batch_stats["batch/padding_ratio"] = float(1.0 - effective_token_count / float(attention_mask.numel()))
462
+ batch_stats["batch/effective_tokens"] = float(effective_token_count)
463
+ batch_stats["batch/image_count"] = float(sum(len(images) for images in batch_images))
464
+ if "pixel_values" in qwen_inputs:
465
+ batch_stats["batch/pixel_values_rows"] = float(qwen_inputs["pixel_values"].shape[0])
466
+
467
+ t_vlm = self._profile_start() if profile_timing else None
468
+ with torch.autocast("cuda", dtype=torch.bfloat16):
469
+ last_hidden = self._forward_qwen_last_hidden(qwen_inputs) # [B, L, H]
470
+ if profile_timing:
471
+ timing_metrics["timing/vlm_forward"] = self._profile_elapsed(t_vlm)
472
+
473
+ # Step 4: Action Expert Forward and Loss
474
+ t_action = self._profile_start() if profile_timing else None
475
+ with torch.autocast("cuda", dtype=torch.float32):
476
+ # Extract action token embeddings as action prediction queries
477
+ input_ids = qwen_inputs["input_ids"]
478
+ action_queries = self._gather_action_token_embeddings(
479
+ last_hidden, input_ids, action_token_id=self.action_token_id
480
+ ) # [B, chunk_len, H]
481
+ action_queries = self._condition_action_queries(action_queries, state)
482
+ pred_actions = self.action_model.predict_action(action_queries) # (B, chunk_len, action_dim)
483
+
484
+ # Label alignment: take the last chunk_len segment
485
+ actions = torch.tensor(
486
+ np.array(actions), device=pred_actions.device, dtype=pred_actions.dtype
487
+ ) # [B, T_full, action_dim]
488
+ actions_target = actions[:, -self.action_horizon :, :] # (B, action_horizon, action_dim)
489
+
490
+ action_loss_mask = None
491
+ if "action_loss_mask" in examples[0]:
492
+ action_loss_mask = torch.as_tensor(
493
+ np.asarray([example["action_loss_mask"] for example in examples]),
494
+ device=pred_actions.device,
495
+ dtype=torch.bool,
496
+ )
497
+
498
+ action_loss = self._compute_action_loss(
499
+ pred_actions,
500
+ actions_target,
501
+ action_env_dims=action_env_dims,
502
+ rl_games_tasks=rl_games_tasks,
503
+ action_loss_mask=action_loss_mask,
504
+ )
505
+ if profile_timing:
506
+ timing_metrics["timing/action_head_loss"] = self._profile_elapsed(t_action)
507
+
508
+ return {"action_loss": action_loss, "loss_weight": float(len(examples)), "timing": timing_metrics, "batch_stats": batch_stats}
509
+
510
+ @torch.inference_mode()
511
+ def predict_action(
512
+ self,
513
+ examples: List[dict] = None,
514
+ **kwargs: str,
515
+ ) -> np.ndarray:
516
+ """
517
+
518
+ Steps:
519
+ 1. Resize images to training resolution (if specified)
520
+ 2. Encode with QwenVL (hidden states retained)
521
+ 6. Return normalized action trajectory
522
+
523
+ Returns:
524
+ dict:
525
+ normalized_actions (np.ndarray): Shape [B, T, action_dim], diffusion-sampled normalized actions.
526
+ """
527
+ if type(examples) is not list:
528
+ examples = [examples]
529
+ if self.kv_memory_enabled:
530
+ return self._predict_action_memory(examples)
531
+ batch_images = [to_pil_preserve(example["image"]) for example in examples] # [B,[PLT]]
532
+ instructions = [example["lang"] for example in examples] # [B, str]
533
+ state = (
534
+ [example["state"] for example in examples] if "state" in examples[0] else None
535
+ ) # List[ndarray (1, state_dim)] or None
536
+
537
+ instructions = self._state_conditioned_instructions(instructions, state)
538
+
539
+ train_obs_image_size = getattr(self.config.datasets.vla_data, "obs_image_size", None)
540
+ if train_obs_image_size:
541
+ batch_images = resize_images(batch_images, target_size=train_obs_image_size)
542
+
543
+ # step 0: add special action token to instruction
544
+ action_tokens = (
545
+ self.action_token * self.chunk_len
546
+ ) # can't add " " between two tokens, otherwise will be tokenized to multiple tokens
547
+ prompt_suffix = f" Please predict the next {self.chunk_len} robot actions: <action>{action_tokens}<action>."
548
+ instructions = [instruction + prompt_suffix for instruction in instructions]
549
+
550
+ # Step 1: QWenVL input format
551
+ qwen_inputs = self.qwen_vl_interface.build_qwenvl_inputs(images=batch_images, instructions=instructions)
552
+ with torch.autocast("cuda", dtype=torch.bfloat16):
553
+ last_hidden = self._forward_qwen_last_hidden(qwen_inputs) # [B, L, H]
554
+
555
+ # Step 4: Action Expert Forward and Loss
556
+ with torch.autocast("cuda", dtype=torch.float32):
557
+ # Extract action token embeddings as action prediction queries
558
+ input_ids = qwen_inputs["input_ids"]
559
+ action_queries = self._gather_action_token_embeddings(
560
+ last_hidden, input_ids, action_token_id=self.action_token_id
561
+ ) # [B, chunk_len, H]
562
+ action_queries = self._condition_action_queries(action_queries, state)
563
+ pred_actions = self.action_model.predict_action(action_queries) # (B, chunk_len, action_dim)
564
+
565
+ normalized_actions = pred_actions.detach().cpu().numpy()
566
+ return {"normalized_actions": normalized_actions}
567
+
568
+ # ──────────────────────────────────────────────────────────────────
569
+ # Fixed-size KV memory. Default OFF. The cache/rotation core is
570
+ # unit-proven (tests/test_kv_memory_equivalence.py); the processor-driven
571
+ # segment construction below still needs end-to-end validation against the
572
+ # real Qwen3-VL-4B checkpoint on GPU.
573
+ # ──────────────────────────────────────────────────────────────────
574
+ def reset_memory(self, slot_id=None) -> None:
575
+ """Clear the KV memory for one eval slot (episode boundary), or all."""
576
+ if slot_id is None:
577
+ self._kv_memories.clear()
578
+ else:
579
+ self._kv_memories.pop(slot_id, None)
580
+
581
+ def _kv_components(self):
582
+ hf = self.qwen_vl_interface.model # Qwen3VLForConditionalGeneration
583
+ backbone = hf.model # Qwen3VLModel
584
+ text_model = backbone.language_model # Qwen3VLTextModel
585
+ return backbone, text_model.rotary_emb, len(text_model.layers), text_model.config
586
+
587
+ def _new_kv_memory(self):
588
+ from starVLA.model.modules.vlm.kv_memory import FrameKVMemory
589
+
590
+ _, rotary_emb, num_layers, text_config = self._kv_components()
591
+ return FrameKVMemory(rotary_emb, self.kv_window, num_layers, text_config)
592
+
593
+ def _build_text_first_inputs(self, frames, instruction):
594
+ """Tokenize a text-first window: [instruction][frame imgs...][action suffix].
595
+
596
+ Returns the processor batch (input_ids, pixel_values, image_grid_thw, ...).
597
+ Static text comes first so its KV stays positionally stable across steps.
598
+ """
599
+ action_tokens = self.action_token * self.chunk_len
600
+ action_suffix = f" Please predict the next {self.chunk_len} robot actions: <action>{action_tokens}<action>."
601
+ content = [{"type": "text", "text": instruction}]
602
+ content += [{"type": "image", "image": img} for img in frames]
603
+ content += [{"type": "text", "text": action_suffix}]
604
+ messages = [[{"role": "user", "content": content}]]
605
+ batch = self.qwen_vl_interface.processor.apply_chat_template(
606
+ messages, tokenize=True, padding=True, add_generation_prompt=True, return_dict=True, return_tensors="pt"
607
+ )
608
+ return batch.to(self.qwen_vl_interface.model.device)
609
+
610
+ def _kv_segments(self, input_ids_1d):
611
+ """Partition a text-first window's ids into (prefix_len, [frame_lens], action_len).
612
+
613
+ A frame block spans its vision_start .. vision_end (inclusive); the prefix is
614
+ everything before the first vision_start; the action suffix is everything
615
+ after the last vision_end. Using the real special-token ids keeps eviction
616
+ leak-free (each evicted frame removes exactly its own markers).
617
+ """
618
+ cfg = self.qwen_vl_interface.model.config
619
+ vstart = int(getattr(cfg, "vision_start_token_id", 151652))
620
+ vend = int(getattr(cfg, "vision_end_token_id", 151653))
621
+ ids = input_ids_1d.tolist()
622
+ starts = [i for i, t in enumerate(ids) if t == vstart]
623
+ ends = [i for i, t in enumerate(ids) if t == vend]
624
+ if not starts or not ends:
625
+ raise RuntimeError("KV memory: window inputs have no vision_start/end tokens")
626
+ action_start = ends[-1] + 1
627
+ bounds = starts + [action_start]
628
+ frame_lens = [bounds[i + 1] - bounds[i] for i in range(len(starts))]
629
+ return starts[0], frame_lens, len(ids) - action_start
630
+
631
+ def _kv_forward_step_batched(self, memories, frames, instruction):
632
+ """Run ONE streaming KV-memory step for a group of same-layout streams and
633
+ return ``(last_hidden_new [B, new_len, H], new_input_ids [B, new_len])``.
634
+
635
+ ``memories`` and ``frames`` are aligned lists (one entry per stream / eval
636
+ slot); all entries share ``instruction`` and history layout (grouped by the
637
+ caller). Two efficiencies vs a naive per-frame, per-step encode:
638
+
639
+ - Single-frame preprocessing: the image processor runs once per stream on its
640
+ OWN current frame. The window's multi-frame token layout (needed only for
641
+ M-RoPE positions via ``get_rope_index``) is reconstructed by replicating the
642
+ frame's token block, so duplicate frames are never re-preprocessed.
643
+ - Cross-stream batching: the streams' canonical KV blocks are stacked along the
644
+ batch dim, so the whole group is one forward; results are sliced back to each
645
+ stream's memory afterwards.
646
+
647
+ Past frames come from each stream's memory; only the current frame's pixels are
648
+ encoded fresh. ``B == 1`` (training rollout) reuses the same path with no
649
+ stacking, so gradients flow through the in-place memory updates.
650
+ """
651
+ from starVLA.model.modules.vlm.kv_memory import FrameKVMemory, memory_step
652
+
653
+ backbone = self.qwen_vl_interface.model.model # Qwen3VLModel
654
+ B = len(memories)
655
+ n_past = memories[0].num_past_frames()
656
+ n_visible = n_past + 1
657
+
658
+ # One processor call per stream's current frame (no duplicate-frame work).
659
+ per_stream = [self._build_text_first_inputs([frame], instruction) for frame in frames]
660
+ ids1 = per_stream[0]["input_ids"][0]
661
+ cur_grid = per_stream[0]["image_grid_thw"][:1]
662
+ prefix_len, frame_lens, action_len = self._kv_segments(ids1)
663
+ frame_len = frame_lens[0]
664
+
665
+ # Reconstruct the n_visible-frame window ids by replicating the frame block,
666
+ # then let get_rope_index assign the (content-independent) M-RoPE positions.
667
+ prefix, action = ids1[:prefix_len], ids1[prefix_len + frame_len :]
668
+ block = ids1[prefix_len : prefix_len + frame_len]
669
+ window_ids = torch.cat([prefix] + [block] * n_visible + [action]).unsqueeze(0)
670
+ full_pos1, _ = backbone.get_rope_index(window_ids, image_grid_thw=cur_grid.repeat(n_visible, 1))
671
+ full_pos = full_pos1.expand(3, B, full_pos1.shape[-1]).contiguous()
672
+
673
+ batched = FrameKVMemory.stack(memories) if B > 1 else memories[0]
674
+ past_len = batched.past_length()
675
+ is_prefill = not batched.has_text()
676
+ expected_past = 0 if is_prefill else prefix_len + n_past * frame_len
677
+ if past_len != expected_past:
678
+ raise RuntimeError(
679
+ f"KV memory slice misaligned: memory past_length={past_len} but window "
680
+ f"expects {expected_past}. Token boundaries drifted across steps."
681
+ )
682
+ if is_prefill:
683
+ new_start, frame_start_in_new, prefill_text_len = 0, prefix_len, prefix_len
684
+ else:
685
+ new_start, frame_start_in_new, prefill_text_len = past_len, 0, 0
686
+
687
+ new_ids = window_ids[:, new_start:].expand(B, -1).contiguous()
688
+ pixels = torch.cat([b["pixel_values"] for b in per_stream], dim=0)
689
+ grid = cur_grid.repeat(B, 1)
690
+
691
+ last_hidden = memory_step(
692
+ backbone,
693
+ batched,
694
+ new_input_ids=new_ids,
695
+ pixel_values=pixels,
696
+ image_grid_thw=grid,
697
+ full_position_ids=full_pos,
698
+ frame_start_in_new=frame_start_in_new,
699
+ frame_len=frame_len,
700
+ prefill_text_len=prefill_text_len,
701
+ )
702
+
703
+ if B > 1:
704
+ for i, memory in enumerate(memories):
705
+ sliced = batched.slice(i)
706
+ memory.text, memory.frames = sliced.text, sliced.frames
707
+ return last_hidden, new_ids
708
+
709
+ # ------------------------------------------------------------------ #
710
+ # Packed single-forward training path (StreamingLLM-style mask).
711
+ #
712
+ # Instead of the per-frame Python loop (`_forward_memory`), pack the whole
713
+ # rollout into ONE sequence
714
+ # [text/sink] [frame_1][action_1] ... [frame_R][action_R]
715
+ # and run a SINGLE Qwen3-VL forward under a FlexAttention BlockMask that
716
+ # reproduces the streaming visibility:
717
+ # * the text prefix is an always-visible attention sink (StreamingLLM);
718
+ # * each frame attends only the last `kv_window` frames (sliding window);
719
+ # * each action read-out block is isolated (seen only by its own step), so
720
+ # the frame KV stream is bit-identical to the streaming loop / eval.
721
+ # Custom M-RoPE `position_ids` keep frame->frame and action->frame relative
722
+ # distances exactly matching eval; only the text-sink->frame absolute distance
723
+ # grows with step (accepted approximation — the sink is distance-robust).
724
+ # Eval/live (`_predict_action_memory`) is untouched and keeps the rolling KV.
725
+ # ------------------------------------------------------------------ #
726
+ def _packed_window_layout(self, frames, instruction):
727
+ """Build the packed [text][f1][a1]...[fR][aR] window for ONE stream.
728
+
729
+ Token structure is content-independent (image placeholders are identical
730
+ per frame), so the prefix / frame / action blocks are reconstructed by
731
+ token-replication (matching `_kv_forward_step_batched`'s `window_ids`),
732
+ which guarantees each action block equals the per-step layout exactly.
733
+
734
+ Returns dict with: input_ids [1,L], pixel_values, image_grid_thw [R,3],
735
+ position_ids [3,1,L] (custom M-RoPE), kind [L] (0=text,1=frame,2=action),
736
+ step [L] (frame/step index for frame&action tokens, -1 for text),
737
+ action_idx [R, chunk_len] (packed indices of each step's action tokens).
738
+ """
739
+ R = len(frames)
740
+ backbone = self.qwen_vl_interface.model.model # Qwen3VLModel
741
+ device = self.qwen_vl_interface.model.device
742
+
743
+ # One processor call per frame: identical token block, distinct pixels.
744
+ per_frame = [self._build_text_first_inputs([f], instruction) for f in frames]
745
+ ids1 = per_frame[0]["input_ids"][0]
746
+ grid1 = per_frame[0]["image_grid_thw"][:1] # [1,3]
747
+ prefix_len, frame_lens, action_len = self._kv_segments(ids1)
748
+ frame_len = frame_lens[0]
749
+ for pf in per_frame:
750
+ pl, fl, al = self._kv_segments(pf["input_ids"][0])
751
+ if (pl, fl[0], al) != (prefix_len, frame_len, action_len):
752
+ raise RuntimeError(
753
+ "Packed KV memory: frames have inconsistent token layout "
754
+ f"({(pl, fl[0], al)} vs {(prefix_len, frame_len, action_len)}); "
755
+ "all frames in a rollout must share resolution/grid."
756
+ )
757
+
758
+ prefix = ids1[:prefix_len]
759
+ frame_block = ids1[prefix_len : prefix_len + frame_len]
760
+ action_block = ids1[prefix_len + frame_len :] # incl. assistant header
761
+ block_len = frame_len + action_len
762
+
763
+ pixel_values = torch.cat([pf["pixel_values"] for pf in per_frame], dim=0)
764
+ grid = grid1.repeat(R, 1) # [R, 3]
765
+
766
+ # Frames-only M-RoPE positions: frames laid out consecutively (no action
767
+ # in between), so frame→frame / action→frame relative distances match eval
768
+ # ("positions within the cache"). These are the canonical frame positions
769
+ # reused regardless of where the frame sits in the packed token sequence.
770
+ frames_only_ids = torch.cat([prefix] + [frame_block] * R).unsqueeze(0)
771
+ full_pos_f, _ = backbone.get_rope_index(frames_only_ids, image_grid_thw=grid) # [3,1,Lf]
772
+ text_pos = full_pos_f[:, :, :prefix_len]
773
+
774
+ action_offsets = (action_block == self.action_token_id).nonzero(as_tuple=False).flatten()
775
+ if action_offsets.numel() < self.chunk_len:
776
+ raise RuntimeError(
777
+ f"Packed KV memory: action block has {action_offsets.numel()} action "
778
+ f"tokens (< chunk_len={self.chunk_len})."
779
+ )
780
+ action_offsets = action_offsets[-self.chunk_len :] # last chunk_len, matches gather
781
+
782
+ def _frame_pos(k):
783
+ s = prefix_len + k * frame_len
784
+ return full_pos_f[:, :, s : s + frame_len]
785
+
786
+ def _action_pos(frame_pos_k):
787
+ fk_max = int(frame_pos_k.max().item())
788
+ ap = torch.arange(1, action_len + 1, device=device) + fk_max
789
+ return ap.view(1, 1, -1).expand(3, 1, -1)
790
+
791
+ W = self.kv_window
792
+ parts, pos_parts, kind_parts, step_parts, action_idx_rows = [], [], [], [], []
793
+
794
+ if self.kv_rebased_sink:
795
+ # Per-step re-based sink, with the redundant pre-eviction sinks deduped.
796
+ # Steps k < W all have j0=0 → o_k=0 → an identical sink at [0,P), so they
797
+ # share ONE front sink (step=-2, visible to queries with step < W). This
798
+ # is exactly eval before any eviction (sink pinned at the front, frames
799
+ # growing from P). Steps k >= W each carry their own re-based sink
800
+ # ([sink_k][frame_k][action_k]) at o_k so the sink→frame distance equals
801
+ # eval's rolling-KV layout (bit-exact). Net: 1 + max(0,R-W) sinks instead
802
+ # of R, saving (W-1) prefix copies while staying numerically identical.
803
+ base0 = int(full_pos_f[0, 0, prefix_len].item()) # frame 0's temporal start
804
+
805
+ # Shared front sink for the pre-eviction steps (step=-2).
806
+ parts.append(prefix)
807
+ pos_parts.append(text_pos)
808
+ kind_parts.append(torch.zeros(prefix_len, dtype=torch.long, device=device))
809
+ step_parts.append(torch.full((prefix_len,), -2, dtype=torch.long, device=device))
810
+ cursor = prefix_len
811
+
812
+ for k in range(R):
813
+ if k >= W:
814
+ # Re-based sink_k sits right before step k's oldest visible frame.
815
+ j0 = k - W + 1
816
+ o_k = int(full_pos_f[0, 0, prefix_len + j0 * frame_len].item()) - base0
817
+ parts.append(prefix)
818
+ pos_parts.append(text_pos + o_k) # shift all 3 M-RoPE dims by o_k
819
+ kind_parts.append(torch.zeros(prefix_len, dtype=torch.long, device=device))
820
+ step_parts.append(torch.full((prefix_len,), k, dtype=torch.long, device=device))
821
+ cursor += prefix_len
822
+ frame_pos_k = _frame_pos(k)
823
+ parts += [frame_block, action_block]
824
+ pos_parts += [frame_pos_k, _action_pos(frame_pos_k)]
825
+ kind_parts.append(
826
+ torch.cat([
827
+ torch.ones(frame_len, dtype=torch.long, device=device),
828
+ torch.full((action_len,), 2, dtype=torch.long, device=device),
829
+ ])
830
+ )
831
+ step_parts.append(torch.full((block_len,), k, dtype=torch.long, device=device))
832
+ action_idx_rows.append(cursor + frame_len + action_offsets)
833
+ cursor += block_len
834
+ else:
835
+ # Legacy single global sink: [sink][f0 a0]...[f_{R-1} a_{R-1}]. Sink at
836
+ # the front (step=-1, always visible); sink→frame distance grows with k.
837
+ parts.append(prefix)
838
+ pos_parts.append(text_pos)
839
+ kind_parts.append(torch.zeros(prefix_len, dtype=torch.long, device=device))
840
+ step_parts.append(torch.full((prefix_len,), -1, dtype=torch.long, device=device))
841
+ cursor = prefix_len
842
+ for k in range(R):
843
+ frame_pos_k = _frame_pos(k)
844
+ parts += [frame_block, action_block]
845
+ pos_parts += [frame_pos_k, _action_pos(frame_pos_k)]
846
+ kind_parts.append(
847
+ torch.cat([
848
+ torch.ones(frame_len, dtype=torch.long, device=device),
849
+ torch.full((action_len,), 2, dtype=torch.long, device=device),
850
+ ])
851
+ )
852
+ step_parts.append(torch.full((block_len,), k, dtype=torch.long, device=device))
853
+ action_idx_rows.append(cursor + frame_len + action_offsets)
854
+ cursor += block_len
855
+
856
+ input_ids = torch.cat(parts).unsqueeze(0) # [1, L]
857
+ position_ids = torch.cat(pos_parts, dim=2) # [3,1,L]
858
+ kind = torch.cat(kind_parts)
859
+ step = torch.cat(step_parts)
860
+ action_idx = torch.stack(action_idx_rows, dim=0) # [R, chunk_len]
861
+
862
+ return {
863
+ "input_ids": input_ids,
864
+ "pixel_values": pixel_values,
865
+ "image_grid_thw": grid,
866
+ "position_ids": position_ids,
867
+ "kind": kind,
868
+ "step": step,
869
+ "action_idx": action_idx,
870
+ }
871
+
872
+ def _packed_block_mask(self, kind, step, L, batch):
873
+ """Build a FlexAttention BlockMask for the packed sliding-window+sink layout."""
874
+ from torch.nn.attention.flex_attention import create_block_mask
875
+ from starVLA.model.modules.vlm.kv_memory import make_packed_sliding_mask_mod
876
+
877
+ mask_mod = make_packed_sliding_mask_mod(kind, step, self.kv_window)
878
+ # B=H=None → the mask is shared across batch and heads (it depends only on
879
+ # token kind/step, not content), so one BlockMask covers the whole batch.
880
+ return create_block_mask(mask_mod, B=None, H=None, Q_LEN=L, KV_LEN=L, device=str(kind.device))
881
+
882
+ def _assert_flex_attention(self):
883
+ """Packed training needs the decoder dispatched through FlexAttention.
884
+
885
+ We pass a FlexAttention BlockMask straight to the model, so the decoder
886
+ (forward AND gradient-checkpointing recompute during backward) must use
887
+ the flex backend the whole time — a transient toggle around the forward
888
+ would leave the recompute on sdpa and choke on the BlockMask. The eval
889
+ streaming path also runs fine under flex, so the whole model is simply
890
+ loaded with `attn_implementation: flex_attention`.
891
+ """
892
+ _, _, _, text_config = self._kv_components()
893
+ impl = getattr(text_config, "_attn_implementation", None)
894
+ if impl != "flex_attention":
895
+ raise RuntimeError(
896
+ "Packed KV-memory training requires the VLM loaded with "
897
+ f"attn_implementation='flex_attention' (got {impl!r}). Set "
898
+ "framework.qwenvl.attn_implementation: flex_attention."
899
+ )
900
+
901
+ def _forward_memory_packed(self, examples: List[dict]) -> dict:
902
+ """Training forward via a single packed sliding-window+sink masked pass.
903
+
904
+ Per-frame supervision identical to `_forward_memory` (every real frame is
905
+ supervised at the window it naturally has), but the expensive VLM forward
906
+ runs ONCE per rollout instead of R times. Full BPTT across the rollout
907
+ (no per-step detach) — pair with gradient checkpointing for memory.
908
+ """
909
+ self._assert_flex_attention()
910
+ profile = self._profile_timing_enabled()
911
+ timing = {"timing/mem_nograd_fwd": 0.0, "timing/mem_grad_fwd": 0.0, "timing/mem_action_head": 0.0}
912
+
913
+ instructions = [
914
+ self._instruction_with_state(ex["lang"], ex.get("state") if "state" in ex else None)
915
+ for ex in examples
916
+ ]
917
+ groups: dict = {}
918
+ for idx, instruction in enumerate(instructions):
919
+ valid = np.asarray(examples[idx]["valid"], dtype=bool)
920
+ groups.setdefault((instruction, tuple(valid.tolist())), []).append(idx)
921
+
922
+ total_weighted_loss = None
923
+ total_weight = 0.0
924
+ for (instruction, valid_key), indices in groups.items():
925
+ valid = np.asarray(valid_key, dtype=bool)
926
+ real_positions = [k for k in range(len(valid)) if valid[k]]
927
+ R = len(real_positions)
928
+ if R == 0:
929
+ continue
930
+ action_env_dims = [int(examples[i].get("action_env_dim", self.action_env_dim)) for i in indices]
931
+ rl_games_tasks = [str(examples[i].get("rl_games_task", "")) for i in indices]
932
+ if not any(rl_games_tasks):
933
+ rl_games_tasks = None
934
+
935
+ # Build per-sample packed layouts (identical token structure, distinct pixels).
936
+ layouts = [
937
+ self._packed_window_layout([examples[i]["image"][k] for k in real_positions], instruction)
938
+ for i in indices
939
+ ]
940
+ base = layouts[0]
941
+ L = base["input_ids"].shape[1]
942
+ B = len(indices)
943
+ input_ids = base["input_ids"].expand(B, -1).contiguous()
944
+ position_ids = base["position_ids"].expand(3, B, -1).contiguous()
945
+ pixel_values = torch.cat([lay["pixel_values"] for lay in layouts], dim=0)
946
+ grid = torch.cat([lay["image_grid_thw"] for lay in layouts], dim=0) # [B*R, 3]
947
+ action_idx = base["action_idx"] # [R, chunk_len]
948
+ block_mask = self._packed_block_mask(base["kind"], base["step"], L, B)
949
+
950
+ t_fwd = self._profile_start() if profile else None
951
+ last_hidden = self._forward_qwen_last_hidden(
952
+ {
953
+ "input_ids": input_ids,
954
+ "position_ids": position_ids,
955
+ "attention_mask": block_mask,
956
+ "pixel_values": pixel_values,
957
+ "image_grid_thw": grid,
958
+ "use_cache": False,
959
+ }
960
+ ) # [B, L, H]
961
+ if profile:
962
+ timing["timing/mem_grad_fwd"] += self._profile_elapsed(t_fwd)
963
+
964
+ t_head = self._profile_start() if profile else None
965
+ with torch.autocast("cuda", dtype=torch.float32):
966
+ for j, k in enumerate(real_positions):
967
+ action_queries = last_hidden[:, action_idx[j], :] # [B, chunk_len, H]
968
+ group_preds = self.action_model.predict_action(action_queries) # [B, chunk, dim]
969
+ targets = [self._prepare_action_array(examples[i]["actions_per_frame"][k]) for i in indices]
970
+ targets = torch.tensor(np.array(targets), device=group_preds.device, dtype=group_preds.dtype)
971
+ targets = targets[:, -self.action_horizon :, :]
972
+ step_loss = self._compute_action_loss(
973
+ group_preds, targets, action_env_dims=action_env_dims, rl_games_tasks=rl_games_tasks
974
+ )
975
+ weight = float(sum(float(np.asarray(examples[i]["density_weight"])[k]) for i in indices))
976
+ contribution = step_loss * weight
977
+ total_weighted_loss = contribution if total_weighted_loss is None else total_weighted_loss + contribution
978
+ total_weight += weight
979
+ if profile:
980
+ timing["timing/mem_action_head"] += self._profile_elapsed(t_head)
981
+
982
+ action_loss = total_weighted_loss / max(total_weight, 1e-6)
983
+ return {"action_loss": action_loss, "loss_weight": total_weight, "timing": timing, "batch_stats": {}}
984
+
985
+ def _instruction_with_state(self, instruction, state):
986
+ if state is None:
987
+ return instruction
988
+ return self.add_discretized_state_to_instruction([instruction], [state])[0]
989
+
990
+ def _forward_memory(self, examples: List[dict]) -> dict:
991
+ """Training forward with the streaming KV memory: per-frame supervision.
992
+
993
+ Each sample is an R-frame rollout `[t-R+1 .. t]`; the dataloader marks clamp
994
+ padding via ``valid`` and supplies one action chunk per frame in
995
+ ``actions_per_frame`` ([R, H, dim]). We skip padding frames (never feed memory,
996
+ never supervise) and supervise EVERY real frame at the window it naturally has
997
+ (1 -> window, then evict), which matches eval (`_predict_action_memory`) frame
998
+ for frame, including the unfilled window at an episode's start. History KV is
999
+ detached between steps (truncated BPTT depth 1), so each step's loss flows only
1000
+ through that step's forward; the per-step weighted losses are summed and the
1001
+ trainer backpropagates once.
1002
+
1003
+ Same-instruction, same-`valid` rollouts share a token layout and window
1004
+ evolution, so they run each step in one batched forward via
1005
+ `_kv_forward_step_batched` (degrades to per-sample otherwise), mirroring
1006
+ `_predict_action_memory`.
1007
+ """
1008
+ profile = self._profile_timing_enabled()
1009
+ timing = {"timing/mem_nograd_fwd": 0.0, "timing/mem_grad_fwd": 0.0, "timing/mem_action_head": 0.0}
1010
+
1011
+ instructions = [
1012
+ self._instruction_with_state(ex["lang"], ex.get("state") if "state" in ex else None)
1013
+ for ex in examples
1014
+ ]
1015
+
1016
+ # Group rollouts that share the prompt AND the same real/padding pattern: those
1017
+ # march through identical window states each step, so they batch cleanly.
1018
+ groups: dict = {}
1019
+ for idx, instruction in enumerate(instructions):
1020
+ valid = np.asarray(examples[idx]["valid"], dtype=bool)
1021
+ groups.setdefault((instruction, tuple(valid.tolist())), []).append(idx)
1022
+
1023
+ total_weighted_loss = None
1024
+ total_weight = 0.0
1025
+ for (instruction, valid_key), indices in groups.items():
1026
+ valid = np.asarray(valid_key, dtype=bool)
1027
+ real_positions = [k for k in range(len(valid)) if valid[k]]
1028
+ memories = [self._new_kv_memory() for _ in indices]
1029
+ rollout = [examples[i]["image"] for i in indices]
1030
+ action_env_dims = [int(examples[i].get("action_env_dim", self.action_env_dim)) for i in indices]
1031
+ rl_games_tasks = [str(examples[i].get("rl_games_task", "")) for i in indices]
1032
+ if not any(rl_games_tasks):
1033
+ rl_games_tasks = None
1034
+
1035
+ for step_pos, k in enumerate(real_positions):
1036
+ if step_pos > 0:
1037
+ for memory in memories:
1038
+ memory.detach_() # truncated BPTT: history is a fixed memory
1039
+ step_frames = [frames[k] for frames in rollout]
1040
+
1041
+ t_fwd = self._profile_start() if profile else None
1042
+ last_hidden, new_ids = self._kv_forward_step_batched(memories, step_frames, instruction)
1043
+ if profile:
1044
+ timing["timing/mem_grad_fwd"] += self._profile_elapsed(t_fwd)
1045
+
1046
+ t_head = self._profile_start() if profile else None
1047
+ with torch.autocast("cuda", dtype=torch.float32):
1048
+ action_queries = self._gather_action_token_embeddings(
1049
+ last_hidden, new_ids, action_token_id=self.action_token_id
1050
+ )
1051
+ group_preds = self.action_model.predict_action(action_queries) # [Bg, chunk, dim]
1052
+ targets = [
1053
+ self._prepare_action_array(examples[i]["actions_per_frame"][k]) for i in indices
1054
+ ]
1055
+ targets = torch.tensor(
1056
+ np.array(targets), device=group_preds.device, dtype=group_preds.dtype
1057
+ ) # [Bg, H, dim]
1058
+ targets = targets[:, -self.action_horizon :, :]
1059
+ step_loss = self._compute_action_loss(
1060
+ group_preds,
1061
+ targets,
1062
+ action_env_dims=action_env_dims,
1063
+ rl_games_tasks=rl_games_tasks,
1064
+ )
1065
+ if profile:
1066
+ timing["timing/mem_action_head"] += self._profile_elapsed(t_head)
1067
+
1068
+ # Per-supervised-step density weight: sum of the group's per-frame
1069
+ # weights at frame k. Uniform weights reduce this to a sample-count
1070
+ # weighting, i.e. the exact mean over all supervised (sample, step).
1071
+ weight = float(
1072
+ sum(float(np.asarray(examples[i]["density_weight"])[k]) for i in indices)
1073
+ )
1074
+ contribution = step_loss * weight
1075
+ total_weighted_loss = contribution if total_weighted_loss is None else total_weighted_loss + contribution
1076
+ total_weight += weight
1077
+
1078
+ action_loss = total_weighted_loss / max(total_weight, 1e-6)
1079
+ return {"action_loss": action_loss, "loss_weight": total_weight, "timing": timing, "batch_stats": {}}
1080
+
1081
+ @torch.inference_mode()
1082
+ def _predict_action_memory(self, examples: List[dict]) -> dict:
1083
+ """Eval-time streaming prediction with per-slot KV memory (req3, milestone 4).
1084
+
1085
+ The newest frame (``example['image'][-1]``) is encoded fresh; past frames are
1086
+ served from the slot's memory. ``reset_memory(slot_id)`` (called from the
1087
+ policy at episode boundaries) clears a slot. Streams that currently share the
1088
+ same instruction and history layout are processed in one batched forward; the
1089
+ rest fall back to their own group (no left padding needed).
1090
+ """
1091
+ train_obs_image_size = getattr(self.config.datasets.vla_data, "obs_image_size", None)
1092
+
1093
+ # Resolve each example to its (slot memory, current frame, instruction).
1094
+ entries = []
1095
+ for idx, example in enumerate(examples):
1096
+ slot_id = example.get("slot_id", idx)
1097
+ frames = [to_pil_preserve(f) for f in example["image"]]
1098
+ if train_obs_image_size:
1099
+ frames = resize_images(frames, target_size=train_obs_image_size)
1100
+ state = example.get("state") if "state" in example else None
1101
+ instruction = self._instruction_with_state(example["lang"], state)
1102
+ memory = self._kv_memories.get(slot_id)
1103
+ if memory is None:
1104
+ memory = self._new_kv_memory()
1105
+ self._kv_memories[slot_id] = memory
1106
+ entries.append({"idx": idx, "frame": frames[-1], "instruction": instruction, "memory": memory})
1107
+
1108
+ # Group same-layout streams (same prompt + same cached layout) into one forward.
1109
+ groups: dict = {}
1110
+ for entry in entries:
1111
+ key = (entry["instruction"], entry["memory"].layout_key())
1112
+ groups.setdefault(key, []).append(entry)
1113
+
1114
+ preds: List[Optional[torch.Tensor]] = [None] * len(examples)
1115
+ for group in groups.values():
1116
+ instruction = group[0]["instruction"]
1117
+ memories = [entry["memory"] for entry in group]
1118
+ frames = [entry["frame"] for entry in group]
1119
+ last_hidden, new_ids = self._kv_forward_step_batched(memories, frames, instruction)
1120
+ with torch.autocast("cuda", dtype=torch.float32):
1121
+ action_queries = self._gather_action_token_embeddings(
1122
+ last_hidden, new_ids, action_token_id=self.action_token_id
1123
+ )
1124
+ pred_actions = self.action_model.predict_action(action_queries)
1125
+ for i, entry in enumerate(group):
1126
+ preds[entry["idx"]] = pred_actions[i : i + 1]
1127
+
1128
+ normalized = torch.cat(preds, dim=0).detach().cpu().numpy()
1129
+ return {"normalized_actions": normalized}
1130
+
1131
+ def _gather_action_token_embeddings(
1132
+ self,
1133
+ last_hidden: torch.Tensor, # [B, L, H]
1134
+ input_ids: torch.Tensor, # [B, L]
1135
+ action_token_id=None, # Can be int or List[int]
1136
+ ) -> torch.Tensor:
1137
+ """
1138
+ Vectorized batch extraction of action token embeddings:
1139
+ - No per-sample for loop
1140
+ - Select the last chunk_len action placeholder tokens from each sample
1141
+ Args:
1142
+ last_hidden: [B, L, H]
1143
+ input_ids: [B, L]
1144
+ action_token_id: int or List[int]
1145
+ Returns:
1146
+ action_queries: [B, chunk_len, H]
1147
+ """
1148
+ if action_token_id is None:
1149
+ raise ValueError("action_token_id must not be None")
1150
+
1151
+ device = input_ids.device
1152
+ B, L, H = last_hidden.shape
1153
+
1154
+ # Support multiple ids (e.g., multiple variants)
1155
+ if isinstance(action_token_id, (list, tuple, set)):
1156
+ id_list = torch.tensor(list(action_token_id), device=device, dtype=input_ids.dtype)
1157
+ # torch.isin requires PyTorch >=1.10
1158
+ mask = torch.isin(input_ids, id_list)
1159
+ else:
1160
+ mask = input_ids == action_token_id # [B, L]
1161
+
1162
+ counts = mask.sum(dim=1) # [B]
1163
+ if (counts < self.chunk_len).any():
1164
+ insufficient = (counts < self.chunk_len).nonzero(as_tuple=False).flatten().tolist()
1165
+ raise RuntimeError(
1166
+ f"The following samples have insufficient action tokens (< {self.chunk_len}): {insufficient} |"
1167
+ f" counts={counts.tolist()}"
1168
+ )
1169
+
1170
+ # Position indices
1171
+ idx = torch.arange(L, device=device).unsqueeze(0).expand(B, L) # [B, L]
1172
+ masked_pos = torch.where(mask, idx, torch.full_like(idx, -1)) # Set non-action positions to -1
1173
+
1174
+ # Take the last chunk_len positions (higher indices = later in sequence)
1175
+ # Note: count sufficiency already verified, so -1 won't be incorrectly selected
1176
+ topk_pos = masked_pos.topk(k=self.chunk_len, dim=-1).values # [B, chunk_len] unsorted
1177
+ # Sort in temporal order
1178
+ selected_pos = topk_pos.sort(dim=-1).values # [B, chunk_len]
1179
+
1180
+ # Gather
1181
+ expanded_index = selected_pos.unsqueeze(-1).expand(-1, -1, H) # [B, chunk_len, H]
1182
+ action_queries = last_hidden.gather(dim=1, index=expanded_index) # [B, chunk_len, H]
1183
+ return action_queries
1184
+
1185
+ # Discretised state → instruction prefix (π₀.5 style); shared with QwenPI_v3.
1186
+ add_discretized_state_to_instruction = staticmethod(add_discretized_state_to_instruction)
1187
+
1188
+
1189
+ if __name__ == "__main__":
1190
+ import argparse
1191
+ import os
1192
+
1193
+ from omegaconf import OmegaConf
1194
+
1195
+ parser = argparse.ArgumentParser()
1196
+ parser.add_argument(
1197
+ "--config_yaml",
1198
+ type=str,
1199
+ default="examples/LIBERO/train_files/starvla_cotrain_libero.yaml",
1200
+ help="Path to YAML config",
1201
+ )
1202
+ args, clipargs = parser.parse_known_args()
1203
+
1204
+ if os.getenv("DEBUGPY_ENABLE", "0") == "1":
1205
+ import debugpy
1206
+
1207
+ debugpy.listen(("0.0.0.0", 10092))
1208
+ print("Rank 0 waiting for debugger attach on port 10092...")
1209
+ debugpy.wait_for_client()
1210
+
1211
+ cfg = OmegaConf.load(args.config_yaml)
1212
+
1213
+ model = Qwenvl_OFT(cfg)
1214
+ print(model)
1215
+
1216
+ image = Image.fromarray(np.random.randint(0, 255, (224, 224, 3), dtype=np.uint8))
1217
+ sample = {
1218
+ "action": np.random.uniform(-1, 1, size=(16, 7)).astype(np.float16),
1219
+ "image": [image],
1220
+ "lang": "This is a fake instruction for testing.",
1221
+ "state": np.random.uniform(-1, 1, size=(1, 7)).astype(np.float16), # chunk, state_dim
1222
+ }
1223
+ sample2 = sample.copy()
1224
+ sample2["lang"] = "Another fake instruction for testing."
1225
+
1226
+ batch = [sample, sample2]
1227
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
1228
+ model = model.to(device)
1229
+ forward_output = model(batch)
1230
+ action_loss = forward_output["action_loss"]
1231
+ print(f"[train] Action Loss (with state): {action_loss.item()}")
1232
+
1233
+ predict_output = model.predict_action(examples=[batch[0]])
1234
+ normalized_actions = predict_output["normalized_actions"]
1235
+ print(f"[infer] Predicted Action shape: {normalized_actions.shape}")
1236
+
1237
+ # Backward-compat: examples without `state` should still work.
1238
+ sample_no_state = {k: v for k, v in sample.items() if k != "state"}
1239
+ forward_no_state = model([sample_no_state, sample_no_state])
1240
+ print(f"[train] Action Loss (no state): {forward_no_state['action_loss'].item()}")
1241
+ predict_no_state = model.predict_action(examples=[sample_no_state])
1242
+ print(f"[infer] Predicted Action shape (no state): {predict_no_state['normalized_actions'].shape}")
1243
+
1244
+ print("Finished")
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/datasets.py ADDED
The diff for this file is too large to render. See raw diff
 
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/doom-mean-reset.patch ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ diff --git a/latency_bench/data/sf_teacher_rollout.py b/latency_bench/data/sf_teacher_rollout.py
2
+ index ef45d95b..e32b942e 100644
3
+ --- a/latency_bench/data/sf_teacher_rollout.py
4
+ +++ b/latency_bench/data/sf_teacher_rollout.py
5
+ @@ -964,6 +964,11 @@ def _replay_accepted_specs(
6
+ row_buffer_size=int(row_buffer_size),
7
+ export_image_size=export_image_size,
8
+ )
9
+ + stream_current_images = (
10
+ + image_transform_config.normalized_transform() == "raw_rgb"
11
+ + and int(context_window) <= 1
12
+ + and filter_preset == "none"
13
+ + )
14
+ image_resolution: list[int] | None = None
15
+
16
+ def assign_specs_to_slots(slots: list[int]) -> dict[int, int]:
17
+ @@ -1051,7 +1056,10 @@ def _replay_accepted_specs(
18
+ next_raw_frame=next_decision_step * obs_stride_raw_frames,
19
+ max_steps_per_episode=int(max_steps_per_episode),
20
+ )
21
+ - active_episode_frames[slot].append(np.array(image_frame, copy=True))
22
+ + if stream_current_images:
23
+ + image_writer.write(image_frame, image_path)
24
+ + else:
25
+ + active_episode_frames[slot].append(np.array(image_frame, copy=True))
26
+ row = teacher_dataset_row(
27
+ env_name=env_name,
28
+ spec=spec,
29
+ @@ -1104,7 +1112,9 @@ def _replay_accepted_specs(
30
+ )
31
+ else:
32
+ shard_rows = [dict(row) for row in final_rows]
33
+ - if _is_demon_ghost_trail:
34
+ + if stream_current_images:
35
+ + image_writer.flush()
36
+ + elif _is_demon_ghost_trail:
37
+ # Frames are pre-built ghost trail images; map directly.
38
+ ep_steps = [int(row["decision_step"]) for row in final_rows]
39
+ frames_by_decision_step = {
40
+ @@ -1118,12 +1128,13 @@ def _replay_accepted_specs(
41
+ frames=active_episode_frames[slot],
42
+ config=image_transform_config,
43
+ )
44
+ - shard_rows = _write_filtered_episode_images(
45
+ - image_writer,
46
+ - shard_rows,
47
+ - frames_by_decision_step,
48
+ - context_window=int(context_window),
49
+ - )
50
+ + if not stream_current_images:
51
+ + shard_rows = _write_filtered_episode_images(
52
+ + image_writer,
53
+ + shard_rows,
54
+ + frames_by_decision_step,
55
+ + context_window=int(context_window),
56
+ + )
57
+ write_episode_row_shard(output_dir, shard_rows)
58
+ progress.update(1)
59
+ replayed += 1
60
+ @@ -1272,9 +1283,8 @@ def _build_rollout_driver_runtime(
61
+ driver = BatchedTeacherRolloutDriver(runtime["envs"][0], int(num_envs))
62
+ else:
63
+ recreate_env = None
64
+ - if integration_name == "deadly_corridor" and (
65
+ - "export_zero_action_history" in config or getattr(cfg, "rollout_profile_seed_by_reset", False)
66
+ - ):
67
+ + # ViZDoom applies reset seeds only while creating its native game.
68
+ + if integration_name == "deadly_corridor":
69
+ from sample_factory.algo.utils.make_env import make_env_func_batched
70
+ from sample_factory.utils.attr_dict import AttrDict
71
+
72
+ diff --git a/tests/data/test_sf_teacher_dataset_export.py b/tests/data/test_sf_teacher_dataset_export.py
73
+ index e6b25233..61a58118 100644
74
+ --- a/tests/data/test_sf_teacher_dataset_export.py
75
+ +++ b/tests/data/test_sf_teacher_dataset_export.py
76
+ @@ -498,8 +498,11 @@ def test_serial_rollout_driver_continues_life_loss_with_seedless_reset(monkeypat
77
+ assert info == {"reset_seed": None}
78
+
79
+
80
+ -def test_serial_teacher_replay_starts_each_seed_in_a_fresh_environment(monkeypatch):
81
+ - sf_teacher_drivers = _load_sf_teacher_drivers_for_direct_test(monkeypatch)
82
+ +@pytest.mark.parametrize("latency_type", ["fixed", "profile_sample"])
83
+ +def test_serial_teacher_replay_starts_each_seed_in_a_fresh_environment(monkeypatch, tmp_path, latency_type):
84
+ + from contextlib import nullcontext
85
+ + from latency_bench.data import sf_teacher_rollout
86
+ + from sample_factory.algo.utils import make_env
87
+
88
+ class StatefulEnv:
89
+ action_space = object()
90
+ @@ -514,13 +517,17 @@ def test_serial_teacher_replay_starts_each_seed_in_a_fresh_environment(monkeypat
91
+ def close(self):
92
+ return None
93
+
94
+ - driver = sf_teacher_drivers.SerialTeacherRolloutDriver(
95
+ - [StatefulEnv()], recreate_env=lambda _slot: StatefulEnv()
96
+ + cfg = SimpleNamespace(frame_stack=4, action_history_decisions=8, latency_type=latency_type)
97
+ + monkeypatch.setattr(sf_teacher_rollout, "sample_factory_init_log", lambda _: nullcontext())
98
+ + monkeypatch.setattr(sf_teacher_rollout, "build_sample_factory_rollout_cfg", lambda _: (object(), cfg))
99
+ + monkeypatch.setattr(sf_teacher_rollout, "build_env_and_policy", lambda *args: {"envs": [StatefulEnv()]})
100
+ + monkeypatch.setattr(make_env, "make_env_func_batched", lambda *args, **kwargs: StatefulEnv())
101
+ + _, _, driver, _ = sf_teacher_rollout._build_rollout_driver_runtime(
102
+ + {"env_name": "deadly_corridor", "integration_name": "deadly_corridor"},
103
+ + output_dir=tmp_path, num_envs=1, export_env_raw_rgb_frames=False,
104
+ )
105
+ -
106
+ driver.reset_slots({0: 42})
107
+ observation, _ = driver.reset_slots({0: 43})[0]
108
+ -
109
+ assert observation["obs"].tolist() == [43, 1]
110
+
111
+
112
+ @@ -670,19 +677,22 @@ def test_collect_teacher_dataset_probe_retries_until_episode_is_accepted(monkeyp
113
+ def action_distribution(self):
114
+ return object()
115
+
116
+ + reset_seeds = []
117
+ +
118
+ class FakeEnv:
119
+ def __init__(self):
120
+ self.action_space = object()
121
+ - self.reset_seeds: list[int] = []
122
+ + self.reset_seeds = reset_seeds
123
+
124
+ def reset(self, seed=None):
125
+ self.reset_seeds.append(seed)
126
+ + self.current_seed = seed
127
+ return np.zeros((3, 2, 2), dtype=np.uint8), [
128
+ {"env_raw_rgb_frame_stack": _env_raw_rgb_frame_stack(5)}
129
+ ]
130
+
131
+ def step(self, action):
132
+ - reward = 3000.0 if len(self.reset_seeds) == 1 else 3000.001
133
+ + reward = 3000.0 if self.current_seed == 11 else 3000.001
134
+ return (
135
+ np.zeros((3, 2, 2), dtype=np.uint8),
136
+ np.float32(reward),
137
+ @@ -702,6 +712,8 @@ def test_collect_teacher_dataset_probe_retries_until_episode_is_accepted(monkeyp
138
+
139
+ fake_env = FakeEnv()
140
+ fake_actor = FakeActorCritic()
141
+ + from sample_factory.algo.utils import make_env
142
+ + monkeypatch.setattr(make_env, "make_env_func_batched", lambda *args, **kwargs: FakeEnv())
143
+ fake_cfg = SimpleNamespace(frame_stack=1, env_fps=35.0, obs_fps=17.5, seed=11)
144
+
145
+ monkeypatch.setattr(exporter, "build_sample_factory_rollout_cfg", lambda config: (object(), fake_cfg))
146
+ @@ -1273,7 +1285,8 @@ def test_collect_teacher_dataset_saves_demon_attack_latest_raw_rgb_image(monkeyp
147
+
148
+
149
+ @pytest.mark.parametrize("export_history", [False, True])
150
+ -def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch, tmp_path, export_history):
151
+ +@pytest.mark.parametrize("filter_preset", ["clean_v1", "none"])
152
+ +def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch, tmp_path, export_history, filter_preset):
153
+ import torch
154
+ from gymnasium.spaces import Discrete
155
+ from PIL import Image
156
+ @@ -1307,6 +1320,9 @@ def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch,
157
+ class FakeEnv:
158
+ action_space = Discrete(2)
159
+
160
+ + def __init__(self, exporting):
161
+ + self.exporting = exporting
162
+ +
163
+ def reset(self, seed=None):
164
+ self.steps = 0
165
+ obs = {"obs": np.zeros((1, 12, 2, 2), dtype=np.uint8)}
166
+ @@ -1323,6 +1339,9 @@ def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch,
167
+
168
+ def step(self, action):
169
+ self.steps += 1
170
+ + if self.exporting and self.steps == 2 and filter_preset == "none":
171
+ + image_path = output_dir / "images/train/episode_000000/decision_step_000000.png"
172
+ + assert image_path.is_file(), "First frame must be on disk before the episode ends"
173
+ obs = {"obs": np.ones((1, 12, 2, 2), dtype=np.uint8)}
174
+ next_stack = np.stack([np.full((6, 5, 3), 50 + idx, dtype=np.uint8) for idx in range(4)], axis=0)
175
+ return (
176
+ @@ -1354,7 +1373,7 @@ def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch,
177
+ exporter,
178
+ "build_env_and_policy",
179
+ lambda module, cfg, config, num_envs: {
180
+ - "envs": [FakeEnv()],
181
+ + "envs": [FakeEnv(cfg.export_env_raw_rgb_frames)],
182
+ "env_info": object(),
183
+ "actor_critic": FakeActorCritic(),
184
+ "device": torch.device("cpu"),
185
+ @@ -1382,6 +1401,7 @@ def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch,
186
+ export_image_size=None,
187
+ image_writer_workers=0,
188
+ row_buffer_size=1,
189
+ + filter_preset=filter_preset,
190
+ )
191
+ train_rows = _read_shard_rows(output_dir, "train")
192
+ val_rows = _read_shard_rows(output_dir, "val")
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/gym-language-contract.patch ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ diff --git a/examples/rl_games/train_files/data_registry/data_config.py b/examples/rl_games/train_files/data_registry/data_config.py
2
+ index 2ef8b39..6d76aeb 100644
3
+ --- a/examples/rl_games/train_files/data_registry/data_config.py
4
+ +++ b/examples/rl_games/train_files/data_registry/data_config.py
5
+ @@ -53,10 +53,10 @@ class AtlantisDataConfig(FlappyDataConfig):
6
+
7
+
8
+ class GymnasiumDataConfig(FlappyDataConfig):
9
+ - pass
10
+ + language_keys = ["annotation.human.task_description"]
11
+
12
+
13
+ -class GymnasiumNativeDataConfig(FlappyDataConfig):
14
+ +class GymnasiumNativeDataConfig(GymnasiumDataConfig):
15
+ """Configure native Gymnasium state and action vectors."""
16
+
17
+ state_keys = ["state.native"]
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/loader-spawn-cache.patch ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ diff --git a/starVLA/dataloader/gr00t_lerobot/datasets.py b/starVLA/dataloader/gr00t_lerobot/datasets.py
2
+ index 17ce5f1..2346230 100644
3
+ --- a/starVLA/dataloader/gr00t_lerobot/datasets.py
4
+ +++ b/starVLA/dataloader/gr00t_lerobot/datasets.py
5
+ @@ -667,6 +667,13 @@ class LeRobotSingleDataset(Dataset):
6
+ # Check if the dataset is valid
7
+ self._check_integrity()
8
+
9
+ + def __getstate__(self):
10
+ + state = self.__dict__.copy()
11
+ + state["_parquet_cache"] = {}
12
+ + state["curr_traj_data"] = None
13
+ + state["curr_traj_id"] = None
14
+ + return state
15
+ +
16
+ @property
17
+ def dataset_path(self) -> Path:
18
+ """The path to the dataset that contains the METADATA_FILENAME file."""
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/loader-spawn-test.patch ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ diff --git a/tests/data/test_starvla_tasks.py b/tests/data/test_starvla_tasks.py
2
+ index 1403fa13..62468aa6 100644
3
+ --- a/tests/data/test_starvla_tasks.py
4
+ +++ b/tests/data/test_starvla_tasks.py
5
+ @@ -395,3 +395,26 @@ def test_balance_masked_l1_uses_equal_sample_weights_and_no_padding_gradient(mon
6
+ all_valid = torch.ones((2, 8), dtype=torch.bool)
7
+ torch.testing.assert_close(model._compute_action_loss(pred, target, action_loss_mask=all_valid),
8
+ (pred - target).abs().mean())
9
+ +
10
+ +
11
+ +def test_lerobot_spawn_reload_preserves_data_without_copying_parent_cache(tmp_path, monkeypatch):
12
+ + import pickle
13
+ + pytest.importorskip("accelerate")
14
+ + monkeypatch.syspath_prepend(str(Path(__file__).resolve().parents[2] / "third_party/starVLA"))
15
+ + from starVLA.dataloader.gr00t_lerobot.datasets import LeRobotSingleDataset
16
+ +
17
+ + path = tmp_path / "episode.parquet"
18
+ + table = pd.DataFrame({"image": [b"rgb" * (1024 * 1024)], "action": [1]})
19
+ + table.to_parquet(path)
20
+ + parent = object.__new__(LeRobotSingleDataset)
21
+ + parent._parquet_cache = {path: table}
22
+ + parent.curr_traj_data = table
23
+ + parent.curr_traj_id = 0
24
+ + parent._all_steps = [(0, 0)]
25
+ +
26
+ + payload = pickle.dumps(parent)
27
+ + assert len(payload) < 64 * 1024
28
+ + worker = pickle.loads(payload)
29
+ + assert worker._all_steps == parent._all_steps
30
+ + pd.testing.assert_frame_equal(worker._read_trajectory_parquet(path), table)
31
+ + pd.testing.assert_frame_equal(parent.curr_traj_data, table)
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/mean-profile-preparation.patch ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ diff --git a/latency_bench/data/sf_teacher_rollout.py b/latency_bench/data/sf_teacher_rollout.py
2
+ index ef45d95b..af0a9fa9 100644
3
+ --- a/latency_bench/data/sf_teacher_rollout.py
4
+ +++ b/latency_bench/data/sf_teacher_rollout.py
5
+ @@ -964,6 +964,11 @@ def _replay_accepted_specs(
6
+ row_buffer_size=int(row_buffer_size),
7
+ export_image_size=export_image_size,
8
+ )
9
+ + stream_current_images = (
10
+ + image_transform_config.normalized_transform() == "raw_rgb"
11
+ + and int(context_window) <= 1
12
+ + and filter_preset == "none"
13
+ + )
14
+ image_resolution: list[int] | None = None
15
+
16
+ def assign_specs_to_slots(slots: list[int]) -> dict[int, int]:
17
+ @@ -1051,7 +1056,10 @@ def _replay_accepted_specs(
18
+ next_raw_frame=next_decision_step * obs_stride_raw_frames,
19
+ max_steps_per_episode=int(max_steps_per_episode),
20
+ )
21
+ - active_episode_frames[slot].append(np.array(image_frame, copy=True))
22
+ + if stream_current_images:
23
+ + image_writer.write(image_frame, image_path)
24
+ + else:
25
+ + active_episode_frames[slot].append(np.array(image_frame, copy=True))
26
+ row = teacher_dataset_row(
27
+ env_name=env_name,
28
+ spec=spec,
29
+ @@ -1104,7 +1112,9 @@ def _replay_accepted_specs(
30
+ )
31
+ else:
32
+ shard_rows = [dict(row) for row in final_rows]
33
+ - if _is_demon_ghost_trail:
34
+ + if stream_current_images:
35
+ + image_writer.flush()
36
+ + elif _is_demon_ghost_trail:
37
+ # Frames are pre-built ghost trail images; map directly.
38
+ ep_steps = [int(row["decision_step"]) for row in final_rows]
39
+ frames_by_decision_step = {
40
+ @@ -1118,12 +1128,13 @@ def _replay_accepted_specs(
41
+ frames=active_episode_frames[slot],
42
+ config=image_transform_config,
43
+ )
44
+ - shard_rows = _write_filtered_episode_images(
45
+ - image_writer,
46
+ - shard_rows,
47
+ - frames_by_decision_step,
48
+ - context_window=int(context_window),
49
+ - )
50
+ + if not stream_current_images:
51
+ + shard_rows = _write_filtered_episode_images(
52
+ + image_writer,
53
+ + shard_rows,
54
+ + frames_by_decision_step,
55
+ + context_window=int(context_window),
56
+ + )
57
+ write_episode_row_shard(output_dir, shard_rows)
58
+ progress.update(1)
59
+ replayed += 1
60
+ diff --git a/tests/data/test_sf_teacher_dataset_export.py b/tests/data/test_sf_teacher_dataset_export.py
61
+ index e6b25233..7d5537ac 100644
62
+ --- a/tests/data/test_sf_teacher_dataset_export.py
63
+ +++ b/tests/data/test_sf_teacher_dataset_export.py
64
+ @@ -1273,7 +1273,8 @@ def test_collect_teacher_dataset_saves_demon_attack_latest_raw_rgb_image(monkeyp
65
+
66
+
67
+ @pytest.mark.parametrize("export_history", [False, True])
68
+ -def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch, tmp_path, export_history):
69
+ +@pytest.mark.parametrize("filter_preset", ["clean_v1", "none"])
70
+ +def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch, tmp_path, export_history, filter_preset):
71
+ import torch
72
+ from gymnasium.spaces import Discrete
73
+ from PIL import Image
74
+ @@ -1307,6 +1308,9 @@ def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch,
75
+ class FakeEnv:
76
+ action_space = Discrete(2)
77
+
78
+ + def __init__(self, exporting):
79
+ + self.exporting = exporting
80
+ +
81
+ def reset(self, seed=None):
82
+ self.steps = 0
83
+ obs = {"obs": np.zeros((1, 12, 2, 2), dtype=np.uint8)}
84
+ @@ -1323,6 +1327,9 @@ def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch,
85
+
86
+ def step(self, action):
87
+ self.steps += 1
88
+ + if self.exporting and self.steps == 2 and filter_preset == "none":
89
+ + image_path = output_dir / "images/train/episode_000000/decision_step_000000.png"
90
+ + assert image_path.is_file(), "First frame must be on disk before the episode ends"
91
+ obs = {"obs": np.ones((1, 12, 2, 2), dtype=np.uint8)}
92
+ next_stack = np.stack([np.full((6, 5, 3), 50 + idx, dtype=np.uint8) for idx in range(4)], axis=0)
93
+ return (
94
+ @@ -1354,7 +1361,7 @@ def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch,
95
+ exporter,
96
+ "build_env_and_policy",
97
+ lambda module, cfg, config, num_envs: {
98
+ - "envs": [FakeEnv()],
99
+ + "envs": [FakeEnv(cfg.export_env_raw_rgb_frames)],
100
+ "env_info": object(),
101
+ "actor_critic": FakeActorCritic(),
102
+ "device": torch.device("cpu"),
103
+ @@ -1382,6 +1389,7 @@ def test_collect_teacher_dataset_saves_flappy_latest_raw_rgb_image(monkeypatch,
104
+ export_image_size=None,
105
+ image_writer_workers=0,
106
+ row_buffer_size=1,
107
+ + filter_preset=filter_preset,
108
+ )
109
+ train_rows = _read_shard_rows(output_dir, "train")
110
+ val_rows = _read_shard_rows(output_dir, "val")
111
+ diff --git a/third_party/MIKASA-Robo b/third_party/MIKASA-Robo
112
+ --- a/third_party/MIKASA-Robo
113
+ +++ b/third_party/MIKASA-Robo
114
+ @@ -1 +1 @@
115
+ -Subproject commit 017490bbb787c6efa8c025f9558e1a691965c0e0
116
+ +Subproject commit 017490bbb787c6efa8c025f9558e1a691965c0e0-dirty
117
+ diff --git a/third_party/starVLA b/third_party/starVLA
118
+ --- a/third_party/starVLA
119
+ +++ b/third_party/starVLA
120
+ @@ -1 +1 @@
121
+ -Subproject commit ccca13c5177fe3d3c884b6e2de4965d916016649
122
+ +Subproject commit ccca13c5177fe3d3c884b6e2de4965d916016649-dirty
123
+ diff --git a/training/gymnasium_sf/integration.py b/training/gymnasium_sf/integration.py
124
+ index 61c65ae9..874f655f 100644
125
+ --- a/training/gymnasium_sf/integration.py
126
+ +++ b/training/gymnasium_sf/integration.py
127
+ @@ -64,7 +64,6 @@ from training.common.sf_raw_reward_stats_compat import (
128
+ )
129
+ from training.common.utils import env_instance_seed, seed_everything, str2bool
130
+ from training.common.wandb_compat import patch_sample_factory_wandb
131
+ -from sample_factory.algo.mc_ppo.env import EpisodeEnv
132
+
133
+
134
+ SF_ENV_NAME = "latency_gymnasium"
135
+ @@ -385,7 +384,11 @@ def make_gymnasium_sf_env(
136
+ env_id=int(env_config.env_id),
137
+ issued_action_labels=action_labels,
138
+ )
139
+ - return EpisodeEnv(env, cfg.ppo) if cfg.algo == "PPO" else env
140
+ + if cfg.algo == "PPO":
141
+ + from sample_factory.algo.mc_ppo.env import EpisodeEnv
142
+ +
143
+ + return EpisodeEnv(env, cfg.ppo)
144
+ + return env
145
+
146
+
147
+ def register_gymnasium_envs() -> None:
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/train_starvla.py ADDED
The diff for this file is too large to render. See raw diff
 
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/trainer_tools.py ADDED
@@ -0,0 +1,736 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ metrics.py
3
+
4
+ Utility classes defining a Metrics container and multiple Trackers to enable model/stage-specific logging to various
5
+ endpoints (e.g., JSONL local logs, Weights & Biases).
6
+ """
7
+
8
+ from typing import Tuple
9
+ import re
10
+ import json
11
+ import numpy as np
12
+ import torch
13
+ import torch.distributed as dist
14
+ from transformers import get_scheduler
15
+
16
+ from accelerate import Accelerator, DeepSpeedPlugin
17
+ from accelerate.logging import get_logger
18
+ from starVLA.training.trainer_utils.config_tracker import reload_module_paths
19
+
20
+ logger = get_logger(__name__)
21
+
22
+
23
+ def build_accelerator(cfg, *, use_deepspeed: bool) -> Accelerator:
24
+ accelerator_kwargs = {
25
+ "gradient_accumulation_steps": cfg.trainer.gradient_accumulation_steps,
26
+ }
27
+ if use_deepspeed:
28
+ accelerator_kwargs["deepspeed_plugin"] = DeepSpeedPlugin()
29
+
30
+ accelerator = Accelerator(**accelerator_kwargs)
31
+ accelerator.print(accelerator.state)
32
+ return accelerator
33
+
34
+
35
+ _VOCAB_SIZED_WEIGHT_SUFFIXES = (
36
+ "embed_tokens.weight",
37
+ "lm_head.weight",
38
+ )
39
+
40
+
41
+ def _adapt_vocab_sized_weights(module, state_dict):
42
+ """Copy overlapping vocab rows when tokenizer-sized Qwen weights changed."""
43
+ target_state_dict = module.state_dict()
44
+ adapted = dict(state_dict)
45
+ adapted_keys = []
46
+ for key, source_tensor in state_dict.items():
47
+ target_tensor = target_state_dict.get(key)
48
+ if target_tensor is None or not hasattr(source_tensor, "shape") or not hasattr(target_tensor, "shape"):
49
+ continue
50
+ if tuple(source_tensor.shape) == tuple(target_tensor.shape):
51
+ continue
52
+ if not key.endswith(_VOCAB_SIZED_WEIGHT_SUFFIXES):
53
+ continue
54
+ if source_tensor.ndim != 2 or target_tensor.ndim != 2:
55
+ continue
56
+ if source_tensor.shape[1] != target_tensor.shape[1]:
57
+ continue
58
+
59
+ patched_tensor = target_tensor.detach().clone()
60
+ rows = min(source_tensor.shape[0], target_tensor.shape[0])
61
+ patched_tensor[:rows].copy_(source_tensor[:rows].to(dtype=patched_tensor.dtype, device=patched_tensor.device))
62
+ adapted[key] = patched_tensor
63
+ adapted_keys.append((key, tuple(source_tensor.shape), tuple(target_tensor.shape), rows))
64
+ return adapted, adapted_keys
65
+
66
+
67
+ # === Define Tracker Interface ===
68
+ #
69
+
70
+ # utils/cli_parser.py
71
+
72
+
73
+ def normalize_dotlist_args(args):
74
+ """
75
+ Convert ['--x.y', 'val'] and ['--flag'] → ['x.y=val', 'flag=true']
76
+ """
77
+ normalized = []
78
+ skip = False
79
+ for i in range(len(args)):
80
+ if skip:
81
+ skip = False
82
+ continue
83
+
84
+ arg = args[i]
85
+ if arg.startswith("--"):
86
+ key = arg.lstrip("-")
87
+ if "=" in key:
88
+ normalized.append(key)
89
+ elif i + 1 < len(args) and not args[i + 1].startswith("--"):
90
+ normalized.append(f"{key}={args[i + 1]}")
91
+ skip = True
92
+ else:
93
+ normalized.append(f"{key}=true")
94
+ else:
95
+ pass # skip orphaned values
96
+ return normalized
97
+
98
+
99
+ def setup_optimizer_and_scheduler(model, cfg) -> Tuple[torch.optim.Optimizer, torch.optim.lr_scheduler._LRScheduler]:
100
+ """Build AdamW optimizer + LR scheduler from cfg.trainer.
101
+
102
+ Supports:
103
+ - Per-module learning rates via cfg.trainer.learning_rate
104
+ - cosine_with_min_lr (or any transformers scheduler) via cfg.trainer.lr_scheduler_type
105
+ """
106
+ param_groups = build_param_lr_groups(model=model, cfg=cfg)
107
+ fused_available = torch.cuda.is_available()
108
+ optimizer = torch.optim.AdamW(
109
+ param_groups,
110
+ lr=cfg.trainer.learning_rate.base,
111
+ betas=tuple(cfg.trainer.optimizer.betas),
112
+ weight_decay=cfg.trainer.optimizer.weight_decay,
113
+ eps=cfg.trainer.optimizer.eps,
114
+ fused=fused_available,
115
+ )
116
+
117
+ if dist.is_initialized() and dist.get_rank() == 0:
118
+ for group in optimizer.param_groups:
119
+ logger.info(f"LR Group {group['name']}: lr={group['lr']}, num_params={len(group['params'])}")
120
+
121
+ # Strip keys unknown to transformers' get_scheduler before passing kwargs.
122
+ sched_kwargs = cfg.trainer.scheduler_specific_kwargs
123
+ lr_scheduler = get_scheduler(
124
+ name=cfg.trainer.lr_scheduler_type,
125
+ optimizer=optimizer,
126
+ num_warmup_steps=cfg.trainer.num_warmup_steps,
127
+ num_training_steps=cfg.trainer.max_train_steps,
128
+ scheduler_specific_kwargs=sched_kwargs,
129
+ )
130
+
131
+ return optimizer, lr_scheduler
132
+
133
+
134
+ def _qwen_vl_interface(model):
135
+ return model.qwen_vl_interface
136
+
137
+
138
+ def _llm_language_model(model):
139
+ return _qwen_vl_interface(model).model.model.language_model
140
+
141
+
142
+ def _vit_module(model):
143
+ # Qwen-VL keeps the visual tower and its vision-to-language connector/merger
144
+ # under this module.
145
+ return _qwen_vl_interface(model).model.model.visual
146
+
147
+
148
+ def _llm_decoder_layers(model):
149
+ return _llm_language_model(model).layers
150
+
151
+
152
+ def _tied_embedding_modules(model):
153
+ language_model = _llm_language_model(model)
154
+ hf_model = _qwen_vl_interface(model).model
155
+ return language_model.embed_tokens, hf_model.lm_head
156
+
157
+
158
+ def resolve_freeze_llm_layer_indices(model, cfg):
159
+ """Translate ``trainer.freeze_llm_layers=[start,end]`` to an inclusive layer list."""
160
+ freeze_llm_layers = cfg.trainer.freeze_llm_layers
161
+ if not freeze_llm_layers:
162
+ return [], len(_llm_decoder_layers(model))
163
+ start, end = [int(value) for value in freeze_llm_layers]
164
+ return list(range(start, end + 1)), len(_llm_decoder_layers(model))
165
+
166
+
167
+ def _module_param_ids(module):
168
+ return {id(param) for param in module.parameters()}
169
+
170
+
171
+ def _has_vit_or_llm_freeze_request(cfg) -> bool:
172
+ return bool(cfg.trainer.freeze_vit or cfg.trainer.freeze_tied_embedding or cfg.trainer.freeze_llm_layers)
173
+
174
+
175
+ def vit_llm_frozen_param_ids(model, cfg):
176
+ """Parameter ids excluded from optimizer by trainer freeze controls."""
177
+ if not _has_vit_or_llm_freeze_request(cfg):
178
+ return set()
179
+
180
+ frozen_params = set()
181
+ freeze_vit = cfg.trainer.freeze_vit
182
+ if freeze_vit:
183
+ frozen_params.update(_module_param_ids(_vit_module(model)))
184
+
185
+ if cfg.trainer.freeze_tied_embedding:
186
+ for module in _tied_embedding_modules(model):
187
+ frozen_params.update(_module_param_ids(module))
188
+
189
+ frozen_layer_indices, _ = resolve_freeze_llm_layer_indices(model, cfg)
190
+ layers = list(_llm_decoder_layers(model))
191
+ for layer_index in frozen_layer_indices:
192
+ frozen_params.update(_module_param_ids(layers[layer_index]))
193
+
194
+ return frozen_params
195
+
196
+
197
+ def build_param_lr_groups(model, cfg):
198
+ """
199
+ build multiple param groups based on cfg.trainer.learning_rate.
200
+ support specifying different learning rates for different modules, the rest use base.
201
+
202
+ Args:
203
+ vla: nn.Module model object
204
+ cfg: config object, requires cfg.trainer.learning_rate dictionary
205
+
206
+ Returns:
207
+ List[Dict]: param_groups that can be used to build optimizer with torch.optim
208
+ """
209
+
210
+ lr_cfg = cfg.trainer.learning_rate
211
+ base_lr = lr_cfg.get("base", 1e-4) # default base learning rate
212
+
213
+ freeze_modules = cfg.trainer.get("freeze_modules", "")
214
+ if not isinstance(freeze_modules, str):
215
+ freeze_modules = ""
216
+ freeze_patterns = [p.strip() for p in freeze_modules.split(",") if p.strip()]
217
+
218
+ used_params = set()
219
+ frozen_params = set()
220
+ param_groups = []
221
+
222
+ for freeze_path in freeze_patterns:
223
+ module = model
224
+ try:
225
+ for attr in freeze_path.split("."):
226
+ module = getattr(module, attr)
227
+ frozen_params.update(id(p) for p in module.parameters())
228
+ except AttributeError:
229
+ print(f"⚠️ freeze module path does not exist: {freeze_path}")
230
+ continue
231
+
232
+ # Exclude trainer freeze controls so frozen parameters never enter an
233
+ # optimizer param group.
234
+ frozen_params.update(vit_llm_frozen_param_ids(model, cfg))
235
+
236
+ for module_name, lr in lr_cfg.items():
237
+ if module_name == "base":
238
+ continue
239
+ # try to find the module under vla by module_name (support nested paths)
240
+ module = model
241
+ try:
242
+ for attr in module_name.split("."):
243
+ module = getattr(module, attr)
244
+ # filter out frozen parameters
245
+ params = [p for p in module.parameters() if id(p) not in frozen_params]
246
+ if params: # only add param group if there are trainable parameters
247
+ param_groups.append({"params": params, "lr": lr, "name": module_name})
248
+ used_params.update(id(p) for p in params)
249
+ except AttributeError:
250
+ ReferenceError(f"⚠️ module path `{module_name}` not found in vla")
251
+
252
+ # assign base learning rate to the remaining unused parameters (exclude frozen ones)
253
+ other_params = [p for p in model.parameters() if id(p) not in used_params and id(p) not in frozen_params]
254
+ if other_params:
255
+ param_groups.append({"params": other_params, "lr": base_lr, "name": "base"})
256
+
257
+ return param_groups
258
+
259
+
260
+ import torch.distributed as dist
261
+
262
+
263
+ def only_main_process(func):
264
+ """
265
+ decorator: only run in main process (rank=0)
266
+ """
267
+
268
+ def wrapper(*args, **kwargs):
269
+ if dist.is_initialized() and dist.get_rank() != 0:
270
+ return None # non-main process does not execute
271
+ return func(*args, **kwargs)
272
+
273
+ return wrapper
274
+
275
+
276
+ from torchvision.ops import box_iou
277
+ from PIL import Image
278
+
279
+
280
+ def resize_images(images, target_size=(224, 224)):
281
+ """
282
+ recursively resize all images in the nested list.
283
+
284
+ :param images: nested list of images or single image.
285
+ :param target_size: target size (width, height) after resizing.
286
+ :return: resized images list, keeping the original nested structure.
287
+ """
288
+ if isinstance(images, Image.Image): # if it is a single PIL image
289
+ return images.resize(target_size)
290
+ elif isinstance(images, list): # if it is a list, recursively process each element
291
+ return [resize_images(img, target_size) for img in images]
292
+ else:
293
+ raise ValueError("Unsupported image type or structure.")
294
+
295
+
296
+ def stitch_frames(frames, grid=(2, 2), size=(224, 224)):
297
+ """Tile temporal frames into one image, keeping the token count of a single image.
298
+
299
+ Used by the ``stitch`` multi-image mode: instead of feeding N frames as N
300
+ tokenized images, they are laid out on a fixed grid and the whole canvas is
301
+ returned at ``size``. Both training (``_pack_sample``) and eval
302
+ (``policy/starvla.py``) call this so the layouts match.
303
+
304
+ Args:
305
+ frames: list of ``PIL.Image`` or ``np.ndarray`` (H, W, C), oldest first.
306
+ grid: (rows, cols). Cells beyond ``len(frames)`` repeat the last frame so
307
+ the layout is fixed regardless of how many frames are available.
308
+ size: (width, height) of the returned canvas.
309
+ """
310
+ rows, cols = grid
311
+ canvas_w, canvas_h = size
312
+ cell_w, cell_h = canvas_w // cols, canvas_h // rows
313
+ pil = [f if isinstance(f, Image.Image) else Image.fromarray(f) for f in frames]
314
+ capacity = rows * cols
315
+ pil = (pil + [pil[-1]] * (capacity - len(pil))) if len(pil) < capacity else pil[:capacity]
316
+ canvas = Image.new("RGB", (canvas_w, canvas_h))
317
+ for idx, frame in enumerate(pil):
318
+ r, c = divmod(idx, cols)
319
+ canvas.paste(frame.convert("RGB").resize((cell_w, cell_h)), (c * cell_w, r * cell_h))
320
+ return canvas
321
+
322
+
323
+ import torch.distributed as dist
324
+
325
+
326
+ class TrainerUtils:
327
+ @staticmethod
328
+ def freeze_backbones(model, freeze_modules=""):
329
+ """
330
+ directly freeze the specified submodules based on the relative module path list (patterns), no longer recursively find all submodule names:
331
+ - patterns: read from config.trainer.freeze_modules, separated by commas to get the "relative path" list
332
+ for example "qwen_vl_interface, action_model.net",
333
+ it means to freeze model.qwen_vl_interface and model.action_model.net.
334
+
335
+ Args:
336
+ model: nn.Module model object
337
+ freeze_modules: relative module path list (patterns)
338
+
339
+ Returns:
340
+ model: nn.Module model object
341
+ return:
342
+ - model:
343
+ """
344
+ frozen = []
345
+ print("#"*30)
346
+ print(freeze_modules)
347
+ if freeze_modules and type(freeze_modules) == str:
348
+ # split and remove whitespace
349
+ patterns = [p.strip() for p in freeze_modules.split(",") if p.strip()] if freeze_modules else []
350
+
351
+ for path in patterns:
352
+ # split the "relative path" by dots, for example "action_model.net" → ["action_model", "net"]
353
+ attrs = path.split(".")
354
+ module = model
355
+ try:
356
+ for attr in attrs:
357
+ module = getattr(module, attr)
358
+ # if the module is successfully get, freeze it and its all submodule parameters
359
+ for param in module.parameters():
360
+ param.requires_grad = False
361
+ frozen.append(path)
362
+ except AttributeError:
363
+ # if the attribute does not exist, skip and print warning
364
+ print(f"⚠️ module path does not exist, cannot freeze: {path}")
365
+ continue
366
+
367
+ # accelerator.wait_for_everyone() # synchronize when distributed training
368
+ if not dist.is_initialized() or dist.get_rank() == 0:
369
+ print(f"🔒 Frozen modules with re pattern: {frozen}")
370
+ return model
371
+
372
+ @staticmethod
373
+ def freeze_vit_and_llm_layers(model, cfg):
374
+ """Apply trainer.freeze_vit/freeze_tied_embedding/freeze_llm_layers.
375
+
376
+ trainer.freeze_vit freezes Qwen-VL's visual module, including the
377
+ vision-to-language connector/merger it contains.
378
+ """
379
+ if not _has_vit_or_llm_freeze_request(cfg):
380
+ return model
381
+
382
+ freeze_vit = cfg.trainer.freeze_vit
383
+ if freeze_vit:
384
+ for param in _vit_module(model).parameters():
385
+ param.requires_grad = False
386
+
387
+ freeze_tied_embedding = cfg.trainer.freeze_tied_embedding
388
+ if freeze_tied_embedding:
389
+ for module in _tied_embedding_modules(model):
390
+ for param in module.parameters():
391
+ param.requires_grad = False
392
+
393
+ frozen_layer_indices, total = resolve_freeze_llm_layer_indices(model, cfg)
394
+ layers = list(_llm_decoder_layers(model))
395
+ for layer_index in frozen_layer_indices:
396
+ for param in layers[layer_index].parameters():
397
+ param.requires_grad = False
398
+
399
+ if not dist.is_initialized() or dist.get_rank() == 0:
400
+ print(
401
+ "🔒 freeze_vit="
402
+ f"{freeze_vit}, freeze_tied_embedding={freeze_tied_embedding}, "
403
+ f"freeze_llm_layers={list(frozen_layer_indices)}"
404
+ f" / total={total}"
405
+ )
406
+ return model
407
+
408
+ @staticmethod
409
+ def print_trainable_parameters(model):
410
+ """
411
+ print the total number of parameters and trainable parameters of the model
412
+ :param model: PyTorch model instance
413
+ """
414
+ if dist.is_initialized() and dist.get_rank() != 0:
415
+ return
416
+ print("📊 model parameter statistics:")
417
+ num_params = sum(p.numel() for p in model.parameters())
418
+ num_trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
419
+ print(
420
+ f"# Parameters (in millions): {num_params / 10**6:.3f} Total, {num_trainable_params / 10**6:.3f} Trainable"
421
+ )
422
+ return num_params, num_trainable_params
423
+
424
+ @staticmethod
425
+ def load_pretrained_backbones(model, checkpoint_path=None, reload_modules=None):
426
+ """
427
+ load checkpoint:
428
+ - if reload_modules is set, load by path part
429
+ - otherwise → load the entire model parameters (overwrite model)
430
+
431
+ return:
432
+ replace, loaded_modules: list of module paths that successfully loaded parameters; if global load, then ["<full_model>"]
433
+ """
434
+ if not checkpoint_path:
435
+ return []
436
+ if not dist.is_initialized() or dist.get_rank() == 0:
437
+ print(f"📦 loading checkpoint: {checkpoint_path}")
438
+ try:
439
+ if _is_safetensors_path(checkpoint_path):
440
+ from safetensors.torch import load_file
441
+
442
+ checkpoint = load_file(checkpoint_path)
443
+ else:
444
+ checkpoint = torch.load(checkpoint_path, map_location="cpu")
445
+ except Exception as e:
446
+ raise RuntimeError(f"❌ loading checkpoint failed: {e}")
447
+
448
+ loaded_modules = []
449
+
450
+ module_paths = reload_module_paths(reload_modules)
451
+ if module_paths: # partial load
452
+ for path in module_paths:
453
+ reload_path = path.split(".")
454
+ module = model
455
+ try:
456
+ for module_name in reload_path: # find the module to modify level by level
457
+ module = getattr(module, module_name)
458
+ prefix = path + "."
459
+ sub_state_dict = {k[len(prefix) :]: v for k, v in checkpoint.items() if k.startswith(prefix)}
460
+ if sub_state_dict:
461
+ sub_state_dict, adapted_keys = _adapt_vocab_sized_weights(module, sub_state_dict)
462
+ for key, source_shape, target_shape, rows in adapted_keys:
463
+ if not dist.is_initialized() or dist.get_rank() == 0:
464
+ print(
465
+ f"⚠️ adapted vocab-sized weight '{path}.{key}' from checkpoint shape "
466
+ f"{source_shape} to current shape {target_shape}; copied {rows} rows"
467
+ )
468
+ module.load_state_dict(sub_state_dict, strict=True)
469
+ if not dist.is_initialized() or dist.get_rank() == 0:
470
+ print(f"✅ parameters loaded to module '{path}'")
471
+ loaded_modules.append(path)
472
+ else:
473
+ print(f"⚠️ parameters not found in checkpoint '{path}'")
474
+ except AttributeError:
475
+ print(f"❌ cannot find module path: {path}")
476
+ else: # full load
477
+ try:
478
+ checkpoint, adapted_keys = _adapt_vocab_sized_weights(model, checkpoint)
479
+ for key, source_shape, target_shape, rows in adapted_keys:
480
+ if not dist.is_initialized() or dist.get_rank() == 0:
481
+ print(
482
+ f"⚠️ adapted vocab-sized weight '{key}' from checkpoint shape "
483
+ f"{source_shape} to current shape {target_shape}; copied {rows} rows"
484
+ )
485
+ model.load_state_dict(checkpoint, strict=False)
486
+ if not dist.is_initialized() or dist.get_rank() == 0:
487
+ print("✅ loaded <full_model> model parameters")
488
+ loaded_modules = ["<full_model>"]
489
+ except Exception as e:
490
+ raise RuntimeError(f"❌ loading full model failed: {e}")
491
+ return model
492
+
493
+ @staticmethod
494
+ def print_freeze_status(model):
495
+ """
496
+ print the freezing status of each parameter in the model
497
+ :param model: PyTorch model instance
498
+ """
499
+ for name, param in model.named_parameters():
500
+ status = "Frozen" if not param.requires_grad else "Trainable"
501
+ print(f"{name:60s} | {status}")
502
+
503
+ @staticmethod
504
+ def setup_distributed_training(accelerator, *components):
505
+ """
506
+ use Accelerator to prepare distributed training components
507
+ :param accelerator: Accelerate instance
508
+ :param components: any number of components (such as model, optimizer, dataloader, etc.)
509
+ :return: prepared distributed components (in the same order as input)
510
+ """
511
+
512
+ # use accelerator.prepare method to wrap components
513
+ prepared_components = accelerator.prepare(*components)
514
+ return prepared_components
515
+
516
+ @staticmethod
517
+ def euclidean_distance(predicted: np.ndarray, ground_truth: np.ndarray) -> float:
518
+ return np.linalg.norm(predicted - ground_truth)
519
+
520
+ @staticmethod
521
+ def _reset_dataloader(dataloader, epoch_counter):
522
+ """safe reset dataloader iterator"""
523
+ # 1. update epoch counter
524
+ epoch_counter += 1
525
+
526
+ dataset = getattr(dataloader, "dataset", None)
527
+ if dataset is not None and callable(getattr(dataset, "set_epoch", None)):
528
+ dataset.set_epoch(epoch_counter)
529
+
530
+ # 2. set new epoch (distributed core)
531
+ if hasattr(dataloader, "sampler") and callable(getattr(dataloader.sampler, "set_epoch", None)):
532
+ dataloader.sampler.set_epoch(epoch_counter)
533
+
534
+ # 3. create new iterator
535
+ return iter(dataloader), epoch_counter
536
+
537
+ @staticmethod
538
+ def compute_grad_angle_with_stats(grads_a: list[torch.Tensor], grads_v: list[torch.Tensor]) -> Tuple[float, float]:
539
+ """
540
+ compute the cosine angle between two groups of gradient vectors (degrees), and calculate the average angle and variance.
541
+ grads_a, grads_v: gradient Tensor list corresponding to the same parameter list interface_params
542
+ return:
543
+ mean_angle_deg: average angle (degrees)
544
+ angle_variance: angle variance
545
+ """
546
+ angle_degs = []
547
+
548
+ # compute the cosine angle between each gradient block grads_a[0].shape = 1280, 3, 14, 14
549
+ # grads_1 = grads_a[0][0] # [3, 14, 14]
550
+ # grads_2 = grads_v[0][0]
551
+ # grads_a = grads_1.view(-1, 3) # reshape to [196, 3]
552
+ # grads_v = grads_2.view(-1, 3)
553
+
554
+ # lang linear
555
+ # reshape to 14*14, 3
556
+ # layer
557
+ grads_action = grads_a[0] # [2048, 11008]
558
+ grads_action = grads_action[
559
+ :32, :7
560
+ ] # only take the first 7 elements, avoid cosim failure in high-dimensional space
561
+ grads_vl = grads_v[0] # [2048, 11008]
562
+ grads_vl = grads_vl[
563
+ :32, :7
564
+ ] # only take the first 32 elements, 7 dimensions, avoid cosim failure in high-dimensional space
565
+ for g_a, g_v in zip(grads_action, grads_vl):
566
+ dot = torch.sum(g_a * g_v)
567
+ norm_a_sq = torch.sum(g_a * g_a)
568
+ norm_v_sq = torch.sum(g_v * g_v)
569
+
570
+ # avoid division by zero
571
+ norm_a = torch.sqrt(norm_a_sq + 1e-16)
572
+ norm_v = torch.sqrt(norm_v_sq + 1e-16)
573
+
574
+ cos_sim = (dot / (norm_a * norm_v)).clamp(-1.0, 1.0)
575
+ angle_rad = torch.acos(cos_sim)
576
+ angle_deg = angle_rad * (180.0 / torch.pi)
577
+
578
+ angle_degs.append(angle_deg.item())
579
+
580
+ # compute the average angle and variance
581
+ angle_degs_tensor = torch.tensor(angle_degs)
582
+ mean_angle_deg = torch.mean(angle_degs_tensor).item()
583
+ angle_variance = torch.sqrt(torch.var(angle_degs_tensor)).item()
584
+ # accelerator.wait_for_everyone()
585
+ return mean_angle_deg, angle_variance
586
+
587
+ @staticmethod
588
+ def pcgrad_project(grads_a: list[torch.Tensor], grads_v: list[torch.Tensor]) -> list[torch.Tensor]:
589
+ """
590
+ apply PCGrad projection to the second group of gradients grads_v, suppress negative transfer between grads_a and grads_v
591
+ if the dot product of two groups of gradients < 0, then:
592
+ grads_v <- grads_v - (dot / ||grads_a||^2) * grads_a
593
+ return the new grads_v list
594
+ """
595
+ # first compute dot and ||grads_a||^2
596
+ dot, norm_a_sq = 0.0, 0.0
597
+ for g_a, g_v in zip(grads_a, grads_v):
598
+ dot += torch.sum(g_a * g_v)
599
+ norm_a_sq += torch.sum(g_a * g_a)
600
+
601
+ if dot < 0:
602
+ coeff = dot / (norm_a_sq + 1e-6)
603
+ # projection
604
+ grads_v = [g_v - coeff * g_a for g_a, g_v in zip(grads_a, grads_v)]
605
+
606
+ return grads_v
607
+
608
+ @staticmethod
609
+ def eval_qwenpi(qwenpi, dataloader, num_batches=20):
610
+ """
611
+ evaluate QwenQFormerDiT model, compute IoU and action distance.
612
+
613
+ Args:
614
+ qwenpi: QwenQFormerDiT model instance.
615
+ dataloader: data loader.
616
+ num_batches: number of batches to evaluate.
617
+
618
+ Returns:
619
+ dict: contains IoU and action distance evaluation results.
620
+ """
621
+ iou_scores = []
622
+ action_distances = []
623
+ count = 0
624
+
625
+ dataset_iter = iter(dataloader)
626
+ while count < num_batches:
627
+ try:
628
+ batch_samples = next(dataset_iter)
629
+ count += 1
630
+ except StopIteration:
631
+ break
632
+
633
+ # extract data
634
+ images = [example["image"] for example in batch_samples]
635
+ instructions = [example["lang"] for example in batch_samples]
636
+ actions = [example["action"] for example in batch_samples]
637
+ solutions = [example["solution"] for example in batch_samples]
638
+
639
+ # model prediction
640
+ predicted_solutions, normalized_actions = qwenpi.predict_action_withCoT(
641
+ images=images, instructions=instructions, use_ddim=False, num_ddim_steps=20
642
+ )
643
+
644
+ # extract and convert predicted results
645
+ parsed_solutions = []
646
+ for solution in predicted_solutions:
647
+ parsed_solution = TrainerUtils.extract_json_from_string(solution)
648
+ parsed_solutions.append(parsed_solution)
649
+
650
+ # compute IoU
651
+ for pred_dict, gt_dict in zip(parsed_solutions, solutions):
652
+ pred_pick_bbox = torch.tensor(pred_dict["pick"]["bbox_2d"], dtype=torch.float32).unsqueeze(0)
653
+ gt_pick_bbox = torch.tensor(gt_dict["pick"]["bbox_2d"], dtype=torch.float32).unsqueeze(0)
654
+ pred_place_bbox = torch.tensor(pred_dict["place"]["bbox_2d"], dtype=torch.float32).unsqueeze(0)
655
+ gt_place_bbox = torch.tensor(gt_dict["place"]["bbox_2d"], dtype=torch.float32).unsqueeze(0)
656
+
657
+ pick_iou = box_iou(pred_pick_bbox, gt_pick_bbox).item()
658
+ place_iou = box_iou(pred_place_bbox, gt_place_bbox).item()
659
+
660
+ iou_scores.append({"pick_iou": pick_iou, "place_iou": place_iou})
661
+
662
+ # compute action distance
663
+ actions = np.array(actions) # convert to numpy array
664
+ num_pots = np.prod(actions.shape) # B*len*dim
665
+ action_distance = TrainerUtils.euclidean_distance(normalized_actions, actions)
666
+ average_action_distance = action_distance / num_pots
667
+ action_distances.append(average_action_distance)
668
+
669
+ # summarize results
670
+ avg_action_distance = np.mean(action_distances)
671
+ return {"iou_scores": iou_scores, "average_action_distance": avg_action_distance}
672
+
673
+ @staticmethod
674
+ def extract_json_from_string(input_string):
675
+ """
676
+ extract valid JSON part from string and convert to dictionary.
677
+
678
+ Args:
679
+ input_string (str): string containing extra characters.
680
+
681
+ Returns:
682
+ dict: dictionary extracted and parsed.
683
+ """
684
+ json_match = re.search(r"{.*}", input_string, re.DOTALL)
685
+ if json_match:
686
+ json_str = json_match.group(0)
687
+ try:
688
+ return json.loads(json_str)
689
+ except json.JSONDecodeError as e:
690
+ print(f"JSON decode failed: {e}")
691
+ return None
692
+ else:
693
+ print("No valid JSON part found")
694
+ return None
695
+
696
+ def _get_latest_checkpoint(self, checkpoint_dir):
697
+ """Find the latest checkpoint in the directory based on step number."""
698
+ if not os.path.exists(checkpoint_dir):
699
+ self.accelerator.print(f"No checkpoint directory found at {checkpoint_dir}")
700
+ return None, 0
701
+
702
+ checkpoints = []
703
+ for name in os.listdir(checkpoint_dir):
704
+ path = os.path.join(checkpoint_dir, name)
705
+ state_match = re.match(r"steps_(\d+)_state$", name)
706
+ if state_match and os.path.isdir(path):
707
+ checkpoints.append((name, int(state_match.group(1)), 1))
708
+ continue
709
+ file_match = re.match(r"steps_(\d+)_(?:pytorch_model\.pt|model\.safetensors)$", name)
710
+ if file_match and os.path.isfile(path):
711
+ checkpoints.append((name, int(file_match.group(1)), 0))
712
+
713
+ if not checkpoints:
714
+ self.accelerator.print(f"No checkpoints found in {checkpoint_dir}")
715
+ return None, 0
716
+
717
+ # Sort by step number, preferring full training-state directories over
718
+ # model-only files when both exist for the same step.
719
+ checkpoints.sort(key=lambda x: (x[1], x[2]))
720
+ latest_checkpoint, completed_steps, _ = checkpoints[-1]
721
+
722
+ latest_checkpoint_path = os.path.join(checkpoint_dir, latest_checkpoint)
723
+ self.accelerator.print(f"Latest checkpoint found: {latest_checkpoint_path}")
724
+ return latest_checkpoint_path, completed_steps
725
+
726
+ import os
727
+
728
+
729
+ def is_main_process():
730
+ rank = int(os.environ.get("RANK", 0)) # if RANK is not set, default to 0
731
+ return rank == 0
732
+
733
+
734
+ def _is_safetensors_path(path):
735
+ """Check if a path refers to a safetensors file."""
736
+ return str(path).endswith(".safetensors")
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training-code/worker_context.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import multiprocessing.context
2
+ import os
3
+ from typing import Any
4
+
5
+
6
+ _DISTRIBUTED_ENV_KEYS = (
7
+ "LOCAL_RANK",
8
+ "RANK",
9
+ "WORLD_SIZE",
10
+ "MASTER_ADDR",
11
+ "MASTER_PORT",
12
+ "GROUP_RANK",
13
+ "LOCAL_WORLD_SIZE",
14
+ "ROLE_RANK",
15
+ "ROLE_WORLD_SIZE",
16
+ "TORCHELASTIC_RUN_ID",
17
+ "TORCHELASTIC_RESTART_COUNT",
18
+ "TORCHELASTIC_MAX_RESTARTS",
19
+ )
20
+
21
+
22
+ class _CpuOnlyWorkerSpawnProcess(multiprocessing.context.SpawnProcess):
23
+ def start(self):
24
+ had_cuda_visible_devices = "CUDA_VISIBLE_DEVICES" in os.environ
25
+ if had_cuda_visible_devices:
26
+ cuda_visible_devices = os.environ["CUDA_VISIBLE_DEVICES"]
27
+ distributed_env = {key: os.environ[key] for key in _DISTRIBUTED_ENV_KEYS if key in os.environ}
28
+
29
+ os.environ["CUDA_VISIBLE_DEVICES"] = ""
30
+ for key in distributed_env:
31
+ del os.environ[key]
32
+ try:
33
+ return super().start()
34
+ finally:
35
+ if had_cuda_visible_devices:
36
+ os.environ["CUDA_VISIBLE_DEVICES"] = cuda_visible_devices
37
+ else:
38
+ del os.environ["CUDA_VISIBLE_DEVICES"]
39
+ for key, value in distributed_env.items():
40
+ os.environ[key] = value
41
+
42
+
43
+ class CpuOnlyWorkerSpawnContext(multiprocessing.context.SpawnContext):
44
+ Process = _CpuOnlyWorkerSpawnProcess
45
+
46
+
47
+ CPU_ONLY_WORKER_CONTEXT = CpuOnlyWorkerSpawnContext()
48
+
49
+
50
+ def _as_bool(value: Any, default: bool = False) -> bool:
51
+ if value is None:
52
+ return default
53
+ if isinstance(value, bool):
54
+ return value
55
+ if isinstance(value, str):
56
+ return value.strip().lower() not in {"false", "0", "no", "off"}
57
+ return bool(value)
58
+
59
+
60
+ def build_cpu_only_dataloader_kwargs(
61
+ num_workers: int,
62
+ *,
63
+ pin_memory: Any = False,
64
+ persistent_workers: Any = False,
65
+ prefetch_factor: Any = None,
66
+ ) -> dict[str, Any]:
67
+ dataloader_kwargs: dict[str, Any] = {
68
+ "pin_memory": _as_bool(pin_memory),
69
+ }
70
+ if int(num_workers) <= 0:
71
+ return dataloader_kwargs
72
+
73
+ dataloader_kwargs["multiprocessing_context"] = CPU_ONLY_WORKER_CONTEXT
74
+ dataloader_kwargs["persistent_workers"] = _as_bool(persistent_workers)
75
+ if prefetch_factor is not None:
76
+ dataloader_kwargs["prefetch_factor"] = int(prefetch_factor)
77
+ return dataloader_kwargs
latency-aware/deadly-corridor/vla/starvla-qwenoft-h1/deadly_corridor-qwenoft-mean-3090-s42/training_results.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "training_complete": true,
3
+ "optimizer_updates": 5000,
4
+ "selection": "final_5000",
5
+ "train_loss": 0.021038614213466644,
6
+ "validation_action_loss": 0.020563077181577682,
7
+ "validation_samples": 6400,
8
+ "final_learning_rates": {
9
+ "learning_rate/qwen_vl_interface": 1e-07,
10
+ "learning_rate/action_model": 3.3333333333333333e-06
11
+ },
12
+ "closed_loop_evaluation": "pending until all four VLA trainings complete",
13
+ "tensor_keys": 732,
14
+ "serialized_tensor_elements_including_tied_aliases": 4892704775,
15
+ "weights_only_load": "passed",
16
+ "all_tensors_finite": true
17
+ }