feat(algo): H-Net, diffusion and BC algorithms - #555
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
4debbbe to
39d9533
Compare
dc37329 to
6cddc2e
Compare
53e3f8e to
02933b4
Compare
…thms algo/hnet, algo/diffusion (with its outer-stage variants) and algo/bc. Builds on the model zoo in the previous commit. Also carries egomimic/pipeline/ -- the batchflow stage framework, its runner PipelineAlgo and the stage implementations -- plus the three H-Net lightning callbacks (random_attn_dropout, chunker_residual_scheduler, ratio_loss_scheduler) and BATCHFLOW.md. These sit here rather than in the infra commit because they import egomimic.models.hnet and egomimic.models.diffusion from the model zoo below, and pipeline/algo.py additionally imports egomimic.algo.hnet.episode_transforms from this commit. Carrying them lower left the infra commit unable to import six of its own modules when checked out on its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
HNetPolicy.step referenced embodiment_id at two places in its body but never
declared it -- not a parameter, local, or attribute. The method failed two ways:
* PackedAlgoBase.inference_step already calls
policy.step(..., embodiment_id=self.domain_by_id.get(emb_id)), which raised
TypeError: unexpected keyword argument;
* called without it, the body raised NameError at the action_out lookup.
Either way the AR single-step path used for closed-loop sim rollout could not
run. The sibling policy step() in this same file already declares
embodiment_id: Optional[str] = None; this matches it, so the existing callers
work unchanged and single-embodiment models keep the None default.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
auxiliary_ac_keys: dict = {} and aux_ac_keys=[] are evaluated once at import and
shared by every caller that omits them. Neither is mutated today (the dict is
copied on assignment, the list is only iterated), so this is prevention rather
than a live bug fix.
Both become None and are materialised inside the function, leaving the
omitted-argument behaviour identical. Adds the missing typing.Optional import.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ages DualStreamChunkedOuterStage and MultiStreamOuterStage both already subclass DualStreamOuterStage, and all three opened encode() with byte-identical copies of the same ~27 lines: the packed-only guard, unpacking actions/__obs, deriving T_total/device/dtype, casting cu_seqlens, accumulating the SPECIFIC stream over input_modules, and computing the AGNOSTIC stream. That block is packed-sequence boundary handling. A cu_seqlens device or dtype fix applied to one copy silently missed the other two -- three places to get the same thing wrong, with no test that would notice. Three helpers on the shared base replace it: _packed_inputs (guard + unpack, taking the caller name so each class keeps its own NotImplementedError message), _specific_stream and _agnostic_stream. Control flow in every encode() is otherwise untouched; only the derivation moved. Net -37 lines. Verified: ruff F401/F821/F841 clean on both files; all three classes import and inherit the helpers; the packed-only guard still fires per class with its own message. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
egomimic/algo/diffusion/ (the DFoT algo and its nine outer stages) moves to its own PR stacked on top of this one. Nothing on main depends on it, and nothing remaining in this stack imports it -- models/diffusion stays, because the batchflow pipeline imports SinusoidalPosEmb from it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
HNetPolicy.init_step_state and HNetOuterStage.init_step_state were the same 27
lines -- same signature, same T_max coercion, same seven-key state dict --
differing only in which submodule owns the KV cache (self.hnet vs
self.inner_stage). Neither class has a base to hang it on, so it becomes a
module-level _init_ar_state(module, cache_owner, ...).
Worth more than its line count because both copies carried
dtype = dtype or next(self.parameters()).dtype
Allocating this state at a fixed dtype instead of the model's own is what once
produced a bf16 rollout state under fp32 weights, under-measuring H-Net
closed-loop coverage ~2-2.6x and reading as the policy failing closed-loop. One
copy of that derivation is the right number.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude Code ReviewReview of PR #555: H-Net, diffusion and BC algorithmsSummaryLarge refactor introducing Key concerns1.
|

algo/hnet, algo/diffusion (with its outer-stage variants) and algo/bc. Builds on
the model zoo in the previous commit.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com