Repository navigation
fix(export): extract rsl_rl actor from alg directly so export works again - #157
Merged
Merged
Conversation
…gain `genelab export <rsl_rl-task>` failed for every rsl_rl checkpoint with "backend 'rsl_rl' did not expose an actor module": `_extract_rsl_rl_actor` read `runner.alg.actor_critic`, but current rsl_rl's `PPO.__init__` stores `self.actor` / `self._raw_actor` directly and no longer has `actor_critic`, so extraction returned `(None, num_obs)` and `_export.py` raised. Source the actor from `alg._raw_actor` (falling back to `alg.actor`) and use the actor's `as_jit()` export wrapper, which exposes the flat `forward(obs) -> deterministic action` contract (learned obs normalizer baked in) that the exporter wraps with env-side scale/clip. The legacy `alg.actor_critic.actor` / `act_inference` path is kept as a fallback for older rsl_rl. Verified headless (QD_GRAPH=0 QT_QPA_PLATFORM=offscreen) against a real inverted-pendulum checkpoint: `-f torchscript` and `-f onnx` both exit 0 and write loadable .ts / .onnx + .metadata.json (obs_dim 8 -> action_dim 1, dynamic batch). Tests build a real rsl_rl MLPModel and assert extraction + full export, plus the legacy and missing-actor paths. Docs (eval-and-export EN/ZH) updated to describe the new extraction path.
This was referenced May 24, 2026
KraHsu
added a commit
that referenced
this pull request
Jun 5, 2026
fix(export): extract rsl_rl actor from alg directly so export works again
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
genelab export <rsl_rl-task> <ckpt> -f torchscript|onnxfailed for everyrsl_rl checkpoint (e.g.
GeneLab-Inverted-Pendulum-v0) with:(This is the next failure after PR #156 fixed the separate "No display detected" crash.)
Root cause
_extract_rsl_rl_actor(src/genelab/rl/backends/rsl_rl.py) readrunner.alg.actor_criticand returned(None, num_obs)when missing. Theinstalled rsl_rl's
PPO.__init__no longer hasactor_critic— it setsself.actor,self._raw_actor,self.critic,self._raw_criticdirectly(verified via
inspect.getsource). So the attribute path was stale,actor_moduleended upNone, and_export.pyraised.Fix
Source the actor from
alg._raw_actor(the uncompiled module; falls back toalg.actor, which may be atorch.compilewrapper). The actor is anMLPModelwhose ownforwardtakes aTensorDictand self-normalizes, so weuse its
as_jit()wrapper —_TorchMLPModel, which exposes the flatforward(obs) -> deterministic actioncontract (learned obs normalizer bakedin) that GeneLab's exporter wraps with env-side scale/clip. Input dim comes
from
actor.obs_dim. The legacyalg.actor_critic.actor/act_inferencepath is kept as a fallback for older rsl_rl.
Verification (headless, real checkpoint)
QD_GRAPH=0 QT_QPA_PLATFORM=offscreen genelab export GeneLab-Inverted-Pendulum-v0 <ckpt> -f {torchscript,onnx} --out ....ts/.onnx+.metadata.jsononnx.checker; IOobs:[batch,8] -> actions:[batch,1](dynamic batch)Tests
tests/test_export.py:test_extract_rsl_rl_actor_new_layout— builds a real rsl_rlMLPModel,asserts extraction returns a flat-input deterministic module with the right
dim, and runs it through the full
export_policy-> loadable.ts.test_extract_rsl_rl_actor_legacy_layout—alg.actor_critic.actorpath.test_extract_rsl_rl_actor_missing_returns_none—(None, num_obs)so thecaller raises a clear error.
tests/test_export.py— 10 passed; export+rsl suite 17 passed; ruff clean.Docs
docs/concepts/eval-and-export.{en,zh}.mdupdated to describe the newextraction path (convention: docs update for
rl/backends/changes).Reference audit
find_referencing_symbols(_extract_rsl_rl_actor)→ only caller isRslRlBackend.make_inference_setup(rsl_rl.py:120); signature unchanged, noother caller affected.
🤖 Generated with Claude Code