Repository navigation
[TRTLLM-17264][refactor] Move the VisualGen handlers into serve/api/visual_gen - #21552
Draft
JunyiXu-nv wants to merge 24 commits into
Draft
JunyiXu-nv wants to merge 24 commits into
JunyiXu-nv wants to merge 24 commits into
Conversation
…lope Pin the exact 422 body at the route-level entry point (FastAPI RequestValidationError on /v1/images/generations, which declares its request model) and at the handler-level entry points (pydantic ValidationError raised while building the request model on /v1/videos/sync, /v1/videos and /v1/images/edits, JSON and multipart). All entry points must render byte-identical bodies; these tests pin the full body so a later refactor of the rendering code has exact coverage. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…derers OpenAIServer._create_visual_gen_validation_error_response (for FastAPI's RequestValidationError) and _VideoRoutesMixin._render_pydantic_validation_error (for pydantic's ValidationError) were statement-for-statement identical. Replace both with one module-level function, render_visual_gen_validation_error in tensorrt_llm/serve/_visual_gen_errors.py, that accepts either exception and the server's error-response factory, and point all six call sites at it. The factory argument keeps the error envelope and the context-length code rule defined in one place and avoids an import cycle with openai_server. This also removes the only call OpenAIServer makes to a method defined by the video-routes mixin (openai_image_edit called the mixin's renderer). No behavior change: both entry points return the same status and bytes as before; the characterization tests added in the previous commit pass unchanged on both sides of this refactor. The new module joins the mypy file list. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…apshots and a CPU test seam for trtllm-serve Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
… baselines at the merge base The route reference is generated from the live apps; the object.__new__ baseline and the gRPC import allowance record what exists on main today and only shrink. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…n the snapshot matrix An attached frontend of a multi-frontend server registers ten launcher forwarding routes before the local table; seven share a method and path with local handlers and three use a path parameter that matches every batch id, so registration order decides which handler serves them. The new configuration records all of it, a live invariant pins the forwarding-before-local order independently of the reference, and the route-class failure message now says why the msgpack route class matters. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
- AGENTS.md: the CPU test command sets LLM_MODELS_ROOT, which the runner requires, and the stage-mapping note says the mapper matches list-entry text, so a file listed through its directory maps by the directory. - check_contracts matches each from-import as <module>.<name>, so 'from pkg import sub' and 'from .. import sub' count as imports of the submodule; new test for both forms and for the allowance entry. - The VisualGen /v1/models test asserts the 200 status. - The AGENTS.md command check also recognizes commands that start with LLM_MODELS_ROOT=. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…on the current main The disaggregated frontend now registers its routes with KvHintsRoute (NVIDIA#20269), which strips kv_hints from request bodies unless the server trusts its ingress. Regenerate the route reference: the six disaggregated configurations record KvHintsRoute where they recorded APIRoute; their route sets and order are unchanged. The route-class invariant, which a regenerated reference cannot hide, now requires KvHintsRoute on every API route of the disaggregated frontend and APIRoute on the coordinator app. Dropping the KV-hint policy from the frontend fails it even after a regeneration, and both apps still reject the aggregated server's msgpack route class. The object.__new__ baseline records the sites on main at the merge base: test_kv_hints.py builds one server that way (NVIDIA#20269), and test_harmony_parsing.py no longer builds any (NVIDIA#21176). The harmony parsing tests are now registered as a whole file (NVIDIA#21411), so the node-id entry that the CPU-selection test used as its example is gone. The node-id check now runs select_entries on a one-entry list of its own, so it no longer depends on which node-id entries l0_cpu.yml holds. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…ail on silent regressions The route snapshot now requires every configuration other than the three invalid ones to build, so a configuration that starts failing at construction cannot pass through a regenerated reference. The object.__new__ ratchet resolves 'from ... import <server class> as <name>' aliases and records each baseline site as its enclosing function or class plus the server class, so swapping one site for another in the same file no longer passes. The baseline keeps the same 52 sites in the same 26 files. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…lm/serve/_base/msgspec_route.py Generated move: _msgpack_decoder, _MsgspecRequest and _MsgspecRoute leave tensorrt_llm/serve/openai_server.py byte for byte; the module imports _MsgspecRoute back for its app router and keeps no re-export (the three names are private). The two disaggregated test importers now import the new module. OpenAIServer.health, .version and .get_model are removed here and replaced by the system router added in the following commits. tensorrt_llm/serve/_base/msgspec_route.py joins legacy-files.txt (its code comes from a legacy-formatted file), and the generated lint configs are regenerated with scripts/legacy_utils.py gen-configs. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…ve the system endpoints through it New structure: tensorrt_llm/serve/_base/ (shared serving infrastructure) and tensorrt_llm/serve/api/ (endpoint packages, one router plus one serving class each; the package __init__ imports nothing so routers load lazily, by role). serve/_base/routing.py provides make_router(), which always uses the msgpack-decoding route class, and attach_routers(), which imports and attaches only the routers whose RouterSpec matches the server role. The first endpoint package, serve/api/ops/system/, serves /health, /version and /v1/models for every role. OpenAIServer builds a SystemServing with the injected _health_probe (today's probe body, SIGINT side effect included) and attaches the routers before the role dispatch; the 12 add_api_route lines for the three paths leave the four role tables. Same routes, methods, route classes, bodies and conflict-relevant order: the recorded route reference is unchanged. The layering tests gain the new packages' contracts, the route-snapshot failure message points new endpoints at the router pattern, and the serve agent docs describe where a new endpoint goes. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…w serve packages tensorrt_llm/serve/_base/ and tensorrt_llm/serve/api/ops/ join the multi-GPU trigger list: the msgpack route class decodes the disaggregated frontend's worker requests, and /health is the disaggregated readiness probe, so changes under these directories keep running the multi-GPU stages that exercise that path. The three new modules join the strict mypy file set, and the type-check pre-commit hook now also triggers on changes under tensorrt_llm/serve/ and tensorrt_llm/commands/serve_cli/, so edits to typed serving modules get local type checking; the hook still checks only the declared file set. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
… tests that build routes by hand Two multi-frontend tests build an OpenAIServer without its constructor and call register_routes() themselves. Since /health, /version and /v1/models are attached through the system router by the constructor, those tests no longer saw the three routes: one asserted that /version stays local on an attached frontend (404), the other reported the three per-frontend-safe entries as removed. Both helpers now set the serving object and attach the routers before the hand registration, in the constructor's order, and the route enumeration walks included routers, which FastAPI 0.139 keeps as objects without a path in app.routes. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…n the OpenEngine metrics test The HTTP-enablement case builds a real OpenAIServer through its constructor and looked for /prometheus/metrics by reading .path off every entry of app.routes. Since the constructor attaches the system router, FastAPI 0.139 keeps an included-router object there that has no .path, and the child process failed with AttributeError. The test now matches a GET /prometheus/metrics request against the routes with the public route-matching API, which works on both ends of the pinned FastAPI range. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…d name The check that endpoint packages under tensorrt_llm/serve/api do not import each other read the package off the from-module alone, so `from tensorrt_llm.serve import api` inside an endpoint package passed and `from tensorrt_llm.serve.api.ops import system` inside ops/system failed. It now reads the package off <module>.<name> per imported name, as the layering contracts do, and a synthetic-edge test pins both forms. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…e/api/visual_gen Move the eight VisualGen request and response models (ImageGenerationRequest, ImageEditRequest, ImageObject, ImageGenerationResponse, MediaReferenceItem, VideoGenerationRequest, VideoJob, VideoJobList) out of tensorrt_llm/serve/openai_protocol.py into the new package tensorrt_llm/serve/api/visual_gen/ (protocol.py), unchanged. openai_protocol keeps the eight names importable through a lazy module __getattr__: importing it no longer loads the VisualGen models or tensorrt_llm.visual_gen, and the re-export is part of its own interface, so it never warns and has no removal release. The imports only the moved block used (UploadFile, AliasChoices, MediaRole) leave openai_protocol with it. Every importer in the repository now imports the new module; the benchmarking guide links the new file. protocol.py joins legacy-files.txt (its code comes from a legacy-formatted file) and the derived lint configs are regenerated. No behavior change. OpenAPI component names may change with the move; they are not a contract. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…isualGen team in CODEOWNERS VisualGen serving code now lives under tensorrt_llm/serve/api/visual_gen/. The new rule, placed after the /tensorrt_llm/serve rule so that it wins, makes @NVIDIA/trt-llm-torch-visual-gen-devs the owner of that directory: changes there need the VisualGen team's approval and no longer need runtime-devs. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…y re-export under a visual_gen path Add tests/unittest/api_stability/visual_gen/test_visual_gen_serve_api.py: it runs the checks of test_serve_api.py on the models of references/trtllm_serve_api.yaml that are defined in tensorrt_llm.serve.api.visual_gen.protocol, and checks that tensorrt_llm.serve.openai_protocol re-exports the eight VisualGen names lazily (importing it does not load the VisualGen module; unknown names still raise AttributeError). The file lives under a visual_gen/ path and has its own l0_cpu.yml entry so that CI selection for VisualGen-only pull requests keeps running it; the reference YAML is unchanged. Add the eight identity rows of the VisualGen names to the VisualGen shim identity table: identity only, no warning and no ban on the old path, because the re-export is openai_protocol's permanent interface. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…its no-warning contract Resolve every pinned model with the full gate's own loader, so a VisualGen model pinned in the reference YAML that is later renamed or removed fails this gate too instead of being dropped silently; the four known models stay a secondary check. Make the lazy-load probe's diagnostic best-effort and identity-based, so a failure prints which modules hold the VisualGen classes instead of crashing on module-level __getattr__ hooks while walking sys.modules. In the same fresh-interpreter probe, assert that reading each of the eight names from openai_protocol emits no FutureWarning or DeprecationWarning. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…e VisualGen protocol-package branch (NVIDIA#21509) Integration base for the VisualGen handler move: both open PRs must be on main before the handler move can merge, and the move is regenerated on the latest main at that time. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
… serve/api/visual_gen
Generated move of the VisualGen serving code out of OpenAIServer and the
video-routes mixin, with the shared error-response factory moved to
serve/_base/serving.py:
- serve/openai_video_routes.py -> serve/api/visual_gen/serving_videos.py
(the module helpers and the nine mixin methods, now on VideoServing)
- the image handlers and helpers of OpenAIServer
-> serve/api/visual_gen/serving_images.py (ImageServing)
- _reject_disabled_path -> serve/api/visual_gen/serving_base.py
(VisualGenBaseServing)
- _new_media_dir and _resolve_media_dir -> serve/api/visual_gen/media.py
- create_error_response -> serve/_base/serving.py (BaseServing);
OpenAIServer keeps staticmethod(BaseServing.create_error_response)
- serve/visual_gen_utils.py, serve/visual_gen_metrics.py and
serve/_visual_gen_errors.py move whole to
serve/api/visual_gen/{utils,metrics,errors}.py
The four old modules are deleted without a compatibility shim, and every
import in the repository points at the new modules. The new files that
carry yapf-formatted code are registered in legacy-files.txt and the lint
configs are regenerated from it; the mypy file list follows the renamed
errors module. The errors module docstring gains the blank line between
summary and description that the docstring rules require once the module
leaves its underscore name. The class headers, constructors, router and
composition-root wiring follow in the next commits.
Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…r into the VISUAL_GEN role The generated move left the handlers in bare classes; this commit adds what a move cannot write: - BaseServing (serve/_base/serving.py) gets its docstring; it holds the shared create_error_response and nothing else. - VisualGenBaseServing (serve/api/visual_gen/serving_base.py) derives from BaseServing and receives generator, model, media_storage_path and the server AdjustedSteadyClock as keyword-only constructor arguments, so missing wiring fails at construction; its _generate() is the one place that submits a generation off the event loop. ImageServing and VideoServing derive from it; VideoServing owns video_gen_tasks as instance state. - The image generation, synchronous video and asynchronous video handlers submit through self._generate(). The image edit keeps its synchronous generate() call: routing it through _generate() would stop it from blocking the event loop, a behavior change that belongs to its own fix (NVIDIA#21403). - _supports_image_edit drops its _is_visual_gen guard: ImageServing only exists for a VisualGen generator, so the guard was always false. - serve/api/visual_gen/api_router.py: one router made with make_router() for the ten image and video routes, bound late to the serving objects on app.state; attach_router refuses an app without them; init_serving_state resolves the media directory once and injects it into both serving objects. The router joins ROUTERS for the VISUAL_GEN role group and the mypy file list. - OpenAIServer no longer derives from the video-routes mixin. For the VISUAL_GEN role it loads the router module once with importlib, calls init_serving_state and registers only /metrics itself; the validation handler reaches the VisualGen renderer through that module. Routers are attached after the role switch, because every attach_router checks that its serving objects are on app.state; /health, /version and /v1/models therefore register after the role-specific routes, which conflicts with no route of any role. - The whole-file-moved utils module gets the repository SPDX header; the bench docstring that named the deleted video-routes module names the new modules. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…dia directory - The test sites that patched or imported names through their old modules now reach the modules the moved code reads: the media clock (api/visual_gen/media.datetime), the image encoder (serving_images.image_to_bytes), the image-edit limits and base64 on api/visual_gen/utils, and resolve_video_format on serving_videos; the module-object imports of the deleted modules follow their new paths. - New tests: images and videos share the one media directory the composition root resolves; the serving classes build without a server and without touching the filesystem; the router answers image and video requests on a bare app with every route on the msgpack route class; attach_router refuses an app whose serving objects are missing and names what to call; image generation, synchronous video and asynchronous video submit through VisualGenBaseServing._generate while the image edit still calls the synchronous generate(); _generate runs the submission off the event loop; OpenAIServer hosts none of the eighteen moved handlers and no video-task table. - test_context_length_error.py: OpenAIServer and the serving classes render errors through the one BaseServing function. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…NTS.md The "Where code goes" list points at tensorrt_llm/serve/api/visual_gen/ (ImageServing and VideoServing on VisualGenBaseServing, the router in api_router.py, one RouterSpec) and records that only the composition root, for the VISUAL_GEN role, loads the package. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
…ord the errors docstring The generated move dropped the type-only comment inside the video module import block and doubled the blank line after _KNOWN_VIDEO_OUTPUT_SUFFIXES; both are restored so the module reads as it did before the move. The errors module docstring no longer calls the module private: it is a public-named module internal to the VisualGen serving package. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
JunyiXu-nv
force-pushed
the
dev-junyix-feat-serve-visualgen-handler-move
branch
from
November 4, 2026 12:51
44fe0ad to
ece037b
Compare
JunyiXu-nv
added a commit
to JunyiXu-nv/TensorRT-LLM
that referenced
this pull request
Nov 12, 2026
Pin main at 1ceb4e6. Keep both source changes and the main-side package license headers. Drop redundant unittest/serve per-file registrations and the duplicate stand-in health tests, already covered by the real-constructor system endpoint tests. Validation: 122 focused tests passed, including 22 public runtime health and 14 private-access lint tests. The 3 VisualGen setup errors match pinned main exactly (12 shared health tests passed on both). Protected API collection also hits the same missing preallocate_nccl_window_buffer.bytes operator on main. Focused pre-commit passed. Keep the current 9 postprocess accesses and _save_bytes baseline location because NVIDIA#21392 and NVIDIA#21552 have not landed. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #21509 (Move the VisualGen protocol models into serve/api/visual_gen) and #21408 (Merge the two VisualGen validation-error renderers); the first commits below belong to those PRs and disappear from this diff when they merge; this PR's own change is the last 5 commits.
@coderabbitai summary
Description
Moves every VisualGen handler and helper out of
OpenAIServerand the video-routes mixin intotensorrt_llm/serve/api/visual_gen/:ImageServingandVideoServingon a sharedVisualGenBaseServingwith explicit constructors, one router created withmake_router(), and the VisualGen utils, metrics and validation-error renderer modules moved whole into the package.OpenAIServerstops inheriting the mixin and loads the package only for the VISUAL_GEN role, so no other role imports VisualGen serving code. The shared error-response factory becomesBaseServing.create_error_responseintensorrt_llm/serve/_base/serving.py;OpenAIServer.create_error_responsestays as the same function. The three image/video generation points submit through one_generate()helper. The four old modules are deleted without a compatibility shim: no code outside the repository imports them (GitHub code search on 2026-11-03 finds only forks of this repository).Part of the trtllm-serve refactor: VisualGen isolation (epic TRTLLM-17056, task TRTLLM-17264). Builds on #21448 (Add the trtllm-serve router skeleton and move /health, /version and /v1/models into ops.system), #21509 and #21408. The PR that lets the CI test selector claim
tensorrt_llm/serve/api/visual_gen/follows immediately; until it merges, VisualGen changes still run the full pre-merge suite.Behavior
No behavior change. Image edits still generate on the serving event loop (
VisualGen.generate()), because #21403 (Generate image edits off the serving event loop) has not merged; the image edit therefore keeps its synchronous call and does not go through_generate(). The three other generation points (image generation, synchronous and asynchronous video) submit through_generate(), which does what they did before:asyncio.to_thread(generate_async, ...).Differences in
/openapi.json, which is not a contract: the VISUAL_GEN listing has/metricsbefore/health,/versionand/v1/models(routers are now attached after the role switch), and the ten VisualGen operations no longer carry the descriptions their method docstrings gave them. Path set, methods, route classes and the order of routes that can match the same request are unchanged (route snapshot unchanged).Moves
Pure-move check
Pure-move check: base 51fa901, head ece037b, tools 517fc468330a
ROUTERS<module statements>render_visual_gen_validation_errorOpenAIServer.create_error_response_new_media_dir_resolve_media_dirOpenAIServer._reject_disabled_pathOpenAIServer._build_image_content_urlOpenAIServer._create_not_supported_errorOpenAIServer._image_objectOpenAIServer._parse_image_edit_requestOpenAIServer._supports_image_editOpenAIServer.get_image_contentOpenAIServer.openai_image_editOpenAIServer.openai_image_generation_image_output_size_normalize_image_outputOpenAIServer.__init__OpenAIServer._init_visual_genOpenAIServer.create_error_responseOpenAIServer.register_visual_gen_routesOpenAIServer_DEFAULT_TENSOR_FORMAT_KNOWN_VIDEO_OUTPUT_SUFFIXES_REFERENCE_FIELDS_VideoRoutesMixin._generate_video_background_VideoRoutesMixin._on_video_task_done_VideoRoutesMixin._parse_video_generation_request_VideoRoutesMixin.delete_video_VideoRoutesMixin.get_video_content_VideoRoutesMixin.get_video_metadata_VideoRoutesMixin.list_videos_VideoRoutesMixin.openai_video_generation_async_VideoRoutesMixin.openai_video_generation_sync_VideoRoutesMixin_path_json_video_response_preflight_encoder_format_resolve_tensor_only_format_video_content_typeVISUAL_GEN_DENOISE_TIMINGVISUAL_GEN_GENERATION_TIMINGVISUAL_GEN_POST_DENOISE_TIMINGVISUAL_GEN_PRE_DENOISE_TIMINGVISUAL_GEN_TOTAL_TIMING_server_timing_metricbuild_visual_gen_server_timingsbuild_visual_gen_timing_headersAsyncDictStoreIMAGE_EDIT_MAX_IMAGESIMAGE_EDIT_MAX_IMAGE_BYTESIMAGE_EDIT_MAX_OUTPUT_IMAGESIMAGE_EDIT_MAX_TOTAL_IMAGE_BYTESVIDEO_STORE_IMAGE_EDIT_INPUT_FORMATS_INVALID_IMAGE_EDIT_INPUT_MESSAGE_NO_SEMANTIC_FIELD_WARNINGS_apply_deprecated_input_reference_b64_build_image_edit_reference_list_build_reference_list_decode_base64_media_decode_image_edit_string_decode_inline_media_merge_extra_params_read_image_edit_upload_reference_transport_resolve_image_edit_layer_multiplier_validate_image_edit_request_limits_validate_png_jpeg_image_warn_if_set_with_no_semanticlocal_media_path_is_disallowedparse_visual_gen_paramsBaseServingtensorrt_llm/serve/api/visual_gen/api_router.py::*VisualGenBaseServing.__init__VisualGenBaseServing._generateVisualGenBaseServingImageServingVideoServing.__init__VideoServingReplaced
_VideoRoutesMixin->tensorrt_llm/serve/api/visual_gen/serving_videos.py::VideoServing: the mixin's class statement becomes VideoServing; its methods move under movesAdded
BaseServing: serving base class; holds create_error_responseVisualGenBaseServing: base class of the image and video serving classesVisualGenBaseServing.__init__: explicit dependencies instead of server attributes, so missing wiring fails at constructionVisualGenBaseServing._generate: the one generation point of the image and video handlersImageServing: image serving classVideoServing: replaces _VideoRoutesMixinVideoServing.__init__: explicit dependencies instead of server attributes, so missing wiring fails at constructiontensorrt_llm/serve/api/visual_gen/api_router.py::*: new router module (every definition in it is new)Changed in move (declared)
tensorrt_llm/serve/api/visual_gen/errors.py::__module__: module docstring split into a summary line and a description, and it no longer calls the module private: the file loses the private-module exemption from the docstring rules when it leaves its underscore name--- base
+++ head
@@ -1 +1 @@
-'The VisualGen 422 renderer shared by the route-level (
RequestValidationError)\nand handler-level (ValidationError) entry points. Private module.'+'The VisualGen 422 renderer.\n\nShared by the route-level (
RequestValidationError) and handler-level\n(ValidationError) entry points. Internal to the VisualGen serving package.\n'_VideoRoutesMixin.openai_video_generation_sync: generation call through self._generate--- base
+++ head
@@ -21,7 +21,7 @@
resolved_encoder_fmt = _preflight_encoder_format(request_format)
logger.info(f'Generating video: {video_id} with params: {params} and prompt: {request.prompt}')
sync_video_start = time.perf_counter()
_VideoRoutesMixin.openai_video_generation_async: generation call through self._generate--- base
+++ head
@@ -22,7 +22,7 @@
request_format = _resolve_tensor_only_format(request.format, params.extra_params, self.generator.extra_param_specs)
_preflight_encoder_format(request_format)
logger.info(f'Generating video: {video_id} with params: {params} and prompt: {request.prompt}')
OpenAIServer._supports_image_edit: drop the always-false _is_visual_gen guard--- base
+++ head
@@ -1,6 +1,4 @@
def _supports_image_edit(self) -> bool:
if executor is None:
return False
OpenAIServer.openai_image_generation: generation call through self._generate--- base
+++ head
@@ -15,7 +15,7 @@
params = parse_visual_gen_params(request, self.generator)
logger.info(f'Generating image: {image_id} with params: {params} and prompt: {request.prompt}')
image_gen_start = time.perf_counter()
Modified (declared)
OpenAIServer.__init__: VisualGen branch of the validation handler through self._visual_gen_api; attach_routers after the role switch--- base
+++ head
@@ -158,7 +158,7 @@
self.metrics_collector.log_request_error(http_code=400)
return anthropic_error_response(str(exc), 'invalid_request_error', 400)
if self.server_role is ServerRole.VISUAL_GEN:
-
@@ -166,7 +166,6 @@detail = detail[:4096] + ' ... [truncated %d bytes]' % (len(detail) - 4096)
return JSONResponse(status_code=400, content={'error': detail})
self.app.state.ops_serving_system = SystemServing(model=self.model, health_probe=self._health_probe)
if self.server_role is ServerRole.VISUAL_GEN:
assert self._is_visual_gen, 'generator must be a VisualGen for VISUAL_GEN server'
self.register_visual_gen_routes()
@@ -180,6 +179,7 @@
else:
self._register_launcher_forwarding_routes()
self.register_routes()
if self._collect_perf_metrics:
self.app.add_middleware(PerfMetricsMiddleware, expose_headers=self._expose_perf_metrics, writer=self._perf_metrics_writer, adjusted_clock=self._adjusted_steady_clock)
self.app.add_middleware(ServerArrivalTimeMiddleware, adjusted_clock=self._adjusted_steady_clock)
OpenAIServer._init_visual_gen: media directory and video tasks move to the VisualGen serving objects--- base
+++ head
@@ -1,6 +1,3 @@
def _init_visual_gen(self):
self.processor = None
self.model_config = None
OpenAIServer.register_visual_gen_routes: role-gated importlib load and init_serving_state; only /metrics stays--- base
+++ head
@@ -1,13 +1,10 @@
def register_visual_gen_routes(self):
self.app.add_api_route('/metrics', self.get_iteration_stats, methods=['GET'])
OpenAIServer: base class _VideoRoutesMixin removed--- base
+++ head
@@ -1,2 +1,2 @@
-class OpenAIServer(_VideoRoutesMixin):
+class OpenAIServer:
pass
ROUTERS: the VisualGen router joins the routing table for the VISUAL_GEN role group--- base
+++ head
@@ -1 +1 @@
-ROUTERS: tuple[RouterSpec, ...] = (RouterSpec('tensorrt_llm.serve.api.ops.system.api_router', roles=ALL_ROLE_GROUPS),)
+ROUTERS: tuple[RouterSpec, ...] = (RouterSpec('tensorrt_llm.serve.api.ops.system.api_router', roles=ALL_ROLE_GROUPS), RouterSpec('tensorrt_llm.serve.api.visual_gen.api_router', roles=frozenset({RoleGroup.VISUAL_GEN})))
60 definitions moved verbatim; 0 differences; 5 changed in move (declared); 3 files moved; 1 borrowed; 1 replaced; 8 added; 5 modified (declared); shim exports 0 names