Skip to content

Replace assert with ValueError in public-API input validation#77

Open
lonexreb wants to merge 1 commit intoNVlabs:mainfrom
lonexreb:refactor/asserts-to-valueerror-public-apis
Open

Replace assert with ValueError in public-API input validation#77
lonexreb wants to merge 1 commit intoNVlabs:mainfrom
lonexreb:refactor/asserts-to-valueerror-public-apis

Conversation

@lonexreb
Copy link
Copy Markdown
Contributor

@lonexreb lonexreb commented May 2, 2026

Summary

Continues the pattern of merged PR #50 (helper.create_message) and PR #73 (load_physical_aiavdataset): convert the remaining public-facing input validators from assert to ValueError, so they survive python -O and emit a clear exception type users can catch.

Changes

1. tokenize_history_trajectory (src/alpamayo_r1/models/base_model.py:104-105)

-    assert "ego_history_xyz" in traj_data
-    assert traj_data["ego_history_xyz"].ndim == 4, "ego_history_xyz must be 4D of [B, n_traj, T, 3]"
+    if "ego_history_xyz" not in traj_data:
+        raise ValueError(
+            f"`traj_data` is missing required key 'ego_history_xyz'; got keys {list(traj_data)}"
+        )
+    if traj_data["ego_history_xyz"].ndim != 4:
+        raise ValueError(
+            "ego_history_xyz must be 4D of [B, n_traj, T, 3], got "
+            f"shape {tuple(traj_data['ego_history_xyz'].shape)}"
+        )

The first assert had no message; the second one's was correct but assert got stripped under -O. Both errors now include the actual offending value (key set or shape) for faster diagnosis.

2. AlpamayoR1.sample_trajectories_from_data_with_vlm_rollout (src/alpamayo_r1/models/alpamayo_r1.py:157)

-        assert n_traj_group == 1, "Only one trajectory group is supported for inference."
+        if n_traj_group != 1:
+            raise ValueError(
+                f"Only one trajectory group is supported for inference, got {n_traj_group=}"
+            )

Scope

These three call sites — plus the two already addressed in #50 and #73 — are all the public-facing input validators that were using assert. I deliberately left the remaining asserts as-is because they guard internal invariants, not caller-supplied input:

File:Line Why kept as assert
models/base_model.py:266 len(discrete_tokens) == num_new_tokens — internal post-condition of tokenizer.add_tokens
models/action_in_proj.py:43 1 <= num_enc_layers — config-time check inside private mixin
models/alpamayo_r1.py (sample loop, internal) various sequence-length / token-position invariants
chat_template/conversation.py:38, 115, 195, 227 template-construction internal invariants
processor/qwen_processor.py:128, 189, 195, 294 processor-internal batching invariants
utils/get_label_mask.py:66, 69, 123, 134 label-mask internal balance invariants
action_space/discrete_action_space.py:37 dim-list parity inside the constructor

If you'd prefer a sweeping conversion to ValueError everywhere, happy to do that in a follow-up — but the convention here mirrors the way #50 was framed (only the user-input boundary).

Test plan

  • Both files parse: python -c \"import ast; [ast.parse(open(f).read()) for f in ['src/alpamayo_r1/models/base_model.py', 'src/alpamayo_r1/models/alpamayo_r1.py']]\"
  • No semantics change: every check fires under exactly the same condition; just a different exception class with a more informative message.
  • Behavior under python -O: the validation now runs (previously stripped). For valid inputs this is a no-op; for invalid inputs callers see ValueError instead of an opaque downstream AttributeError/KeyError.

Continues the pattern of NVlabs#50 (helper.create_message) and NVlabs#73
(load_physical_aiavdataset) by converting two more user-facing input
validations from assert to ValueError so they survive python -O and
emit a clear exception type:

- tokenize_history_trajectory(): missing 'ego_history_xyz' key, and
  rank check on the tensor (base_model.py:104-105). Both errors now
  include the offending value (key set or actual shape) in the message.
- AlpamayoR1.sample_trajectories_from_data_with_vlm_rollout(): the
  n_traj_group == 1 contract (alpamayo_r1.py:157) now reports the
  actual n_traj_group value.

These three call sites (the assert in helper.create_message that NVlabs#50
already fixed, the t0_us check NVlabs#73 already fixed, and the two here)
are the only public-facing input validators that were still using
assert. Internal invariants (e.g. base_model.py:266, action_in_proj.py:43)
are left as assert because they guard implementation correctness, not
caller-supplied input.

Signed-off-by: lonexreb <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant