Skip to content

[Frontend] Add return_mm_kwargs to render requests - #60728

Merged
DarkLight1337 merged 3 commits into
vllm-project:mainfrom
vMaroon:render-return-mm-kwargs
Oct 9, 2026
Merged

DarkLight1337 merged 3 commits into
vllm-project:mainfrom
vMaroon:render-return-mm-kwargs

Conversation

@vMaroon

@vMaroon vMaroon commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Add return_mm_kwargs to render requests. When false, the render response leaves out the processed multimodal tensors (kwargs_data) and mm_metadata, for callers that need only token ids, item hashes and placeholder ranges, such as cache-aware routers. Part of #46722.

Claims

  • return_mm_kwargs: false on the chat, completions, Messages and Responses render endpoints returns kwargs_data and mm_metadata as null. Token ids, mm_hashes and mm_placeholders are unchanged. The default (true) keeps current behavior.
  • For four 1080p images the response drops from 66.91 MB to 0.058 MB, and render time from 166-189 ms to 38 ms with a warm processor cache, or from 194 to 74 ms cold.
  • Tensor serialization no longer holds the API server's event loop: /health p99 during back-to-back renders goes from 114.5 to 2.0 ms.

Validation

pytest tests/entrypoints/scale_out/token_in_token_out/test_mm_serde.py tests/entrypoints/scale_out/token_in_token_out/test_protocol.py: 45 passed, including the new test_extract_without_kwargs_keeps_layout.

End to end on this head: vllm launch render Qwen/Qwen3-VL-8B-Instruct on CPU (M4 Pro, OMP_NUM_THREADS=1), four 1920x1080 PNGs by URL, median of 3 after a warm-up:

Endpoint Default return_mm_kwargs: false Token ids, hashes, placeholders equal
chat 166.0 ms, 66.91 MB 37.9 ms, 0.058 MB yes
Messages 172.2 ms, 66.91 MB 38.1 ms, 0.058 MB yes
Responses 188.9 ms, 66.91 MB 37.5 ms, 0.058 MB yes

Measured with the same change on main 1afb029839, processor cache off (--mm-processor-cache-gb 0): render 193.9 to 73.6 ms. The time removed is json.dumps of the response (102 ms) and msgpack plus base64 (4.8 ms), both on the event loop, plus 14 ms of transfer. With renders back to back, /health p99 goes from 114.5 to 2.0 ms and max from 117.4 to 4.1 ms.

On GPUs: 2 x H100 serving Qwen3-VL-8B (nightly 81198e97 with this change laid over the installed package) behind llm-d-router with llm-d/llm-d-router#3273, closed loop, four 1080p images by URL per request, 60 s per step, flag off, on, off. At 16 concurrent clients throughput went from 2.6 to 8.3 req/s, client p95 from 15.2 to 3.0 s, and engine /health p99 from 1,177 to 11 ms. With the flag on, the router's predicted cached tokens equal the engine's cached tokens (6 of 6 repeats, chat and Messages).

Not run: the GPU vllm serve render tests (tests/entrypoints/scale_out/render/test_render_multimodal.py). No model eval: the change affects only render responses.

Details

AI assistance (Claude) was used to write this change and run the validation above.


Pull Request Checklist
  • I used vLLM's /pr-checklist skill. (Mandatory for agents, optional for humans).

  • AI assistance was used during the creation of this PR.

  • Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.

  • Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.

  • Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.

  • Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.

Cache-aware routers call the render endpoints for token ids, item
hashes and placeholder ranges, and discard the processed tensors.
Serializing those tensors dominates render time for image requests
and holds the API server's event loop: four 1080p images produce a
66.9 MB response, of which a router reads 58 KB.

`return_mm_kwargs: false` leaves `kwargs_data` and `mm_metadata` null
on the chat, completions, Messages and Responses render endpoints.

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Maroon Ayoub <mayoub@redhat.com>
@mergify

mergify Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Documentation preview: https://vllm--60728.org.readthedocs.build/en/60728/

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@sagearc sagearc 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.

great! left 2 style nits though

kwargs_data: dict[str, list[str | None]] | None = None
mm_metadata: dict[str, list[str | None]] | None = None
if raw_mm_kwargs := mm_engine_input.get("mm_kwargs"):
if include_kwargs and (raw_mm_kwargs := mm_engine_input.get("mm_kwargs")):

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.

nit: more python-idiomatic way

Suggested change
if include_kwargs and (raw_mm_kwargs := mm_engine_input.get("mm_kwargs")):
if include_kwargs:
raw_mm_kwargs = mm_engine_input.get("mm_kwargs")
if raw_mm_kwargs:
kwargs_data, mm_metadata = _encode_mm_kwargs_with_metadata(
raw_mm_kwargs,
metadata_fields_for=metadata_fields_for,
)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 8b8c271.

engine_input: EngineInput,
*,
metadata_fields_for: Callable[[str], Collection[str]] | None = None,
include_kwargs: bool = True,

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.

Could we rename include_kwargs to include_mm_kwargs in both helpers? It would make the scope explicit and align it with return_mm_kwargs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 8b8c271, in both helpers and the test.

Matches the request field `return_mm_kwargs`, per review.

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Maroon Ayoub <mayoub@redhat.com>
@vMaroon

vMaroon commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

❌ This PR is 19 commits behind upstream main. Your branch must contain every commit currently on upstream main. No new CI build was started. Merge or rebase onto the latest main, then rerun /ci run. To test this branch at your own risk, use /ci run --allow-stale.

…args

Signed-off-by: Maroon Ayoub <mayoub@redhat.com>
@vMaroon

vMaroon commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93789 for commit bfc70e0ee2d9.

@DarkLight1337
DarkLight1337 enabled auto-merge (squash) October 9, 2026 07:11
@github-actions github-actions Bot added the ready ONLY add when PR is ready to merge/full CI is needed label Oct 9, 2026

@hickeyma hickeyma 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.

LGTM, thanks @vMaroon

@DarkLight1337
DarkLight1337 merged commit 8a03ccf into vllm-project:main Oct 9, 2026
107 of 108 checks passed
@vMaroon
vMaroon deleted the render-return-mm-kwargs branch October 9, 2026 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation frontend ready ONLY add when PR is ready to merge/full CI is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants