[None][feat] Add Cosmos3-Edge (Nemotron-dense) support - #16773
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughCosmos3-Edge support adds Nemotron-dense architecture handling, checkpoint-aware generation defaults, native-flow sampling, prompt and scheduler updates, CLI and documentation entries, and unit, parity, distributed, and LPIPS integration coverage. ChangesCosmos3 visual generation support
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant User
participant VisualGen
participant Cosmos3OmniMoTPipeline
participant Cosmos3VFMTransformer
participant LPIPSTest
User->>VisualGen: select nvidia/Cosmos3-Edge and output mode
VisualGen->>Cosmos3OmniMoTPipeline: merge mode-aware defaults
Cosmos3OmniMoTPipeline->>Cosmos3VFMTransformer: denoise Edge latents
Cosmos3OmniMoTPipeline-->>User: return image or video
LPIPSTest->>Cosmos3OmniMoTPipeline: run deterministic generation
LPIPSTest->>LPIPSTest: compare output with golden reference
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
tests/integration/defs/examples/visual_gen/test_visual_gen.py (1)
2116-2141: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winEdge LPIPS gates lack on-failure candidate preservation. The three Edge gates assert the threshold but never call
_preserve_lpips_candidate_on_failure, so a cross-host failure leaves no archived media to refresh the golden — yet the Edge goldens'threshold_rationaleexplicitly banks on that helper for the ~0.04 cross-host headroom. The distilled I2V gate (Lines 2299-2305) already wires this up; mirror it here (each gate takesrequestand passes its generated path + golden basename).
tests/integration/defs/examples/visual_gen/test_visual_gen.py#L2116-L2141: addrequestto the signature and call_preserve_lpips_candidate_on_failurebefore_assert_lpips_below_thresholdwithgenerated_path/cosmos3_edge_t2v_lpips_golden_video.mp4.tests/integration/defs/examples/visual_gen/test_visual_gen.py#L2144-L2172: same, withcosmos3_edge_i2v_lpips_golden_video.mp4.tests/integration/defs/examples/visual_gen/test_visual_gen.py#L2175-L2201: same, withcosmos3_edge_t2i_lpips_golden.png(also add the_visual_gen_deps/requestfixtures already noted separately).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/integration/defs/examples/visual_gen/test_visual_gen.py` around lines 2116 - 2141, Update the three Edge LPIPS gates in tests/integration/defs/examples/visual_gen/test_visual_gen.py at lines 2116-2141, 2144-2172, and 2175-2201: add the request fixture to each test signature, call _preserve_lpips_candidate_on_failure with the generated path and the corresponding golden basename before _assert_lpips_below_threshold, and add the _visual_gen_deps fixture to the T2I gate as needed. Use cosmos3_edge_t2v_lpips_golden_video.mp4, cosmos3_edge_i2v_lpips_golden_video.mp4, and cosmos3_edge_t2i_lpips_golden.png respectively..gitignore (1)
125-126: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
.plans/looks unrelated to this PR's scope.This ignore entry isn't tied to Cosmos3 Edge/distilled support and reads like a local tooling artifact. Consider dropping it here and adding it in a dedicated change (or your personal global gitignore) to keep the PR focused.
As per coding guidelines: "Keep each pull request focused on one concern and avoid scope creep; split unrelated changes into separate pull requests."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.gitignore around lines 125 - 126, Remove the unrelated .plans/ entry from .gitignore to keep this change focused on Cosmos3 Edge/distilled support; do not replace it with another ignore rule.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In @.gitignore:
- Around line 125-126: Remove the unrelated .plans/ entry from .gitignore to
keep this change focused on Cosmos3 Edge/distilled support; do not replace it
with another ignore rule.
In `@tests/integration/defs/examples/visual_gen/test_visual_gen.py`:
- Around line 2116-2141: Update the three Edge LPIPS gates in
tests/integration/defs/examples/visual_gen/test_visual_gen.py at lines
2116-2141, 2144-2172, and 2175-2201: add the request fixture to each test
signature, call _preserve_lpips_candidate_on_failure with the generated path and
the corresponding golden basename before _assert_lpips_below_threshold, and add
the _visual_gen_deps fixture to the T2I gate as needed. Use
cosmos3_edge_t2v_lpips_golden_video.mp4,
cosmos3_edge_i2v_lpips_golden_video.mp4, and cosmos3_edge_t2i_lpips_golden.png
respectively.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 82c2a32f-30dc-4081-8a65-f056cb82ae4c
⛔ Files ignored due to path filters (1)
tests/integration/defs/examples/visual_gen/golden/visual_gen_lpips/visual_gen_lpips_golden_media.zipis excluded by!**/*.zip
📒 Files selected for processing (24)
.gitignoredocs/source/models/supported-models.mddocs/source/models/visual-generation.mdexamples/visual_gen/configs/cosmos3-t2i-1gpu.yamlexamples/visual_gen/models/cosmos3/README.mdexamples/visual_gen/models/cosmos3/cosmos3.pyrequirements.txttensorrt_llm/_torch/visual_gen/models/cosmos3/defaults.pytensorrt_llm/_torch/visual_gen/models/cosmos3/pipeline_cosmos3.pytensorrt_llm/_torch/visual_gen/models/cosmos3/sampling.pytensorrt_llm/_torch/visual_gen/models/cosmos3/transformer_cosmos3.pytensorrt_llm/_torch/visual_gen/pipeline.pytests/integration/defs/examples/visual_gen/golden/visual_gen_lpips/cosmos3_edge_i2v_lpips_golden_video.jsontests/integration/defs/examples/visual_gen/golden/visual_gen_lpips/cosmos3_edge_t2i_lpips_golden.jsontests/integration/defs/examples/visual_gen/golden/visual_gen_lpips/cosmos3_edge_t2v_lpips_golden_video.jsontests/integration/defs/examples/visual_gen/golden/visual_gen_lpips/cosmos3_i2v_4step_lpips_golden_video.jsontests/integration/defs/examples/visual_gen/test_visual_gen.pytests/integration/test_lists/test-db/l0_b200.ymltests/unittest/_torch/visual_gen/conftest.pytests/unittest/_torch/visual_gen/cosmos3_edge_diffusers_parity.pytests/unittest/_torch/visual_gen/test_cosmos3_distilled.pytests/unittest/_torch/visual_gen/test_cosmos3_edge.pytests/unittest/_torch/visual_gen/test_cosmos3_pipeline.pytests/unittest/_torch/visual_gen/test_cosmos3_transformer.py
fredricz-20070104
left a comment
There was a problem hiding this comment.
Review summary - CONCERNS
Verdict: No blocking code defect found, but this cannot merge yet — the branch is dirty (conflicts with main) and the strict weight-loading change is high-blast-radius and warrants QA on existing checkpoints before merge.
Concerns
-
[MAJOR] PR is not mergeable (
mergeable_state=dirty)- What is wrong: the branch conflicts with base
main. - How it fails: a merge now either fails or forces an unreviewed manual conflict resolution.
- Suggested fix: rebase onto current
main, resolve conflicts, re-run thel0_b200visual_gen suite, and confirm the state goes clean.
- What is wrong: the branch conflicts with base
-
[MAJOR]
tensorrt_llm/_torch/visual_gen/models/cosmos3/transformer_cosmos3.py:~1523-load_weightsis now default-fail for every Cosmos3 checkpoint- What is wrong:
load_weightsnow raises when any constructed parameter has no checkpoint tensor, replacing the previous behaviour that silently kept init values. This path is shared by Nano, Super, audio-capable and distilled variants, not just Edge. - How it fails: an existing Super/audio checkpoint that previously loaded because a benign tensor was silently skipped (name drift, an optional/extra tensor, or a module the recipe no longer builds) will now hard-fail at load. In this PR only Nano is clearly exercised end-to-end (LPIPS +
test_cosmos3_example); Super and audio-capable real checkpoints are covered only via reduced synthetic state dicts. - Suggested fix: load each currently-supported real checkpoint (Nano, Super, audio, both distilled) through the new strict loader in CI/QA before merge, or scope the strict-fail to the new recipe until the older variants are confirmed clean.
- What is wrong:
Minor notes (non-blocking)
tests/integration/defs/examples/visual_gen/test_visual_gen.py:~2116- the three Edge LPIPS gates don't call_preserve_lpips_candidate_on_failure; mirror the distilled I2V gate so cross-host failures archive a candidate to refresh the golden.tests/integration/defs/examples/visual_gen/test_visual_gen.py:~2175-test_cosmos3_edge_t2i_lpips_against_goldenomits the_visual_gen_depsfixture its siblings take.
QA view
- Test coverage: adequate for the new Edge/distilled paths (recipe validation, Nemotron norm bit-exactness, generator-only K-norm regression, native-flow schedule parity, strict-loading positive/negative cases, mode resolution, denoise-loop contract). Uncovered: strict load of real Super/audio checkpoints; native-flow validated against recorded fixtures rather than a live cross-run.
- SM coverage: architecture-independent (bf16, VANILLA attention, RMSNorm/MLP; no arch guards in the diff). Tests run on B200 (sm100). Numeric goldens captured on B200; other-SM parity relies on documented cross-host LPIPS headroom.
- Test code: Edge LPIPS gates lack candidate preservation; one gate lacks
_visual_gen_deps; the diffusers-parity subprocess script is env/checkpoint-gated and silently skips when unavailable. - Test time: significant - four new B200 LPIPS gates + three example smoke tests added to
l0_b200.yml(TIMEOUT 30/45/30 and 20/20/15/15), a refreshed golden media zip, and ~2200 lines of new unit tests. - Needs
/qa-verify: yes - resolve the dirty merge and confirm existing Super/audio checkpoints still load under the now strictload_weights.
Possible new issues
- Strict
load_weightscould crash an existing Super/audio checkpoint that previously loaded with a silently-skipped tensor. forward()now writes the I2V conditioning frame in place without the prior.clone()/.to(device,dtype); correct only ifimage_latentalready matches the loop output's device/dtype.
What I could not verify
- Whether every real Super/audio/distilled checkpoint's full parameter set is covered by the remap so the strict loader does not false-positive (callers and real checkpoint layouts are not in the diff).
- Runtime LPIPS/parity numbers and whether the goldens reproduce on the CI B200 host within the stated thresholds.
Automated review by NVCortex Lite, run by @fredricz-20070104.
The README documented "--prompt or a JSON file path", but --prompt passed its value through verbatim, so pointing it at a checkpoint's assets/*_prompt.json generated from the 43-character path string and produced artifact-ridden output. --negative_prompt did resolve paths, which made the asymmetry easy to miss. Neither flag could consume a checkpoint's own prompt asset either: those files are structured caption objects with no top-level "prompt" key, so load_prompt_file rejected them and there was no way to reproduce the model-card sample. --prompt and --negative_prompt now each take literal text or a path, selected by whether the value names an existing file. --prompt_file and the new --negative_prompt_file take a path only and fail loudly when it is missing, so scripted callers cannot silently fall back to text. Prompt files may hold an omni prompt object, a structured caption, or plain text. Update the Edge example to the model-card invocation and document the flags. Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
…ults Unmarking a filled default relies on model_fields_set returning the live __pydantic_fields_set__ rather than a copy. Name the test that enforces it so a pydantic upgrade that breaks the assumption is traceable to this line. Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
A caller-supplied flow_shift outside the cacheable set takes the uncached path in _scheduler_for, so the resulting scheduler lands on self.scheduler (and self.audio_scheduler) without ever entering _scheduler_cache. Walking only the cache left its latent-sized model_outputs pinned until the next request replaced the attribute -- exactly the caller-override case the bounded cache exists for. Also read _scheduler_cache directly: it is initialised unconditionally in __init__, unlike the two live schedulers, which are genuinely optional. Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
Every rank of a TP/Ulysses worker runs _log_envelope_advisory, so an out-of-envelope request produced one warning per rank per request. Gate on rank 0 the way the surrounding logs already do. Gated inside the helper rather than at its call site so the behavior is unit-testable without driving forward(). Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
…t not text The two paths disagree by design: the reference keeps the fractional value in the plain-text template and truncates in the structured one. Cite both so the asymmetry is not mistaken for a bug and normalized later. Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
The checkpoint's negative prompt contains "LOD (level-of-detail)", which codespell reads as a misspelling of LOAD. Widening the shared ignore list suppressed it everywhere; an inline directive on the one line that needs it leaves the rest of the repo checked and reverts .pre-commit-config.yaml to upstream. Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
_bare_pipeline set pipeline.rank = 0, but rank is a property derived from torch.distributed with no setter, so every test using the fixture raised AttributeError. The property already yields 0 when dist is uninitialised, so the assignment was unnecessary; the non-zero-rank case shadows the property on the class instead. Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
…zation The Edge cases were ported into this file when upstream split test_visual_gen.py; that port lived in a merge commit, which rebasing drops. Also restores the negative_prompt="" pins the nano/4step goldens were baked against. Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
|
/bot run --disable-fail-fast |
|
PR_Github #65129 [ run ] triggered by Bot. Commit: |
|
/bot run --disable-fail-fast |
|
PR_Github #65129 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #65229 [ run ] triggered by Bot. Commit: |
|
PR_Github #65229 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #65246 [ run ] triggered by Bot. Commit: |
|
/bot run --disable-fail-fast |
|
PR_Github #65318 [ run ] triggered by Bot. Commit: |
|
PR_Github #65246 [ run ] completed with state |
|
PR_Github #65318 [ run ] completed with state |
|
✅ LFS objects already in storage (1 file) — no sync needed. These LFS-tracked files are already present in this repository's LFS storage:
|
… presets The Edge merge (NVIDIA#16773) replaced _apply_flow_shift with _scheduler_for but missed _forward_transfer's call site, so every transfer request raised AttributeError after media decode and control generation, right before denoising. Assign the result rather than calling bare: forward() deliberately skips the scheduler rebuild when a transfer config is present, so this is transfer's only scheduler setup and dropping the return would leave whatever schedule the previous request left on the worker. Five test stubs assigned the removed method onto __new__'d pipeline fakes, which is why CI stayed green against zero definitions -- a bare attribute assignment invents whatever name it is given. Two of them were dead weight (those tests stub _forward_transfer too), and the recorded flow shifts in a third were never asserted. Drop all five and give StubSamplingPolicy the set_flow_shift its own docstring already claimed, so the tests drive the real _scheduler_for and a future rename fails loudly instead of being absorbed. resolve_transfer_config materialized an omitted guidance_scale to 1.0 before the single-hint merge, making the user_set check always true and the tuned per-hint presets unreachable: every edge/blur/depth/seg transfer ran at 1.0 instead of 3.0. Both references apply the preset -- cosmos-framework gates on an explicit user_fields set, vllm-omni on _is_user_field -- so gate on model_fields_set, which the executor already clears for merged defaults. Multi-hint requests keep falling back to the generic video default. _cacheable_flow_shifts() never consulted TRANSFER_DEFAULTS. No behavior change today, since every hint declares V2V's 10.0, but tuning one off that value would silently drop it from the cache and rebuild a scheduler per request. Port emphasize_control_in_prompt from cosmos-framework: the active hint names are appended to the user prompt as a control-adherence directive, on by default, positive prompt only, system prompt untouched. Signed-off-by: Igor Shovkun <igshov@gmail.com>
Edge (NVIDIA#16773) refactors transformer_cosmos3.py around a Cosmos3ArchRecipe and moves both decoder layers' MLP construction into _build_cosmos3_mlp(). Our split_gate_up=uses_static_fp8(model_config) lives at those construction sites, so it is threaded into the factory instead. Resolving that hunk in Edge's favour would leave static FP8 silently on the fused topology: it still loads, still runs, and still renders plausible images while re-quantizing 56% of shards onto max(scales), which is the defect this branch exists to fix. The other two conflicts: - test_visual_gen_cosmos3.py: our FP8 golden test and Edge's T2V golden test were spliced together by the 3-way merge because they share a tail (_run_lpips_eval's trailing args and the _preserve_lpips_candidate_on_failure prologue). Keeping "both sides" truncates one of them, so both were reconstructed with the shared section duplicated. The result carries all 13 tests: upstream's 12 plus ours. Our generator also lost its outer finally -- the guardrails-env restore -- at a conflict boundary; restored. - visual_gen_lpips_golden_media.zip: an LFS binary both sides added images to. Upstream's copy was materialized and our golden re-added, so Edge's three goldens and ours now coexist (42 entries). Rebuilt incrementally against the merged tree (1.3.0rc25, 172 targets). Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
Dev Engineer Review
nvidia/Cosmos3-Edgesupport for text-to-image, text-to-video, and image-to-video at native 480p.NemotronRMSNorm, MLP variants, RoPE resolution, generator-only key normalization, and strict checkpoint coverage checks.use_und_k_norm_for_gen._merge_defaultsandVisualGen.default_paramsto preserve caller-versus-pipeline default state across serialization.QA Engineer Review
Test functions and coverage added or modified:
tests/unittest/_torch/visual_gen/test_cosmos3_edge.pyl0_b200.ymlthrough the Cosmos3 Edge unit entry.tests/unittest/_torch/visual_gen/cosmos3_edge_diffusers_parity.pyl0_b200.yml; verify invocation through the Edge unit test.tests/unittest/_torch/visual_gen/test_cosmos3_distilled.pytests/unittest/_torch/visual_gen/test_cosmos3_pipeline.pytests/unittest/_torch/visual_gen/test_cosmos3_transformer.pyrope_scalingandhas_action_weightsregression coverage.tests/unittest/_torch/visual_gen/multi_gpu/test_cosmos3_transformer_parallel.pytests/integration/defs/examples/visual_gen/test_visual_gen_cosmos3.pyl0_b200.ymlthrough the Edge I2V and three LPIPS entries.tests/integration/test_lists/test-db/l0_b200.yml.Verdict: needs follow-up. The primary Edge unit and integration tests are listed for CI. Several modified unit and distributed test modules are not explicitly represented in the changed test list, and CBTS coverage data is unavailable.
Description
Adds inference support for
nvidia/Cosmos3-Edge, the 4B Cosmos3 variant whosereasoner and generator towers use the Nemotron-dense architecture instead of
Nano/Super's Qwen3. Supported tasks: T2I, T2V, I2V (480p-native).
Builds on the sampling-policy and checkpoint-declared-defaults plumbing
introduced by #16690 (distilled I2V-4Step), now merged into
main.Reference implementations: diffusers
Cosmos3OmniTransformer/Cosmos3OmniPipeline(huggingface/diffusers#14181 + #14246) for thetransformer, and cosmos-framework's PyTorch backend for the sampling schedule.
Architecture recipes (the core change).
backbone_typein the transformerconfig selects a complete, validated architecture recipe rather than
individual flags steering construction — a mixed config cannot half-apply and
fails at startup with the offending key named. The Nemotron-dense recipe:
non-gated squared-ReLU MLP (reusing
_torch/modules/mlp.py::MLPwith theexisting
relu2activation, asmodeling_nemotron.pydoes — no Edge MLPclass), no reasoner Q/K norm, and a new per-layer
k_norm_und_for_genapplied to the reasoner's keys only where the generator consumes them: in the
cached-KV design,
forward_with_kvattends withrope(k_raw)internally butcaches
rope(k_norm_und_for_gen(k_raw))for the generator layers. Thisdistinction is subtle enough that both public references shipped it wrong
initially (diffusers normed the reasoner pathway too, fixed in #14246;
vllm-omni read a transposed config key and skipped the norm entirely, fixed
in vllm-project/vllm-omni#5239) — it is pinned here by a dedicated
regression test. Edge norms use the Nemotron flavor (weight multiply in fp32
before downcast);
F.rms_normis bit-exact to that flavor, soNemotronRMSNormis a one-line fused wrapper, and the attention Q/K norms ofboth recipes now route through norm modules instead of a hardcoded
functional — byte-identical for Nano by construction (pinned by test).
Native flow schedule. Edge's
model_index.jsondeclaresuse_native_flow_schedule: true; the intended schedule (per the model cardand cosmos-framework's PyTorch backend) is linear flow sigmas with a runtime
shift of 3.0. Stock diffusers does not reproduce it — its UniPC karras branch
discards the provided sigmas (the checkpoint config ships
use_karras_sigmas: true), which is why the schedule is validated againstcosmos-framework directly. The implementation configures diffusers' own
Apache-2.0
UniPCMultistepScheduler(karras off,flow_shiftfrom theper-mode table, explicit linspace sigmas): timesteps are bit-identical to
cosmos-framework's
FlowUniPCMultistepSchedulerand full multi-stepstep()trajectories agree to ≤1.6e-7 relative across three (shift, steps) fixtures
recorded in the tests — no OpenMDW code is copied.
A scheduler's identity is its resolved
(flow_shift, use_karras_sigmas)pair, not the request mode, so
forward()resolves that pair — mode table,then V2V's stronger shift, then a caller-supplied
flow_shift— and takesthe instance from a cache keyed on it. Each configuration is constructed at
most once and never rebuilt; a mode that is never served never builds one,
and modes that resolve to the same pair share an instance (Edge's video and
image tables both declare shift 3.0, so Edge builds one scheduler, not two).
Streams key separately so audio gets its own instance at the same
configuration — schedulers mutate state on every
step(), and the twostreams denoise in lockstep. This replaces the per-request rebuild that
#16155 introduced for V2V, which reconstructed a scheduler on every mode
alternation.
Strict weight loading (both recipes benefit).
load_weightspreviouslycollected skipped modules and dropped the list on return — a missing tensor
silently kept its init values. Coverage is now default-fail in both
directions at parameter granularity: any parameter of a constructed module
(root parameters included) without a checkpoint tensor raises with names, a
partially covered fused QKV raises, and mapped tensors that land on no
constructed parameter warn with names. The explicit skip list (
lm_head, thereasoner's final
norm— text-output path VisualGen never computes — and theaction heads) is logged, never silent.
Pipeline. The tokenizer loads via
AutoTokenizer(Edge ships a NemotronPreTrainedTokenizerFast; eos = pad = 11,<|vision_start|>= 20).Generation defaults become a
(family, mode)table — family resolved fromthe same recipe function, mode from the request's output type, never from the
checkpoint name — with Edge's model-card values (video 832×480 × 121 frames,
50 steps, guidance 5.0, shift 3.0; T2I 640×640, guidance 4.0).
forward()'snumeric parameters are now None-defaulted and resolve through the same
tables, so direct callers get checkpoint-appropriate values (this also lets
the sampling policy fill fixed distilled steps/guidance for direct callers).
Requests outside the model-card envelope (256p/480p, 50–150 frames, 12–30
fps) log one advisory line and proceed — the reference runtime accepts a
wider range, so the envelope is documented support, not enforced validation.
The checkpoint's action weights are skipped loudly and the init log says
action generation is not supported;
enable_safety_checker: falsein themodel_index is deliberately not honored (guardrail policy unchanged).
Verified on 1×B200: per-step transformer velocity parity vs diffusers main is
0.7–1.6% relative (bf16, both CFG branches, masked I2V path included); E2E
LPIPS vs reference goldens: T2V 0.045, I2V 0.078, T2I 0.006.
Out of scope for Edge: action generation (lands on the in-flight cosmos3
action work), audio (the checkpoint has no audio tower — requesting it
raises), and V2V/transfer — not an Edge capability, since the generator's
inputs are text, image, and action trajectories only. V2V itself is
supported for Nano/Super via #16155; this PR merges that work and keeps its
request path intact, it just does not extend it to Edge.
Reference-parity fixes for prompt conditioning (follow-up commits). Three
divergences from cosmos-framework in how prompt text is built, found while
investigating an artifact report on Edge. Each is verified by comparing the text
reaching the tokenizer against the reference on the real assets, and each is
independently corroborated by vllm-omni, which matches cosmos-framework on every
point.
The negative prompt took the JSON field-injection branch.
forward()routed itthrough
_format_prompt_with_metadata, which for a JSON prompt injectsduration/fps/resolution/aspect_ratioas object fields. cosmos-frameworkapplies its plain-text formatter to the negative unconditionally
(
inference.py:541) and reserves field injection for the positive; vllm-omni doesthe same (
pipeline_cosmos3.py:2095). 125 of ~2900 tokens differed, all at the tail— immediately before the handoff to the video tokens. Now byte-identical at 14936
chars / 2910 tokens.
JSON metadata values.
duration"5.0s"→"5s",fps24→24.0,resolution{"W","H"}→{"H","W"},aspect_ratiofrom the reduced ratio"15,26"to the nearestW,Hbucket"16,9", andjson.dumpsback to the defaultensure_ascii=True. Stills now popduration/fpsinstead of merely skipping them.Two of these were not cosmetic: the checkpoint's own
example_i2v_prompt.jsonalready carries
"aspect_ratio": "16,9", which the reduced-ratio computationoverwrote with a string outside the bucket vocabulary the model saw in training; and
a T2I request kept the source prompt's stale
"duration": "7s"._aspect_ratio_bucketround-trips all 25 entries of cosmos-framework'sVIDEO_RES_SIZE_INFO.Default negative prompt for video modes. The pipeline defaulted every mode to
empty, matching diffusers and vllm-omni but not cosmos-framework, whose per-mode
defaults wire
neg_prompts.jsoninto text2video, image2video, video2video andaudio_image2video while leaving text2image/image2image unset. Video modes now default
to it, carried as a Python literal in
negative_prompt.pyso it ships in everyinstall mode without a
package_dataentry. Image modes keep the empty default — theprompt is almost entirely temporal vocabulary a still cannot exhibit, and the model
card advertises nothing for image generation.
Blast radius. (3) changes default output for every Cosmos3 video request that
does not pass a negative prompt — Nano and Super included, not only Edge. The
LPIPS goldens were generated against an empty uncond branch, so their three helpers
now pin
negative_prompt=""explicitly rather than inheriting a default they neverrecorded.
.pre-commit-config.yamlgains one codespell word (LOD); the vendoredtext cannot be edited without breaking parity.
These are parity fixes, not artifact fixes. They make the conditioning match the
reference; they do not reduce generation artifacts. Measured across 5 seeds on the
model-card config, pre- vs post-fix moves the artifact rate from 11.82x to 10.87x
median — improved or tied on every seed, but p=0.71, i.e. indistinguishable.
Test Coverage
tests/unittest/_torch/visual_gen/test_cosmos3_edge.py, 78 tests, nocheckpoint required for the unit tier): recipe selection/validation with
rejection cases (unknown
backbone_type, contradicting flags, latent-geometryinvariants, inconsistent
patch_latent_dim); Nemotron RMSNorm bit-exactnessvs the Qwen flavor; the generator-only K-norm regression (perturbing
k_norm_und_for_genleaves reasoner attention bit-identical) plus anumeric identity check; Nano Q/K byte-identical pin; native-flow schedule
parity against three recorded cosmos-framework fixtures (bit-equal
timesteps, full
step()trajectories to 1e-9); strict-loading coverage inboth directions (missing generic/architecture-specific/root tensors raise,
partial fused raises, skip list and unconsumed-tensor warnings asserted by
content); per-family defaults/warmup/advisory resolution and the
executor-defaults shape.
vs a diffusers-main golden and the uncond CFG branch vs a recorded
self-golden (keep-metadata semantics documented); model-index detection;
recipe/scheduler wiring (both mode schedulers at shift 3.0, karras off);
full 549-tensor load + forward; direct
forward(None)resolution reachingthe generation path with Edge values; T2V/I2V/T2I sanity generations with
shape and non-black checks.
DIFFUSERS_MAIN_PATH, subprocess because the pinneddiffusers predates the Edge classes): per-step velocity comparison vs
diffusers main on the real checkpoint, threshold 5% (observed 0.7–1.6%).
test_cosmos3_edge_i2v_example,l0_b200.yml): thedocumented example invocation at the deployed 480p × 121-frame, 50-step
shape; asserts a non-empty MP4.
test_cosmos3_edge_{t2v,i2v,t2i}_lpips_against_golden,l0_b200.yml): LPIPS vs goldens produced by the reference implementation(diffusers main with the scheduler patched to the native flow schedule —
equivalent to cosmos-framework at fp32-ulp), with matched initial noise and
matched cond/uncond prompt texts, so the gates check the denoising
trajectory against the reference rather than regression against a past
TRT-LLM run. Thresholds 0.10 / 0.13 / 0.05 (measured 0.0447 / 0.0778 /
0.0056 at creation; a wrong-seed I2V run measures 0.858). The I2V gate runs
10 steps — cross-stack drift accumulates per step and the deployed 50-step
shape is covered by the example test. Full provenance in
golden/visual_gen_lpips/cosmos3_edge_*.json.pinned byte-identical through the norm-routing and loader refactors.
test_cosmos3_pipeline.py): the negative prompt keepsits serialized JSON and gains sentences rather than injected fields, checked
byte-for-byte against the reference algorithm; the positive branch still injects,
so the two paths stay deliberately distinct; aspect-ratio bucket mapping over seven
resolutions; non-ASCII escaping; stills dropping stale
duration/fps; and thevideo/image split of the default negative prompt including its serialization and
cache identity.
Cosmos3-Edge(8.7 GB) must be staged in the CIllm-models/storage, or the checkpoint-gated tests skip.PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title.Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.