Skip to content

[TRTLLM-13143][feat] BREAKING: VisualGen serving API: response_format support path and modify async job status - #17490

Merged
luyiyun1021 merged 12 commits into
NVIDIA:mainfrom
luyiyun1021:feat/vg-video-sync-response-format-path
Aug 25, 2026
Merged

[TRTLLM-13143][feat] BREAKING: VisualGen serving API: response_format support path and modify async job status#17490
luyiyun1021 merged 12 commits into
NVIDIA:mainfrom
luyiyun1021:feat/vg-video-sync-response-format-path

Conversation

@luyiyun1021

@luyiyun1021 luyiyun1021 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Description

Improves the VisualGen OpenAI-compatible serving API in two areas — output transports and async job observability.

Transports: add response_format="path" to the image/video endpoints — return the server-side on-disk output path so a co-located client (shared filesystem) opens the file directly, with no url second-fetch or base64 bloat. Precedent is self-hosted only (Veo-Vertex gcsUri, ComfyUI filename, SGLang file-store); no SaaS API has it, since a filesystem path only means something when caller and engine share a filesystem.

Observability: the async /v1/videos job exposes a generating → postprocessing → completed lifecycle so a client can time generation before postprocessing, and both sync + async responses emit a Server-Timing header with engine (generation/denoise) and end-to-end (total) metrics.

Details below.

  • Image — additive: path added; url / b64_json unchanged.
  • Video — breaking response_format: {url, b64_json}{file, path} (drop b64_json; file replaces the misnamed url that returned bytes). A response_format validator rejects the removed url/b64_json values with an actionable 422 naming the replacement (not the generic Input should be 'file' or 'path'); callers on the old default are unaffected (old url default and new file default both return raw bytes). Plus a new canonical sync route /v1/videos/sync; the pre-existing /v1/videos/generations is retained as a deprecated alias to the same sync handler (upstream already depends on it), so the route change itself is non-breaking.
    • Why /sync: OpenAI exposes a generations endpoint only for images (/v1/images/generations, synchronous); its video API /v1/videos is async by default and has no /v1/videos/generations. The old name borrowed generations from the image endpoint for a route with no OpenAI counterpart; /v1/videos/sync names the synchronous behavior explicitly, paired with the async /v1/videos. /v1/videos/generations stays registered as a deprecated alias so existing callers keep working.
  • Status endpoint GET /v1/videos/{id} (and list) now returns status only — the internal output_path/output_paths are no longer leaked on the wire (they stay on the job for /content resolution + delete). The path is delivered via /content when response_format="path". Closes a pre-existing path leak.
  • Async job status lifecycle — the async /v1/videos job now advances queued → generating → postprocessing → completed (the previously-unused in_progress is split into generating = model inference and postprocessing = encode the media and/or write the output file). The generating → postprocessing transition marks the end of inference, so a co-located benchmarking client polling GET /v1/videos/{id} can time generation on its side (independent of postprocessing); the file stays downloadable via /content once completed (/content returns not ready / 400 while generating/postprocessing). To keep postprocessing observable, the async encoder save is offloaded to a thread (env-gated TRTLLM_VIDEO_ASYNC_ENCODE, matching the sync route) so the event loop stays responsive during the encode. The sync route is unchanged.
  • Server-Timing headers (sync + async aligned) — the video sync route and the async GET /v1/videos/{id}/content now return a Server-Timing header with generation, denoise, and a new total (ms), so a co-located dev client reads engine + end-to-end timings straight off the response instead of polling. total is the full server time (sync: request arrival → response; async: POST arrival → job completed), stamped with perf_counter at handler entry. For async the timings ride on the job as internal exclude=True fields bridging POST → background → /content (status endpoint stays status-only). generation/denoise are the engine metrics (also on the in-process output.metrics); total is a serve-side measurement, so it is not added to VisualGenMetrics. (Image generation keeps generation/denoise; total is video-only for now.)
  • VideoJob.output_paths stays on the job (internal only) — excluded from every wire response, consumed by delete for batch cleanup and kept as the manifest the n>1 multi-output follow-up builds on. The single-video wire is output_path; output_paths never appears on the wire. (Video n>1 is unreachable over HTTP today — no n field — so it stays length-1 for now; multi-output is the data[]-of-objects follow-up below, not a flat paths list.)
  • response_format="path" opt-out gatepath returns absolute server-side file paths (always under the media-storage directory TRTLLM_MEDIA_STORAGE_PATH, so the disclosure is bounded) and trtllm-serve has no auth, so it is enabled by default but can be disabled server-side with TRTLLM_DISALLOW_LOCAL_MEDIA_PATH=1 (→ 400 on the image and video endpoints). Path (co-located) clients also receive the same Server-Timing metrics as file clients.

