Add LingBot-VA Robotwin integration for V2 - #520
Conversation
|
/ready to test faed607 |
|
/ok to test faed607 |
@jmccaffrey-nv, there was an error processing your request: See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/ |
|
/ok to test d9cdd92 |
db3d6fe to
94bee38
Compare
Greptile SummaryThe PR adds a self-contained LingBot-VA RoboTwin model package and a V2 application adapter for one-shot joint video/action rollouts.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains in the eligible follow-up review scope. No blocking failure remains. Important Files Changed
Sequence DiagramsequenceDiagram
actor User
participant Runtime as V2 Runtime
participant App as LingBot-VA Application
participant Session as Session / Model Loop
participant Engine as LingBot-VA Engine
participant Model as Video-Action Model
participant Sinks as Generic Output Sinks
User->>Runtime: Launch with prompt, images, and model options
Runtime->>App: Initialize and validate session contract
App->>Session: Create session
Runtime->>Session: step()
Session->>Engine: Lazily construct and run
Engine->>Model: Encode prompt and observations
loop Autoregressive chunks
Engine->>Model: Denoise video and actions
Model->>Model: Advance conditional and unconditional KV caches
end
Engine->>Model: Release denoising state and decode video
Model-->>Engine: Video, actions, and metrics
Engine-->>Session: Complete rollout
Session-->>Runtime: StepResult with tensor artifact
Runtime->>Sinks: Write MP4, metrics, and actions
Reviews (7): Last reviewed commit: "Clarify LingBot offline action contract" | Re-trigger Greptile |
Code review record — #520 (+ dependency #524)Reviewed at Reproduced the stated CPU validation: Two findings were confirmed by execution rather than by reading; both are marked below. #524 — typed tensor artifactsWell-scoped and model-neutral as claimed. The generation semantics (latest-wins, buffered older output cleared, late stale batches ignored), the per-file 1. A failed run still writes its artifacts (medium). 2. 3. Output directory isn't validated until 4. Sinks opened after 5. Nit. #520 — LingBot-VA integration1. The destructive teardown frees none of the KV it targets — confirmed by execution
block_cache.self_attn.reset()
block_cache.cross_attn.text.k = torch.empty(0)
block_cache.cross_attn.text.v = torch.empty(0)Both lines are no-ops:
Verified directly: Scale under the Robotwin config: The buffers are eventually reclaimed by refcount when Suggested fix, which doubles as a reuse win: add a public 2. Rolling-window steady state reports a duplicated chunk as committed — confirmed by execution
Simulated with a 3-slot cache, one distinct value per chunk: From the first steady-state chunk onward, every denoising step attends to the previous chunk's KV twice and one chunk too few of history. Shapes don't change, nothing raises, and the outputs stay finite — it just quietly stops matching upstream. Reachable at 3. The unconditional branch is computed and discarded when its scale is 1.0 (efficiency)
The uncond cache exists because 4.
|
|
Addressed the actionable PR 520 review findings in
Final validation: 275 CPU tests passed (2 GPU tests deselected), all pre-commit hooks passed including The suggested shared UMT5/Wan-VAE/scheduler/RoPE/block/checkpoint/session-validation refactors are reasonable follow-ups, but are intentionally not mixed into this model-only stacked PR because they cross the #524 boundary or require renewed parity validation. The #524 sink-lifecycle observations likewise belong on that dependency PR rather than in this diff. |
| * (cfg.latent_width // ps[2]) | ||
| ) | ||
| action_chunk = cfg.frame_chunk_size * cfg.action_per_frame | ||
| window_slots = cfg.attn_window // 2 |
There was a problem hiding this comment.
Should the 2 in cfg.attn_window // 2 be cfg.frame_chunk_size? A slot holds one chunk of latent frames, so those look like they should be the same number. They match right now, so nothing's broken, but frame_chunk_size defaults to 4 on line 107 of this file, so if anyone ever leans on that default the window silently doubles. Should line 107's default be 2, to match the pipeline config and ROBOTWIN_FRAME_CHUNK_SIZE?
There was a problem hiding this comment.
(GPT Sol) Good catch on the stale default: frame_chunk_size now defaults to 2, matching Robotwin and the pipeline, with focused CPU coverage. I kept attn_window // 2 intentionally: pinned upstream create_empty_cache() uses that divisor for both its two-frame Robotwin config and its four-frame LIBERO/demo/Franka configs. The window counts paired video/action regions, not frames per chunk. I documented that invariant in code and the architecture README. Addressed in 830019e6.
| nn.SiLU(), | ||
| nn.Linear(self.dim, self.dim * 6), | ||
| ) | ||
| self.action_text_embedding = nn.Sequential( |
There was a problem hiding this comment.
Is action_text_embedding meant to be used somewhere? I can't find a caller. initialize_cache on line 264 builds the cross-attention text context once from self.text_embedding (the video one), and both the video and action forwards read that same cache.
There was a problem hiding this comment.
(GPT Sol) It is intentionally not used in inference. The pinned upstream model deep-copies the full condition embedder, but _input_embed(..., input_type="text") always calls condition_embedder.text_embedder; action mode only selects the copied time embedding/projection. Wiring the copied action text projection here would therefore diverge from upstream and invalidate the recorded parity. I retained it solely so the upstream checkpoint loads strictly and documented that invariant in 830019e6.
jarcherNV
left a comment
There was a problem hiding this comment.
Left a couple of comments but I don't think they should block anything. Up to you if you want to address them or not. The PR LGTM.
|
/ok to test bd95bf5 |
b1be7c9 to
0f0eb2a
Compare
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Jonathan McCaffrey <jmccaffrey@nvidia.com>
bd95bf5 to
7a15f43
Compare
jmccaffrey-nv
left a comment
There was a problem hiding this comment.
Design-review follow-up: the three questions are valid and are addressed in 7a15f43. The V2 session/model-loop now lives separately from app.py; the documentation explains why this fixed-input video-plus-action lifecycle does not map to the shared text-only T2V session; and the model package now includes a validated action manifest loader with four-panel plot and optional named CSV output. The docs also distinguish this offline I2AV adapter from the pinned upstream closed-loop RoboTwin client/server path.
|
/ok to test 7a15f43 |
|
/ok to test 7a15f43 |
Summary
Stack
This PR is stacked on #524 (
dev/jmccaffrey/v2-tensor-artifacts). It is rebased onto its current head, which contains currentorigin/main. Merge #524 first, then retarget this PR tomain.Relative to #524, this PR has no implementation changes under
flashdreams/flashdreams/runtime_v2/.Integrated scope
This adapter wraps the pinned upstream
WanVAServer.generate()path:actions[step, channel], and metricsStepResultUserInputEventsare not consumed; no live observation stream, simulator bridge, asynchronous motor execution, or robot actuation is implementedThis is a limitation of the FlashDreams adapter, not of LingBot-VA as a whole. Pinned upstream also has a closed-loop RoboTwin evaluator/server that executes action chunks, captures actual observations, and feeds observations plus executed state back into the KV cache. That path is documented but intentionally not ported here.
The adapter does not use the shared text-to-video session: its inputs include three camera observations, its outputs include robot actions, and its engine does not expose the shared per-block
generate/finalizelifecycle. It still reuses V2 interfaces and generic MP4, metrics, and tensor-artifact sinks.Action artifact decision
Discarding actions would remove the policy half of this video-action model. The adapter therefore declares one typed
actions[step, channel]artifact and emits all 16 selected RoboTwin channels:Upstream composes the relative poses with the initial end-effector poses and normalizes the quaternions before simulator execution. FlashDreams emits the denormalized relative values and does not actuate them.
The generic V2 result already supports multiple independently named tensors via
tuple[TensorArtifactOutput, ...]; no list API change is needed. LingBot-VA remains the first model integration exercising the facility, so validation with a second model remains an explicit follow-up rather than a claim in this PR.A model-specific
lingbot-va-visualize-actionscommand now validates committed artifact manifests and produces a four-panel two-arm trajectory plot plus optional named CSV. It stays outside the generic runtime and is diagnostic only.Architecture revisions
lingbot_va_v2/app.pylingbot_va_v2/session.pydocs/source/models/lingbot_va.rstThe earlier review fixes remain intact: steady-state KV rollover, teardown ordering, inactive CFG work elimination, private KV access removal, latent denormalization, prompt validation, cleanup reporting, and stale defaults/constants.
Validation
ty-W --keep-going: passeduv lock: resolved successfullylingbot-va-visualize-actionsentry point: exercised against legacy and committed-manifest outputs15bcdc4307e080218255e83946c2c2e5dbc30f3b7acd26c8925167017234e586[64, 16], finite, distinct second chunk463b307b667c1ca13a47bbbc5a17f68604621dfe3c3a10fc5860077216928d95, byte-identical to prior resident/offload and pre-review runsThe model README retains exact input hashes, checkpoint mapping counts, eager/compiled upstream parity results, reproduction commands, memory phases, and safety limitations.