[TRTLLM-14730][feat] Add image edit serving endpoint for visual generation models - #16987
Conversation
f5b8b99 to
bad7e7f
Compare
|
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:
WalkthroughQwen image-edit requests now support JSON and multipart inputs for supported Qwen visual-generation models. Qwen-Image-Layered outputs default to separate RGBA layers, with an option to return a packed grid. Tests, examples, and model documentation reflect the new behavior. ChangesQwen Image Edit and Layer Output
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant OpenAIServer
participant visual_gen_utils
participant QwenImageLayeredPipeline
Client->>OpenAIServer: Submit image-edit request
OpenAIServer->>visual_gen_utils: Materialize input images
OpenAIServer->>QwenImageLayeredPipeline: Generate edited layers
QwenImageLayeredPipeline-->>OpenAIServer: Return layers or grid
OpenAIServer-->>Client: Return encoded images or URLs
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
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_qwen_image_layered_registry.py (1)
117-126: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winTest coverage is insufficient
- Modified:
test_qwen_image_layered_default_params_match_runtime_inputs,test_qwen_image_layered_layer_stack_to_image_grid- Added:
test_qwen_image_layered_formats_multiple_layer_images_by_default,test_qwen_image_layered_rejects_non_bool_save_layers_to_grid- No matching entry was found for
tests/unittest/_torch/visual_gen/test_qwen_image_layered_registry.pyintests/integration/test_lists/; add it to the appropriate list (likelytests/integration/test_lists/test-db/l0_b200.yml) so it runs in CI.🤖 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_qwen_image_layered_registry.py` around lines 117 - 126, Add tests/unittest/_torch/visual_gen/test_qwen_image_layered_registry.py to the appropriate CI test-list entry, likely tests/integration/test_lists/test-db/l0_b200.yml, so the Qwen image layered registry tests run in CI.Source: Path instructions
🤖 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 `@docs/source/models/supported-models.md`:
- Around line 191-192: Update the footnote definitions in the supported-models
documentation: align the FLUX definition with the matrix’s referenced footnote
identifier, and remove or rename the duplicate `[^3]` definition so the
Qwen-Image-Layered row resolves to its intended note. Preserve the existing
footnote text and ensure all referenced definitions are unique and
markdownlint-compliant.
In `@examples/visual_gen/models/qwen_image_layered.py`:
- Around line 69-79: Update the output-saving condition around output.image to
inspect the leading batch dimension size rather than image rank: use the
multi-file layer path only when output.image.shape[0] is greater than one, and
preserve the direct output.save(args.output_path) path for a single image or
grid.
In `@tensorrt_llm/serve/visual_gen_utils.py`:
- Around line 105-131: Update _materialize_conditioning_input so existing local
paths and file:// URIs are not passed through unchanged; only accept paths under
media_storage_path or an established allowed-path list, materializing or
rejecting other local inputs. Preserve direct passthrough for HTTP(S) URLs and
ensure _load_image_input can only open image files from the permitted upload
storage.
---
Outside diff comments:
In `@tests/unittest/_torch/visual_gen/test_qwen_image_layered_registry.py`:
- Around line 117-126: Add
tests/unittest/_torch/visual_gen/test_qwen_image_layered_registry.py to the
appropriate CI test-list entry, likely
tests/integration/test_lists/test-db/l0_b200.yml, so the Qwen image layered
registry tests run in CI.
🪄 Autofix (Beta)
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: f782df60-3992-4e72-b5a7-890a7578cc60
📒 Files selected for processing (9)
docs/source/models/supported-models.mddocs/source/models/visual-generation.mdexamples/visual_gen/models/qwen_image_layered.pytensorrt_llm/_torch/visual_gen/models/qwen_image_layered/pipeline_qwen_image_layered.pytensorrt_llm/serve/openai_protocol.pytensorrt_llm/serve/openai_server.pytensorrt_llm/serve/visual_gen_utils.pytests/unittest/_torch/visual_gen/test_qwen_image_layered_registry.pytests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
There was a problem hiding this comment.
Actionable comments posted: 1
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)
147-174: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winPreserve an explicitly empty extra-parameter schema.
extra_param_specs={}is stored as empty, but the executor receives the fallbackstg_scaleschema because both assignments use truthiness. This makes the mock metadata disagree with validation behavior and can let tests accept an unsupported parameter. Useis not Nonewhen selecting the fallback.🤖 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 147 - 174, Update the executor.extra_param_specs assignment in the mock initialization to use the provided extra_param_specs whenever it is not None, including an explicitly empty dictionary; only apply the default stg_scale schema when no schema was supplied. Keep the earlier self._extra_param_specs assignment and existing validation metadata unchanged.
🤖 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 746-759: Preserve any pre-existing TRTLLM_MEDIA_STORAGE_PATH
instead of unconditionally removing it after each test. Update both
environment-handling blocks at
tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py lines 746-759
and 776-790 to use monkeypatch.setenv() or explicitly restore the original value
during cleanup.
---
Outside diff comments:
In `@tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py`:
- Around line 147-174: Update the executor.extra_param_specs assignment in the
mock initialization to use the provided extra_param_specs whenever it is not
None, including an explicitly empty dictionary; only apply the default stg_scale
schema when no schema was supplied. Keep the earlier self._extra_param_specs
assignment and existing validation metadata unchanged.
🪄 Autofix (Beta)
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: d0ac62ec-8f0c-4eb3-bc61-d1f609448ef9
📒 Files selected for processing (1)
tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
There was a problem hiding this comment.
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)
163-174: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winPreserve an explicit empty extra-parameter schema.
Line 173 converts
{}into the defaultstg_scaleschema.MockVisualGen(extra_param_specs={})then exposes no extra parameters throughextra_param_specs, but its executor acceptsstg_scale. Tests cannot model a pipeline that rejects every model-specific parameter.Proposed fix
- extra_param_specs=extra_param_specs - or {"stg_scale": ExtraParamSchema(type="float", default=1.0)}, + extra_param_specs=( + extra_param_specs if extra_param_specs is not None else { + "stg_scale": ExtraParamSchema(type="float", default=1.0), + } + ),🤖 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 163 - 174, Update the SimpleNamespace initialization in MockVisualGen so extra_param_specs uses the provided value whenever it is explicitly supplied, including an empty dictionary, and only applies the default stg_scale schema when the argument is omitted or None. Keep the executor’s extra_param_specs consistent with the model’s exposed parameters.
🧹 Nitpick comments (1)
tensorrt_llm/serve/visual_gen_utils.py (1)
105-106: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse explicit input types instead of
Anyandhasattr().Type the helpers with their supported union, including
bytesandstarlette.datastructures.UploadFile. Useisinstance(value, starlette.datastructures.UploadFile)becauseraw_request.form()can return Starlette upload objects, notfastapi.UploadFileinstances.🤖 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/visual_gen_utils.py` around lines 105 - 106, Update _materialize_conditioning_input and its related helpers to use an explicit supported union type including bytes and starlette.datastructures.UploadFile instead of Any; replace hasattr-based detection with isinstance(value, starlette.datastructures.UploadFile), ensuring Starlette upload objects returned by raw_request.form() are handled correctly.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.
Outside diff comments:
In `@tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py`:
- Around line 163-174: Update the SimpleNamespace initialization in
MockVisualGen so extra_param_specs uses the provided value whenever it is
explicitly supplied, including an empty dictionary, and only applies the default
stg_scale schema when the argument is omitted or None. Keep the executor’s
extra_param_specs consistent with the model’s exposed parameters.
---
Nitpick comments:
In `@tensorrt_llm/serve/visual_gen_utils.py`:
- Around line 105-106: Update _materialize_conditioning_input and its related
helpers to use an explicit supported union type including bytes and
starlette.datastructures.UploadFile instead of Any; replace hasattr-based
detection with isinstance(value, starlette.datastructures.UploadFile), ensuring
Starlette upload objects returned by raw_request.form() are handled correctly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: b8ee523f-9694-47cd-bf0a-94d7a41ec3c2
📒 Files selected for processing (4)
docs/source/models/supported-models.mdexamples/visual_gen/models/qwen_image_layered.pytensorrt_llm/serve/visual_gen_utils.pytests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
🚧 Files skipped from review as they are similar to previous changes (1)
- docs/source/models/supported-models.md
e9f7506 to
4b6542f
Compare
|
/bot run |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
tensorrt_llm/serve/openai_server.py (2)
2594-2638: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winGuard against non-string
extra_paramsin multipart requests.If a client sends the
extra_paramsfield as a file part instead of text,valueat line 2621-2630 is anUploadFile, not a string.value == ""isFalse, so the code proceeds tojson.loads(value), which raisesTypeError, notjson.JSONDecodeError. ThatTypeErroris not caught byexcept json.JSONDecodeErrorhere, nor byexcept ValueError/except ValidationErrorinopenai_image_edit, so it falls through to the outerexcept Exceptionand returns anInternalServerError(500) instead of aBadRequestError(400) for what is a client-input error.🐛 Proposed fix
if key == "extra_params": if value == "": continue + if not isinstance(value, str): + raise ValueError( + "'extra_params' must be a JSON object string.") try: data[key] = json.loads(value) except json.JSONDecodeError as exc:🤖 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_server.py` around lines 2594 - 2638, Guard the extra_params branch in _parse_image_edit_request against non-string multipart values before calling json.loads. Treat an UploadFile or any other non-string value as invalid client input and raise ValueError, while preserving the existing empty-value skip and JSON decoding behavior so openai_image_edit returns a 400 response instead of an internal error.
500-511: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse bounded matching for image-edit model IDs.
_model_supports_image_edit()uses unbounded substring matching. This enables image editing for unrelated IDs such asorg/not-qwen-image-edit-compatible. Match supported model IDs with explicit boundaries while preserving valid variants such asQwen/Qwen-Image-Edit-2511, and add regression tests for near matches.🤖 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_server.py` around lines 500 - 511, Update _model_supports_image_edit to use bounded matching for supported model identifiers, so embedded substrings in unrelated IDs are rejected while valid variants such as Qwen/Qwen-Image-Edit-2511 remain accepted. Preserve _supports_image_edit’s existing model-ID sources and add regression tests covering both near-match rejection and valid variant acceptance.
♻️ Duplicate comments (1)
tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py (1)
930-996: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winUse
monkeypatch.setenv()instead of rawos.environmutation.
test_qwen_layered_image_edit_returns_multiple_layers_by_default(lines 948, 961) andtest_qwen_layered_image_edit_save_layers_to_grid_returns_single_image(lines 978, 992) set and then unconditionally popTRTLLM_MEDIA_STORAGE_PATHviaos.environ, unlike the newer tests in this same class that already usemonkeypatch.setenv(...). This mirrors the pattern flagged in a prior review round for this same test family: it can clobber a pre-existing value ofTRTLLM_MEDIA_STORAGE_PATHand leaves it removed instead of restored.♻️ Proposed fix
- os.environ["TRTLLM_MEDIA_STORAGE_PATH"] = str(tmp_path) + monkeypatch.setenv("TRTLLM_MEDIA_STORAGE_PATH", str(tmp_path)) client = _create_server(gen, model_name="Qwen/Qwen-Image-Layered") - try: - image_bytes = BytesIO(base64.b64decode(_b64_white_png_1x1())) - resp = client.post(...) - finally: - os.environ.pop("TRTLLM_MEDIA_STORAGE_PATH", None) + image_bytes = BytesIO(base64.b64decode(_b64_white_png_1x1())) + resp = client.post(...)Add the
monkeypatchfixture parameter to both test functions.🤖 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 930 - 996, Update both test methods, test_qwen_layered_image_edit_returns_multiple_layers_by_default and test_qwen_layered_image_edit_save_layers_to_grid_returns_single_image, to accept the monkeypatch fixture and replace direct os.environ assignment/removal with monkeypatch.setenv("TRTLLM_MEDIA_STORAGE_PATH", str(tmp_path)). Remove the manual cleanup blocks so any pre-existing environment value is restored automatically.
🧹 Nitpick comments (2)
tensorrt_llm/serve/visual_gen_utils.py (2)
141-171: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNarrow the broad exception handling.
Both
_materialize_conditioning_input(line 164) and_materialize_conditioning_inputs(line 245) catchexcept Exception:before cleanup and re-raise. The only exceptions the wrapped calls can raise here areValueError(limit/decode failures) andOSError(file I/O failures). Catch that narrower tuple instead ofException.♻️ Proposed fix
- except Exception: + except (ValueError, OSError): try: os.remove(path) except FileNotFoundError: pass raiseApply the same change to the
except Exception:at line 245.As per coding guidelines, "Catch specific exceptions instead of using broad or bare exception handling such as
except:."Also applies to: 222-248
🤖 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/visual_gen_utils.py` around lines 141 - 171, Replace the broad exception handlers in _materialize_conditioning_input and _materialize_conditioning_inputs with a tuple catching only ValueError and OSError, while preserving the existing path cleanup and re-raise behavior.Source: Coding guidelines
251-261: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a docstring to this public helper.
cleanup_materialized_conditioning_inputsis imported and called fromopenai_server.py, so it is a cross-module public interface. It currently has no docstring, unlike its sibling_materialize_conditioning_input. Document that it accepts a single path or a list, silently skips non-string entries, and tolerates missing files.As per coding guidelines, "Prefer docstrings for external interfaces, use Google-style docstrings, document public function arguments."
🤖 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/visual_gen_utils.py` around lines 251 - 261, Add a Google-style docstring to the public helper cleanup_materialized_conditioning_inputs describing that value may be one path or a list of paths, non-string entries are skipped, and missing files are tolerated; document its argument according to the project’s docstring conventions.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.
Outside diff comments:
In `@tensorrt_llm/serve/openai_server.py`:
- Around line 2594-2638: Guard the extra_params branch in
_parse_image_edit_request against non-string multipart values before calling
json.loads. Treat an UploadFile or any other non-string value as invalid client
input and raise ValueError, while preserving the existing empty-value skip and
JSON decoding behavior so openai_image_edit returns a 400 response instead of an
internal error.
- Around line 500-511: Update _model_supports_image_edit to use bounded matching
for supported model identifiers, so embedded substrings in unrelated IDs are
rejected while valid variants such as Qwen/Qwen-Image-Edit-2511 remain accepted.
Preserve _supports_image_edit’s existing model-ID sources and add regression
tests covering both near-match rejection and valid variant acceptance.
---
Duplicate comments:
In `@tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py`:
- Around line 930-996: Update both test methods,
test_qwen_layered_image_edit_returns_multiple_layers_by_default and
test_qwen_layered_image_edit_save_layers_to_grid_returns_single_image, to accept
the monkeypatch fixture and replace direct os.environ assignment/removal with
monkeypatch.setenv("TRTLLM_MEDIA_STORAGE_PATH", str(tmp_path)). Remove the
manual cleanup blocks so any pre-existing environment value is restored
automatically.
---
Nitpick comments:
In `@tensorrt_llm/serve/visual_gen_utils.py`:
- Around line 141-171: Replace the broad exception handlers in
_materialize_conditioning_input and _materialize_conditioning_inputs with a
tuple catching only ValueError and OSError, while preserving the existing path
cleanup and re-raise behavior.
- Around line 251-261: Add a Google-style docstring to the public helper
cleanup_materialized_conditioning_inputs describing that value may be one path
or a list of paths, non-string entries are skipped, and missing files are
tolerated; document its argument according to the project’s docstring
conventions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 0592c272-a419-4976-9fc8-46b88e7dffd4
📒 Files selected for processing (6)
docs/source/models/supported-models.mdexamples/visual_gen/models/qwen_image_layered.pytensorrt_llm/serve/openai_protocol.pytensorrt_llm/serve/openai_server.pytensorrt_llm/serve/visual_gen_utils.pytests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py
🚧 Files skipped from review as they are similar to previous changes (3)
- tensorrt_llm/serve/openai_protocol.py
- examples/visual_gen/models/qwen_image_layered.py
- docs/source/models/supported-models.md
|
PR_Github #62948 [ run ] triggered by Bot. Commit: |
|
PR_Github #62948 [ run ] completed with state
|
|
/bot run |
|
PR_Github #62969 [ run ] triggered by Bot. Commit: |
|
PR_Github #62969 [ run ] completed with state
|
|
/bot run |
|
PR_Github #63009 [ run ] triggered by Bot. Commit: |
Signed-off-by: yibinl-nvidia <109242046+yibinl-nvidia@users.noreply.github.com>
Signed-off-by: yibinl-nvidia <109242046+yibinl-nvidia@users.noreply.github.com>
Signed-off-by: yibinl-nvidia <109242046+yibinl-nvidia@users.noreply.github.com>
Signed-off-by: yibinl-nvidia <109242046+yibinl-nvidia@users.noreply.github.com>
Ensure the seconds-without-frame-rate test removes the mock pipeline frame_rate default so it exercises the intended validation path. Signed-off-by: yibinl-nvidia <109242046+yibinl-nvidia@users.noreply.github.com>
Signed-off-by: yibinl-nvidia <109242046+yibinl-nvidia@users.noreply.github.com>
Signed-off-by: yibinl-nvidia <109242046+yibinl-nvidia@users.noreply.github.com>
3a001dc to
4ce1940
Compare
|
/bot run |
|
PR_Github #66856 [ run ] triggered by Bot. Commit: |
|
PR_Github #66856 [ run ] completed with state
|
|
/bot run |
|
PR_Github #66875 [ run ] triggered by Bot. Commit: |
|
PR_Github #66875 [ run ] completed with state
|
|
/bot run |
|
PR_Github #66906 [ run ] triggered by Bot. Commit: |
|
PR_Github #66906 [ run ] completed with state
|
|
/bot run |
|
PR_Github #66944 [ run ] triggered by Bot. Commit: |
|
PR_Github #66944 [ run ] completed with state
|
|
/bot run |
|
PR_Github #67050 [ run ] triggered by Bot. Commit: |
|
PR_Github #67050 [ run ] completed with state
|
|
/bot run |
|
PR_Github #67057 [ run ] triggered by Bot. Commit: |
|
PR_Github #67057 [ run ] completed with state |
Description
Adds an OpenAI-compatible
/v1/images/editsserving endpoint for VisualGen models. The endpoint accepts JSON/base64 and multipart image inputs, materializes uploaded inputs into server-owned temporary storage, cleans request input files after generation, and returns edited images through eitherurlorb64_jsonresponses.This PR wires image edit serving for Qwen image-edit, Qwen-Image-Layered, and Flux2 local checkpoint routing. For Qwen-Image-Layered, the pipeline default output changes from a packed layer grid to a per-layer image batch; callers that need the previous single-grid behavior should pass
extra_params={"save_layers_to_grid": true}.Test Coverage
tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.pytests/unittest/_torch/visual_gen/test_qwen_image_layered_registry.pytests/integration/test_lists/test-db/l0_b200.ymlenrolls both visual-gen unit test files.