Usage (old → new)

Image · POST /v1/images/generations (endpoint unchanged, path added)

# old — url: returns a URL string, client does a 2nd GET to fetch bytes
curl -sX POST localhost:8000/v1/images/generations -H content-type:application/json \
  -d '{"prompt":"a cat","response_format":"url"}'
#   -> {"data":[{"url":"http://localhost:8000/v1/images/<id>/content?i=0"}]}

# new — path: returns the on-disk path, co-located client reads it directly
curl -sX POST localhost:8000/v1/images/generations -H content-type:application/json \
  -d '{"prompt":"a cat","response_format":"path"}'
#   -> {"data":[{"path":"/tmp/trtllm_generated/image_<hex>_0.png"}]}
import requests
d = requests.post("http://localhost:8000/v1/images/generations",
                  json={"prompt": "a cat", "response_format": "path"}).json()
img_bytes = open(d["data"][0]["path"], "rb").read()          # no 2nd request

Video sync · new canonical route /v1/videos/sync (/v1/videos/generations kept as deprecated alias)

# old
curl -sX POST localhost:8000/v1/videos/generations -H content-type:application/json \
  -d '{"prompt":"...","size":"512x512","seconds":2,"fps":24,"response_format":"url"}'
#   -> raw mp4 bytes           (response_format="url" misleadingly returned bytes)

# new — file (default): raw mp4 bytes
curl -sX POST localhost:8000/v1/videos/sync -H content-type:application/json \
  -d '{"prompt":"...","size":"512x512","seconds":2,"fps":24}'
#   -> raw mp4 bytes

# new — path: on-disk path JSON
curl -sX POST localhost:8000/v1/videos/sync -H content-type:application/json \
  -d '{"prompt":"...","size":"512x512","seconds":2,"fps":24,"response_format":"path"}'
#   -> {"id":"video_<hex>","output_path":"/tmp/trtllm_generated/video_<hex>_0.mp4"}

# /v1/videos/generations still works as a deprecated alias (same handler, same new response_format)
# removed for video: response_format="b64_json"

Video async · POST /v1/videos (new generating/postprocessing status; new path)

import requests, time
B = "http://localhost:8000"
job = requests.post(f"{B}/v1/videos",
                    json={"prompt": "...", "size": "512x512", "seconds": 2, "fps": 24,
                          "response_format": "path"}).json()          # stored on the job

# new: status advances queued -> generating -> postprocessing -> completed.
# generating -> postprocessing marks the end of model inference, so a
# co-located benchmarking client can time generation itself.
t0, gen_time = time.time(), None
while True:
    status = requests.get(f"{B}/v1/videos/{job['id']}").json()["status"]
    if gen_time is None and status in ("postprocessing", "completed"):
        gen_time = time.time() - t0      # pure generation time (excludes postprocessing)
    if status in ("completed", "failed"):
        break
    time.sleep(0.5)

r = requests.get(f"{B}/v1/videos/{job['id']}/content").json()
#   old  /content -> mp4 bytes (file) or b64_json
#   new  response_format="path" -> {"id":..., "output_path":"/tmp/trtllm_generated/video_<hex>_0.mp4"}
path = r["output_path"]

