Conversation
Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
Signed-off-by: Igor Shovkun <igshov@gmail.com>
Signed-off-by: Igor Shovkun <igshov@gmail.com>
c52332d to
9ceef65
Compare
Signed-off-by: Igor Shovkun <igshov@gmail.com>
ConstBob
left a comment
There was a problem hiding this comment.
Thanks for these TensorRT-LLM Transfer / Action / distilled guides. The use_guardrails vs vLLM guardrails split, distilled omit-num_inference_steps/guidance_scale, and Action safetensors contract are clear.
Static checks passed (notebook JSON, Python compile, assets, local links). I did not run GPU inference as part of the review. Transfer #16394 and Action #17325 are already on TensorRT-LLM main.
Two places where the write-up and the notebooks drifted apart (inline).
Nit, non-blocking: new distilled T2I/I2V cells in run_with_trt_llm.ipynb still go through the existing /v1/videos/generations helper, while this PR documents /v1/videos/sync as canonical. Fine if the alias stays.
Signed-off-by: Igor Shovkun <igshov@gmail.com>
Signed-off-by: Igor Shovkun <igshov@gmail.com>
|
When testing this PR there were a few issues that showed up. Shared it offline with Igor. Let's wait before merging this PR. |
Signed-off-by: Igor Shovkun <igshov@gmail.com>
5a51304 to
7ff4a86
Compare
Signed-off-by: Igor Shovkun <igshov@gmail.com>
|
Follow-up GPU check of Action forward dynamics (FD) on current HEAD.
All four: Note: notebook default Did not re-run Transfer / inverse dynamics, and did not retest GB200. LGTM on the Action FD path. |
|
|
Signed-off-by: Igor Shovkun <igshov@gmail.com>
Signed-off-by: Igor Shovkun <igshov@gmail.com>
Updated docs: a9029df, e4d59b6.
|
Could this comment be intended for another PR? #354 has no t2i_edge example. Its Nano/Super T2I examples already use image mode, /v1/images/generations, and PNG decoding. |
skasetty-Siri
left a comment
There was a problem hiding this comment.
Thanks—the original runtime-schema and blur-resolution comments are addressed. Before I approve for public release, please clarify the remaining guardrail limitation: the validation record reports missing safety models, and the September 17 follow-up reports failure with guardrails enabled.
Please provide validation with guardrails actually loaded, or obtain explicit release-owner acceptance of this limitation. Please also update the PR description to match the corrected validation record.
Updated the PR description with the corrected runtime revision, blur resolution, and guardrail clarification. |
|
Thanks for clarifying the warning and updating the description. Understood that it does not mean all guardrails failed. The remaining question is the separate pathsec failure with guardrails enabled. Please provide validation of a working configuration or explicit release-owner acceptance before we close that item. |
|
@skassety I added server-side NLTK setup in 1595ad3: it copies the required tokenizer/dictionary resources into a private directory as regular files and exports To clarify exactly which guardrail components are used:
We use every component enabled by the package’s default configuration; we have not disabled any additional checks. The 0.3.0 warning refers to its empty video-classifier list, not missing active models. I rebuilt the documented TensorRT-LLM revision and ran both Action notebooks and all five Transfer cases on one H200 with |
skasetty-Siri
left a comment
There was a problem hiding this comment.
Thanks for the fix and detailed clarification. The documented NLTK workaround, updated guardrail-enabled validation, and revised PR description address my remaining comments. Rechecked 1595ad3; no remaining blocking findings from my review.
## Summary - add a TensorRT-LLM walkthrough for the two published DMD2-distilled Cosmos3-Super students, `nvidia/Cosmos3-Super-Text2Image-4Step` (text-to-image) and `nvidia/Cosmos3-Super-Image2Video-4Step` (image-to-video), each on a single GPU - document the distilled request contract: the checkpoint's scheduler config locks the schedule to four stochastic (SDE) steps and classifier-free guidance is baked into the weights, so requests omit `num_inference_steps` and `guidance_scale` entirely and the server fills both in; a conflicting value is rejected, not clamped - leave `use_system_prompt` unset in every request so the image-to-video student's checkpoint-declared `default_use_system_prompt: true` applies - add both `trtllm-serve` launch commands to the shared setup guide, and index the notebook from the root README - **separately**: reword two guardrail blocklist false positives in the shared audiovisual negative prompts, without which no image-to-video request can run at all (see below) This is the follow-up #310 deferred ("keep the four-step distilled T2I/I2V examples out of this PR pending separate output-quality follow-up"). The examples match the assets every other backend already uses for its distilled sections — `robot_draping` for text-to-image and `car_driving` for image-to-video — so the cookbook surface is consistent across Cosmos Framework, Diffusers, vLLM-Omni, SGLang, and now TensorRT-LLM. The shipped scope is text-to-image and image-to-video only. These students are task-specialized and no other backend advertises text-to-video, video-to-video, or synchronized audio for them either. ## The guardrail fix, and why it is in this PR The shared audiovisual negative prompts contained two substrings that the `cosmos_guardrail` 0.3.0 `Blocklist` censors. Any request carrying them fails with HTTP 500 and `Text guardrail blocked prompt` **before any denoising runs**: | Text | Censored word | Replacement | |---|---|---| | `color bleeding between elements` | `bleeding` | `color smearing between elements` | | `The scene feels lifeless and sterile` | `lifeless` | `The scene feels inert and sterile` | Neither describes anything the blocklist is meant to catch; both are ordinary image-artifact vocabulary. The replacement wording is not invented here. TensorRT-LLM already ships a corrected copy of this exact prompt as `examples/visual_gen/models/cosmos3/cosmos3_negative_prompt.json`, and that is the default every Cosmos3 request falls back to when it sends no negative prompt of its own. Upstream's copy and the cookbook's differ in **exactly four leaves, and all four are these two substrings** — so the cookbook asset is simply stale. Both files are now identical to the TensorRT-LLM default. Kept as separate commits so they can be split out if preferred. Text-to-image was unaffected because that path sends no negative prompt — which is why only the image-to-video example hit it. Three related issues found while diagnosing this, **not changed here**: 1. The two files are shared by the Diffusers, vLLM-Omni, SGLang and base TensorRT-LLM notebooks, so this also unblocks their image-to-video / text-to-video / video-to-video examples. 2. `assets/prompts/image2video/humanoid_robot.json` is blocked by a *different* rule (partial match, not the word blocklist). That is the prompt the merged `run_with_trt_llm.ipynb` uses for `i2v_nano` and `i2v_super`. Left alone deliberately: rewording a *positive* prompt changes generated content. 3. `transfer/assets/negative_prompt.json` carries the same two substrings. That file belongs to #310, which now rewords both, so it is covered there rather than duplicated here. ## Validation ### GPU inference Both notebook sections were executed **as written** with `jupyter nbconvert --to notebook --execute` against real `trtllm-serve` VisualGen servers — the shipped notebook's own cells, not a re-implementation. TensorRT-LLM at `505a02ce04`, whose `tensorrt_llm/_torch/visual_gen`, `tensorrt_llm/visual_gen` and `examples/visual_gen` trees are byte-identical to `main` (`2dbab44d4f`); the only delta is test files. Hardware: 1 x NVIDIA B300. **Text-to-image** — `Cosmos3-Super-Text2Image-4Step` with `configs/cosmos3-t2i-1gpu.yaml`: ``` Distilled Cosmos3 checkpoint: fixed 4-step schedule [1.0, 0.9375, 0.8333333333333334, 0.625], classifier-free guidance baked in. Running warmup for Cosmos3OmniMoTPipeline: 1 shape(s) [1024x1024x1], 4 steps Denoising: 4 steps, guidance=1.0 POST /v1/videos/generations HTTP/1.1" 200 OK ``` Artifact: 57,617 bytes, decoded with PyAV as H.264 1024x1024, 1 frame. **Image-to-video** — `Cosmos3-Super-Image2Video-4Step`, no config file: ``` Running warmup for Cosmos3OmniMoTPipeline: 1 shape(s) [720x1280x189], 4 steps Denoising: 4 steps, guidance=1.0 POST /v1/videos/generations HTTP/1.1" 200 OK ``` Artifact: 4,890,310 bytes, decoded as H.264 1280x720, 24 fps, 189 frames. The warmup shape confirms the claim that this checkpoint deploys at the default omni shape and needs no config file. **Negative control** (both servers): a request that sets `guidance_scale=6.0` is rejected rather than clamped — ``` HTTP 400: This is a distilled Cosmos3 checkpoint; classifier-free guidance is baked into the weights. guidance_scale must be 1.0 or left unset (got 6.0). ``` **Guardrail fix verified directly** against `cosmos_guardrail` 0.3.0's `Blocklist`: both reworded negative prompts and both positive prompts used by the notebook now report `safe=True`. The trigger words were located by diffing the censored output against the original, not guessed. Re-verified after adopting upstream's wording: `bleeding` and `lifeless` are present in NVIDIA's `blocklist`/`exact_match` word sets (383 and 1430 entries) while `smearing` and `inert` are not. **Visual review**: the text-to-image frame renders the prompt's robot-arm-draping-satin scene coherently. The image-to-video clip follows its `temporal_caption` — coastal dashcam view, rockfall beginning a few seconds in, boulders and dust building until the road is partially blocked — with no flicker or geometry snapping across the 189 frames. ### Local validation - parsed the new notebook as JSON - validated it against the nbformat schema with `nbformat==5.11.1` (the CI gate) - linted it with `ruff==0.16.4 check --select=E9,F63,F7,F82` (the CI gate) - verified unique cell IDs, empty outputs, null execution counts, and that every code cell parses - re-validated both edited JSON assets with `json.tool` - ran `git diff --check` ### Source contract audit The request contract is read from TensorRT-LLM `main` (`tensorrt_llm/_torch/visual_gen/models/cosmos3/sampling.py`): - `load_scheduler` selects `FlowMatchEulerDiscreteScheduler` for distilled checkpoints and `UniPCMultistepScheduler` for base ones; an unknown declaration is a load-time error - `Cosmos3SamplingPolicy.validate_request` rejects any `num_inference_steps` other than `len(t_list)` and any `guidance_scale` other than `1.0` - `generation_default_overrides` supplies both values when the request leaves them unset - `set_flow_shift` is a structural no-op for distilled checkpoints, so `flow_shift` does not apply - both checkpoints declare `fixed_step_sampler_config.t_list = [1.0, 0.9375, 0.8333333333333334, 0.625]` with `stochastic_sampling: true` ## Dependencies and review state - TensorRT-LLM support is already merged: NVIDIA/TensorRT-LLM#16563 (distilled text-to-image) and NVIDIA/TensorRT-LLM#16690 (distilled image-to-video). - No dependency on #310; the two PRs touch different notebooks. If #310 merges first there is no expected conflict. --------- Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
## Summary Add a Cosmos3-Edge section to the TensorRT-LLM audiovisual cookbook, covering exactly what TensorRT-LLM `main` supports for that checkpoint. - add Edge text-to-image, text-to-video, and image-to-video walkthroughs to `run_with_trt_llm.ipynb`, with the Edge endpoint, launch command, and per-case request shape - send Edge's 480p-native contract explicitly: 832x480 with 121 frames, 50 UniPC steps, guidance 5.0 for video, and Edge's native 640x640 with guidance 4.0 for text-to-image. Flow shift (3.0) rides the checkpoint-declared native flow schedule, so requests do not send it - run Edge text-to-image in native image mode against `/v1/images/generations` (see below) - document the Edge launch and request contract in the audiovisual README and the shared Cosmos3 environment setup guide, and note the new section in the root notebook index - realign the shared audiovisual negative prompt with the TensorRT-LLM default (separate commit, details below) ## What TensorRT-LLM head supports for Edge Checked against `main` at `8cfa341332`. Edge support landed in [TensorRT-LLM #16773](NVIDIA/TensorRT-LLM#16773). | Mode | Edge on TensorRT-LLM | Basis | | --- | --- | --- | | Text-to-image | supported | `COSMOS3_EDGE_T2I_PARAMS` (640x640, 50 steps, guidance 4.0), via `/v1/images/generations` with `output_type="image"` | | Text-to-video | supported | `COSMOS3_EDGE_VIDEO_PARAMS` (832x480, 121 frames, 50 steps, guidance 5.0, shift 3.0) | | Image-to-video | supported | same video defaults; reference image as multipart `input_reference` | | Synchronized audio | not supported | Edge has no audio tower | | Video-to-video | not supported | V2V is validated for Nano/Super only | | Action (forward/inverse dynamics, policy) | not supported | the VisualGen pipeline has no action path on `main`, and the Edge checkpoint's action weights are explicitly unsupported | | Transfer controls | not supported | no transfer/control path exists in TensorRT-LLM `main` | | Reasoning | not supported | measured: `POST /v1/chat/completions` returns 404 against a live Edge server, and the served OpenAPI exposes only `/health`, `/metrics`, `/v1/images/*`, `/v1/videos/*`, `/v1/models`, `/version` | Edge is served with no config override — its generation defaults come from the checkpoint. That is also the invocation the upstream `test_cosmos3_edge_i2v_example` integration test exercises. For comparison, Edge coverage across the backends already in this repo: Cosmos Framework, Diffusers, and vLLM-Omni ship image-to-video; SGLang ships text-to-image, text-to-video, and image-to-video. This PR brings TensorRT-LLM to the same three modes. ## Text-to-image runs in native image mode Raised in review. The notebook's existing pattern expresses text-to-image as a one-frame video request. At `8cfa341332` that selects **video** mode, because `extra_params.output_type` defaults to `"video"`, and the pipeline keys its default negative prompt off that: ```python def default_negative_prompt(output_type: str) -> str: return (COSMOS3_DEFAULT_NEGATIVE_PROMPT if output_type == "image" else default_video_negative_prompt()) ``` The example sends no negative prompt of its own, so a still image was being steered by Cosmos3's **video** negative prompt — "Incoherent motion", "visible frame-to-frame discontinuities", "Movement appears as a slideshow" — none of which mean anything for a single frame. The Edge case now posts to `/v1/images/generations` with `output_type="image"` and decodes the base64 PNG, keeping 640x640, 50 steps, and guidance 4.0. Both halves are required: `parse_visual_gen_params` does not set `output_type` for image requests either, so hitting the image endpoint without the flag runs video mode, leaves `output.image` as `None`, and returns 500. For Edge this is the only generation-semantics change — `guidance_interval` is `None` in both `COSMOS3_EDGE_VIDEO_PARAMS` and `COSMOS3_EDGE_T2I_PARAMS`. **`t2i_nano` and `t2i_super` hit the same default and are deliberately left alone here.** They are the `qwen3` family, whose image-mode table also flips `guidance_interval` from `None` to `(400, 1000)`, so switching them changes their output in a way this PR cannot validate (Super needs four GPUs). Worth a follow-up. ## The negative-prompt commit **Update after merging `main`:** #353 landed the byte-identical rewording independently, so this change no longer appears in the diff against `main`. Commit `0407123` remains in the branch history and the explanation below still describes why it was needed at the time. A prerequisite for the Edge examples to run, but not Edge-specific — it fixes the Nano and Super video cases in the same notebook. TensorRT-LLM runs the text guardrail over the **negative** prompt as well as the positive one. The checked-in audiovisual negative prompt had drifted from the reference default in two places — `color bleeding between elements` and `the scene feels lifeless and sterile` — and the Cosmos guardrail blocklist matches `bleeding` and `lifeless`. Every video request carrying this asset therefore failed with HTTP 500 (`Text guardrail blocked prompt`) under the documented default of guardrails enabled. Text-to-image was unaffected only because the payload builder attaches no negative prompt for that mode. [TensorRT-LLM #17523](NVIDIA/TensorRT-LLM#17523) already reworded those exact phrases to `color smearing` and `feels inert` in TensorRT-LLM's own default. The cookbook ships its own copy and sends it explicitly as `negative_prompt`, so the corrected default never applied. This commit adopts the upstream wording; the serialized request body each file produces is now byte-for-byte identical to `COSMOS3_VIDEO_NEGATIVE_PROMPT` (14674 bytes, key order included). `cookbooks/cosmos3/generator/transfer/assets/negative_prompt.json` carries the same drift and is left alone — #310 already covers it. ## Validation Real Edge server, real generations, guardrails enabled throughout. **Environment.** 1x NVIDIA B200, x86_64. TensorRT-LLM built from source at `8cfa341332` (reports `1.3.0rc25+8cfa341332`). `cosmos_guardrail==0.3.0` with the pinned `nvidia/Cosmos-1.0-Guardrail` revision `cf03c0395fac8c4de386c0bdab12cc4fc8d66362`. `ffmpeg` 7.0.2 on `PATH`, so video responses take the MP4 encoder rather than the AVI fallback. The checkpoint is a local copy of `nvidia/Cosmos3-Edge`, served by path. **Server.** `trtllm-serve <Cosmos3-Edge> --port 8000`, no `--visual_gen_args`, exactly as the new section documents. **Execution.** The notebook's Edge cells were run verbatim through `jupyter nbconvert --to notebook --execute` from a checkout of this branch, so `find_repo_root`, the repo-relative asset paths, `create_payload`, `check_trtllm_server`, `run_trtllm_payload`, and `view_run` all ran as a reader hits them. `nbconvert` exited 0 with every cell executed. **Guardrail preflight.** All five prompt/negative assets the Edge cases send pass `CosmosSafetyChecker.check_text_safety`. **Endpoints actually served**, from the server log: ``` 1 "POST /v1/images/generations HTTP/1.1" 200 OK <- t2i_edge 2 "POST /v1/videos/generations HTTP/1.1" 200 OK <- t2v_edge, i2v_edge ``` **Generation parameters the server resolved**, from the server log (warmup line omitted): ``` Cosmos3 generation dims: 640x640 (WxH), num_frames=1, num_inference_steps=50, guidance_scale=4.00 Cosmos3 generation dims: 832x480 (WxH), num_frames=121, num_inference_steps=50, guidance_scale=5.00 Cosmos3 generation dims: 832x480 (WxH), num_frames=121, num_inference_steps=50, guidance_scale=5.00 ``` **Results**, decoded from the returned payloads: | Case | Decoded shape | FPS | Size | | --- | --- | --- | --- | | `t2i_edge` | `(640, 640, 3)` PNG | n/a | 514 KB | | `t2v_edge` | `(121, 480, 832, 3)` | 24 | 510 KB | | `i2v_edge` | `(121, 480, 832, 3)` | 24 | 1952 KB | Every case matches the documented contract. The run logged zero model-card envelope advisories; the one previously emitted came from the one-frame video text-to-image request and disappears in native image mode. Outputs were inspected visually as well as by shape. As a cross-check the same three cases were also run through cosmos-framework (`3845f4c`) at matched settings — same prompts, negative prompts, seed, sampler, steps and guidance. Shapes agree on all three, and after the image-mode fix the text-to-image results agree in composition as well, which they did not before: cosmos-framework already sends an empty negative prompt for text-to-image, so it was the TensorRT-LLM video-mode default that diverged. --------- Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
ConstBob
left a comment
There was a problem hiding this comment.
GB200 Action FD visual quality is a merge blocker. Maciej’s observation reproduces; H100/H200 does not.
Setup: GB200 (aarch64 Grace, driver 580.173.02), 1× GB200 (CUDA_VISIBLE_DEVICES=0), Cosmos3-Nano, POST /v1/videos/sync, use_guardrails=false (cookbook default still 500s here on Guardrail HF blobs). Two TRT-LLM stacks: main HEAD Python overlay, and the public NGC image nvcr.io/nvidia/tensorrt-llm/release:1.3.0rc26.dev202609060001. Both produced byte-identical safetensors.
What fails: frames 0–35 match H100/H200. From t≈40 the upper half smears and never recovers.
H100/H200 (top) vs GB200 (bottom), same input.
t=50
t=60
Full clip
fd_gb200_av.mp4
Numbers (Laplacian-variance sharpness; t=0 is essentially identical across platforms — mean 97.65 vs 97.66, sharpness 182.7 vs 182.6 — so this is rollout divergence, not a bad start frame):
H100/H200 GB200
sharpness, first 5 172.3 181.1
sharpness, last 5 144.0 114.5
retention ratio 0.836 0.632
On GB200, sharpness falls between t=40 (135.6) and t=44 (103.8), then flatlines at ~104.
This does not look like a cookbook diff. On GB200, main HEAD and rc26 were byte-identical (deec0969…); on H100/H200, main HEAD matched the earlier run byte-for-byte (31206e4d…). Same code, same inputs, only the platform differs — points at a Blackwell/SM100 kernel or precision path in TRT-LLM.
Please don’t merge on the previous Action FD LGTM. Happy to re-approve once either GB200 FD quality is fixed or explained as acceptable with a cookbook caveat that Maciej/Igor sign off on.
Summary
Add Cosmos3 Action and Transfer cookbooks for TensorRT-LLM's VisualGen serving API.
Action
image_referenceandvideo_referencerequests, safetensors decoding, and MP4 previews.Transfer
extra_paramsand synchronous MP4 responses from/v1/videos/sync.Setup and documentation
NLTK_DATA, with path security enabled.Testing
Executed all code cells in the two Action notebooks and the Transfer notebook on one H200 using Cosmos3-Nano and a native build of TensorRT-LLM
bca6761. The run used the documented NLTK setup and server command, withcosmos-guardrail==0.3.0anduse_guardrails=True.All seven MP4s were decoded frame by frame. Both Action tensor payloads passed shape, dtype, and finite-value checks. All 35 tracked notebooks passed JSON/schema validation and the CI lint selection; the three added notebooks have cleared outputs and pass strict schema validation.
Guardrail coverage follows the package's default configuration: Blocklist and Qwen3Guard text checks plus RetinaFace face blurring; video-content classification is not enabled in 0.3.0.
The GPU results above cover Nano Action and Transfer. See the validation record for the exact environment, execution records, and artifact metadata.