The in-process VisualGen Python API is unchanged — it already returns the output object and you call output.save(path) yourself. response_format is the HTTP-serve equivalent for remote / co-located clients.

Tests

161 unit tests (mock-based, no GPU): tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py (image path incl. n>1 data[] fan-out; video file/path across sync-tensor, sync-encoder, async /content; async job status lifecycle generating → postprocessing → completed incl. an httpx-AsyncClient test that observes postprocessing while the offloaded encode runs, plus /content not-ready gating; Server-Timing generation/denoise/total on sync + async /content; status/list endpoints status-only — no path leak) and test_visual_gen_utils.py. The async-completion tests run over an httpx AsyncClient on a live loop because starlette's TestClient does not progress detached background tasks between requests.

Follow-up (separate PR)

  • media_storage TTL GC to bound disk for path/url artifacts, which persist today with no per-request cleanup.
  • Video n>1 multi-output (differs from image — no url): keep response_format ∈ {file, path}; the POST returns {id, data: [VideoObject{path}]} (a path manifest, no url/b64). The client fetches each item itself via GET /v1/videos/{id}/content?i=<i> — extend /content to accept ?i= (default 0; bare /content stays "first item"). Unlike image, video does not return a ready url field; the client builds /content?i= from the id. VideoJob.output_paths is the manifest ?i= indexes into.

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-compatible or api-breaking. For api-breaking, include BREAKING in 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.

GitHub Bot Help

To see a list of available CI bot commands, please comment /bot help.

@luyiyun1021

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The visual generation API renames the synchronous video route to /v1/videos/sync. Image and video responses now support filesystem paths, with video responses using file downloads or path envelopes. Examples, benchmarks, fixtures, and tests were updated.

Changes

Visual generation API

Layer / File(s) Summary
Response format contracts
tensorrt_llm/serve/openai_protocol.py
Image requests and objects support filesystem paths. Video requests and jobs use file or path response formats, and removed formats return validation errors.
Image path responses
tensorrt_llm/serve/openai_server.py, tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
Image generation returns saved paths for response_format="path". Tests verify PNG and tensor outputs.
Video route and path responses
tensorrt_llm/serve/openai_server.py, tensorrt_llm/serve/openai_video_routes.py
The synchronous route is available at /v1/videos/sync, with the former route retained as a deprecated alias. Path responses return an ID and output path. File responses remain downloads, while metadata omits internal output paths.
Integration and validation
docs/source/models/visual-generation.md, examples/visual_gen/serve/*, tensorrt_llm/serve/scripts/benchmark_visual_gen.py, tests/unittest/_torch/visual_gen/*
Documentation, examples, benchmark routing, fixtures, and tests use the updated route and response formats.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 0e8ad

The PR adds path-based video responses and route compatibility; the remaining concern is limited to strengthening exact response-envelope assertions in tests, with no actionable merge-blocking risk.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the feature, breaking API change, and async job status update.
Description check ✅ Passed The description explains the changes, rationale, API impact, testing, follow-up work, and checklist status in detail.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tensorrt_llm/serve/openai_protocol.py (1)

1576-1576: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the new transport fields in the generated schema.

Add Field(description=...) to the changed response_format fields and to ImageObject.path. This keeps the OpenAPI schema clear for clients that discover the new transport through the API.

Proposed change
-    response_format: Literal["url", "b64_json", "path"] = "url"
+    response_format: Literal["url", "b64_json", "path"] = Field(
+        default="url",
+        description="Response transport: URL, inline base64 JSON, or server-side path.",
+    )
...
-    path: Optional[str] = None
+    path: Optional[str] = Field(
+        default=None,
+        description="Server-side path to the generated image for co-located clients.",
+    )
...
-    response_format: Literal["file", "path"] = "file"
+    response_format: Literal["file", "path"] = Field(
+        default="file",
+        description="Response transport: file download or server-side path JSON.",
+    )

As per coding guidelines, “For Pydantic fields, use Field(description=...).”

Also applies to: 1645-1645, 1676-1676

🤖 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 `@tensorrt_llm/serve/openai_protocol.py` at line 1576, Add
Field(description=...) metadata to the response_format fields at the referenced
locations and to ImageObject.path, preserving their existing types and defaults.
Use concise descriptions that document each supported transport value and the
path field’s purpose so the generated OpenAPI schema clearly exposes the new
transport options.

Source: Coding guidelines

tensorrt_llm/serve/openai_video_routes.py (1)

67-80: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a precise path-compatible type for paths.

The helper receives both list[Path] and list[str]. Annotate it as Sequence[str | Path] and import Sequence from collections.abc.

🤖 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 `@tensorrt_llm/serve/openai_video_routes.py` around lines 67 - 80, Update
_path_json_video_response to annotate paths as Sequence[str | Path], and import
Sequence from collections.abc. Preserve the existing string conversion and
response construction.

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.

Inline comments:
In `@tests/unittest/_torch/visual_gen/test_trtllm_serve_e2e.py`:
- Line 250: Update the request URL used by both synchronous tests, test_t2v_sync
and test_ti2v_sync, to call /v1/videos/sync instead of /v1/videos/generations.
Keep the existing request payloads and assertions unchanged.

---

Nitpick comments:
In `@tensorrt_llm/serve/openai_protocol.py`:
- Line 1576: Add Field(description=...) metadata to the response_format fields
at the referenced locations and to ImageObject.path, preserving their existing
types and defaults. Use concise descriptions that document each supported
transport value and the path field’s purpose so the generated OpenAPI schema
clearly exposes the new transport options.

In `@tensorrt_llm/serve/openai_video_routes.py`:
- Around line 67-80: Update _path_json_video_response to annotate paths as
Sequence[str | Path], and import Sequence from collections.abc. Preserve the
existing string conversion and response construction.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 272622ef-9d6c-4399-981d-e72f0096369b

📥 Commits

Reviewing files that changed from the base of the PR and between fd2edba and 27355b5.

📒 Files selected for processing (10)
  • docs/source/models/visual-generation.md
  • examples/visual_gen/serve/README.md
  • examples/visual_gen/serve/sync_video_gen.py
  • tensorrt_llm/serve/openai_protocol.py
  • tensorrt_llm/serve/openai_server.py
  • tensorrt_llm/serve/openai_video_routes.py
  • tensorrt_llm/serve/scripts/benchmark_visual_gen.py
  • tests/unittest/_torch/visual_gen/test_trtllm_serve_e2e.py
  • tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
  • tests/unittest/_torch/visual_gen/test_visual_gen_utils.py

Comment thread tests/unittest/_torch/visual_gen/test_trtllm_serve_e2e.py
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65216 [ run ] triggered by Bot. Commit: 27355b5 Link to invocation

@luyiyun1021
luyiyun1021 marked this pull request as draft August 11, 2026 08:00
@luyiyun1021
luyiyun1021 force-pushed the feat/vg-video-sync-response-format-path branch 4 times, most recently from 8008f24 to d88c099 Compare August 11, 2026 10:14
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65216 [ run ] completed with state FAILURE. Commit: 27355b5
/LLM/main/L0_MergeRequest_PR pipeline #53001 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@luyiyun1021
luyiyun1021 force-pushed the feat/vg-video-sync-response-format-path branch 3 times, most recently from 83f8ef1 to 2ed0835 Compare August 12, 2026 02:58
@luyiyun1021
luyiyun1021 marked this pull request as ready for review August 12, 2026 03:14
@luyiyun1021 luyiyun1021 changed the title [TRTLLM-13143][feat] BREAKING: VisualGen response_format=path (image+video); rename video sync route to /v1/videos/sync [TRTLLM-13143][feat]VisualGen response_format=path (image+video); rename video sync route to /v1/videos/sync Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py (1)

1707-1752: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject removed video response formats.

Add parameterized requests with response_format="url" and response_format="b64_json". Assert HTTP 422. The current tests verify accepted file and path values, but they do not enforce removal of the old values.

The PR objective restricts video response_format to file and path.

Also applies to: 1802-1837

🤖 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/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py` around lines
1707 - 1752, Add parameterized tests alongside
test_sync_tensor_file_returns_file_with_correct_suffix and
test_sync_tensor_path_returns_readable_output_path that submit response_format
values "url" and "b64_json" for a supported tensor format, then assert the
endpoint returns HTTP 422. Ensure the tests explicitly enforce that only the
existing "file" and "path" response formats are accepted.
🤖 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.

Inline comments:
In `@tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py`:
- Around line 801-809: Add a test near TestVideoGenerationSync that posts to the
removed /v1/videos/generations route and asserts a 404 response, ensuring the
old synchronous endpoint remains unavailable after the rename.
- Around line 556-573: Update test_image_generation_pt_path to assert that
obj["b64_json"] is None alongside the existing path and URL assertions, ensuring
tensor path responses leave both transport fields unset.

---

Outside diff comments:
In `@tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py`:
- Around line 1707-1752: Add parameterized tests alongside
test_sync_tensor_file_returns_file_with_correct_suffix and
test_sync_tensor_path_returns_readable_output_path that submit response_format
values "url" and "b64_json" for a supported tensor format, then assert the
endpoint returns HTTP 422. Ensure the tests explicitly enforce that only the
existing "file" and "path" response formats are accepted.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 82eb42fb-4a54-4f92-b4f8-bf68b1c07baa

📥 Commits

Reviewing files that changed from the base of the PR and between 27355b5 and 2ed0835.

📒 Files selected for processing (3)
  • tensorrt_llm/serve/openai_protocol.py
  • tensorrt_llm/serve/openai_video_routes.py
  • tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tensorrt_llm/serve/openai_protocol.py
  • tensorrt_llm/serve/openai_video_routes.py

Comment thread tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
Comment thread tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
@luyiyun1021
luyiyun1021 force-pushed the feat/vg-video-sync-response-format-path branch from 2ed0835 to a113cc8 Compare August 12, 2026 03:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@tests/unittest/_torch/visual_gen/test_trtllm_serve_e2e.py`:
- Around line 251-252: Add a finite ten-minute timeout to both synchronous video
POST requests in
tests/unittest/_torch/visual_gen/test_trtllm_serve_e2e.py:251-252 and
tests/unittest/_torch/visual_gen/test_trtllm_serve_e2e.py:372-373, covering the
text-to-video and image-to-video request flows respectively. Use the same
timeout value for both requests.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a9127fe7-15d5-43e1-aab6-6c9a90388d7c

📥 Commits

Reviewing files that changed from the base of the PR and between 2ed0835 and a113cc8.

📒 Files selected for processing (2)
  • tests/unittest/_torch/visual_gen/test_trtllm_serve_e2e.py
  • tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py

Comment thread tests/unittest/_torch/visual_gen/test_trtllm_serve_e2e.py
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68670 [ run ] completed with state FAILURE. Commit: f795226
/LLM/main/L0_MergeRequest_PR pipeline #56073 completed with status: 'UNSTABLE'

CI Report

⚠️ Multi-GPU Label Required:
Multi-GPU tests require the ci: full pre-merge approved label on this PR. Ask a member of NVIDIA/trt-llm-ci-approvers to add the label, then re-trigger CI with the same bot command (no rebase needed).

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@luyiyun1021

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68732 [ run ] triggered by Bot. Commit: f795226 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68732 [ run ] completed with state FAILURE. Commit: f795226
/LLM/main/L0_MergeRequest_PR pipeline #56129 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@luyiyun1021

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68818 [ run ] triggered by Bot. Commit: f795226 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68818 [ run ] completed with state SUCCESS. Commit: f795226
/LLM/main/L0_MergeRequest_PR pipeline #56212 completed with status: 'SUCCESS'

CI Report

Link to invocation

Drop rationale clauses (measurement use-case, security reasoning, disclosure justification) from the async lifecycle, response_format=path, and release-note prose, keeping the state machine, endpoints, and flag behavior as plain description.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
…t post

Move the two-stage `mark_post_start` from the end of stage 1 to the decode boundary, so `denoise` spans stage 1 plus the stage-2 upsample / LoRA bind / refinement loop and `post_denoise` is decode only, matching single-stage models. The Server-Timing `denoise` this PR emits was understated for LTX-2 two-stage (stage 1 only). Fine-grained `stage2_denoise_time()` / `decode_time()` logs read independent event pairs and are unaffected.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
@luyiyun1021

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68870 [ run ] triggered by Bot. Commit: 8975e75 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68870 [ run ] completed with state FAILURE. Commit: 8975e75
/LLM/main/L0_MergeRequest_PR pipeline #56256 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@luyiyun1021

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68974 [ run ] triggered by Bot. Commit: 8975e75 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68974 [ run ] completed with state FAILURE. Commit: 8975e75
/LLM/main/L0_MergeRequest_PR pipeline #56351 completed with status: 'UNSTABLE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@luyiyun1021

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #69125 [ run ] triggered by Bot. Commit: 8975e75 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #69125 [ run ] completed with state SUCCESS. Commit: 8975e75
/LLM/main/L0_MergeRequest_PR pipeline #56494 completed with status: 'SUCCESS'

CI Report

Link to invocation

@luyiyun1021
luyiyun1021 merged commit e8eb690 into NVIDIA:main Aug 25, 2026
7 checks passed
karljang added a commit to karljang/TensorRT-LLM that referenced this pull request Aug 25, 2026
The sync video route attaches Server-Timing to every tensor response.
Its `path` sub-path is asserted by
test_sync_tensor_path_returns_readable_output_path, but the `file`
sub-path -- the FileResponse a measurement client actually downloads --
is only checked for its filename suffix and payload round-trip, so a
regression that dropped the headers there would go unseen.

Assert the headers on the `file` sub-path as a sibling test in
TestVideoTensorResponse, reusing its _post_sync helper and the existing
_assert_visual_gen_server_timing.

This PR originally also changed openai_video_routes.py to attach those
headers, which was the actual bug at the time it was opened. NVIDIA#17490
(BREAKING: response_format support for `path`) has since restructured
that route and attaches them already, so only the missing coverage
remains.

Signed-off-by: Kanghwan Jang <861393+karljang@users.noreply.github.com>
ishovkun added a commit to ishovkun/TensorRT-LLM that referenced this pull request Aug 26, 2026
Two conflicts, both in the serving layer against the deliberate
response_format break on main (NVIDIA#17490: video API drops b64_json for
"file"/"path" plus Server-Timing headers and a "postprocessing" job
status):

- openai_video_routes.py: the tensor-payload sync branch adopts the new
  conventions (timing headers, path envelope, FileResponse with
  headers); the dead b64 helper goes with the rest of the b64 paths.
  The background task keeps resolving through request_format (the
  route's tensor-only resolution) rather than raw request.format, and
  gains upstream's postprocessing status transition.
- test_trtllm_serve_endpoints.py: keeps the thread-settling TestClient
  (pytest-threadleak guard) wired into upstream's reworked
  _create_server.

Signed-off-by: Igor Shovkun <igshov@gmail.com>
luyiyun1021 added a commit to luyiyun1021/TensorRT-LLM that referenced this pull request Aug 31, 2026
`/v1/images/generations` and `/v1/images/edits` emitted only the engine's `generation` and `denoise` metrics, so a client could not tell how much server time was spent outside the engine — request parsing, image encoding, response serialization. Both video routes have reported `total` since NVIDIA#17490.

Start the clock at the top of each handler, before request parsing, so the metric spans the same window the video routes measure. The existing `latency` variable is not reused because it starts after parsing and would under-report.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
luyiyun1021 added a commit to luyiyun1021/TensorRT-LLM that referenced this pull request Sep 1, 2026
The image edit route already writes each output image to media storage
before returning a fetchable URL, but it could not return that path:
`ImageEditRequest.response_format` only accepted `url` / `b64_json`,
while `/v1/images/generations` and both video routes have supported
`path` since NVIDIA#17490.

Reuse the existing `_image_object` helper so the edit route shares one
transport dispatch with the generation route, and gate `path` behind the
same `TRTLLM_DISALLOW_LOCAL_MEDIA_PATH` check the other routes use.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
luyiyun1021 added a commit to luyiyun1021/TensorRT-LLM that referenced this pull request Sep 1, 2026
`/v1/images/generations` and `/v1/images/edits` emitted only the engine's `generation` and `denoise` metrics, so a client could not tell how much server time was spent outside the engine — request parsing, image encoding, response serialization. Both video routes have reported `total` since NVIDIA#17490.

Start the clock at the top of each handler, before request parsing, so the metric spans the same window the video routes measure. The existing `latency` variable is not reused because it starts after parsing and would under-report.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
luyiyun1021 added a commit to luyiyun1021/TensorRT-LLM that referenced this pull request Sep 1, 2026
The image edit route already writes each output image to media storage
before returning a fetchable URL, but it could not return that path:
`ImageEditRequest.response_format` only accepted `url` / `b64_json`,
while `/v1/images/generations` and both video routes have supported
`path` since NVIDIA#17490.

Reuse the existing `_image_object` helper so the edit route shares one
transport dispatch with the generation route, and gate `path` behind the
same `TRTLLM_DISALLOW_LOCAL_MEDIA_PATH` check the other routes use.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
luyiyun1021 added a commit to luyiyun1021/TensorRT-LLM that referenced this pull request Sep 1, 2026
`/v1/images/generations` and `/v1/images/edits` emitted only the engine's `generation` and `denoise` metrics, so a client could not tell how much server time was spent outside the engine — request parsing, image encoding, response serialization. Both video routes have reported `total` since NVIDIA#17490.

Start the clock at the top of each handler, before request parsing, so the metric spans the same window the video routes measure. The existing `latency` variable is not reused because it starts after parsing and would under-report.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
luyiyun1021 added a commit to luyiyun1021/TensorRT-LLM that referenced this pull request Sep 2, 2026
The image edit route already writes each output image to media storage
before returning a fetchable URL, but it could not return that path:
`ImageEditRequest.response_format` only accepted `url` / `b64_json`,
while `/v1/images/generations` and both video routes have supported
`path` since NVIDIA#17490.

Reuse the existing `_image_object` helper so the edit route shares one
transport dispatch with the generation route, and gate `path` behind the
same `TRTLLM_DISALLOW_LOCAL_MEDIA_PATH` check the other routes use.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
luyiyun1021 added a commit to luyiyun1021/TensorRT-LLM that referenced this pull request Sep 2, 2026
`/v1/images/generations` and `/v1/images/edits` emitted only the engine's `generation` and `denoise` metrics, so a client could not tell how much server time was spent outside the engine — request parsing, image encoding, response serialization. Both video routes have reported `total` since NVIDIA#17490.

Start the clock at the top of each handler, before request parsing, so the metric spans the same window the video routes measure. The existing `latency` variable is not reused because it starts after parsing and would under-report.

Signed-off-by: Yiyun Lu <55233584+luyiyun1021@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-compatible Accepted LLM API contract change that is backwards-compatible ci: full pre-merge approved VisualGen

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants