Skip to content

[Frontend][Rust] Support mm_processor_kwargs in chat completions - #50164

Open
almogtavor wants to merge 3 commits into
vllm-project:mainfrom
almogtavor:rust-mm-processor-kwargs
Open

almogtavor wants to merge 3 commits into
vllm-project:mainfrom
almogtavor:rust-mm-processor-kwargs

Conversation

@almogtavor

@almogtavor almogtavor commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Purpose

Roadmap item from #44280: mm_processor_kwargs.

The Rust frontend rejected it with mm_processor_kwargs is not supported. on /v1/chat/completions. This accepts it and makes it take effect.

Implementation

The kwargs are merged onto the model's resolved PreProcessorConfig in vllm-chat, right before the image and video preprocessors run, so both modalities honour a per-request override such as min_pixels or max_pixels.

The merge deserializes the request map as a PreProcessorConfig, which type checks known keys, then copies over only the keys the request actually set, leaving the rest of the model default intact. Keys the struct does not name land in its #[serde(flatten)] extra map, which is where model-specific keys from preprocessor_config.json already go, so they still reach the processor rather than being dropped. A bad value (for example "max_pixels": "lots") is a request validation error and returns HTTP 400.

Test

cargo test -p vllm-chat -p vllm-server

All green. New tests in vllm-chat cover: unset kwargs keep the model config, only requested keys are overridden, unknown keys survive through extra, and a wrong value type produces InvalidMmProcessorKwargs classified as a request validation error. A vllm-server test covers the convert layer forwarding the field.

cargo clippy -p vllm-chat -p vllm-server --all-targets is clean and cargo fmt applied.

Runtime check on an H100

Built vllm-rs from this branch against the image's own vLLM commit and served Qwen2-VL-2B with VLLM_USE_RUST_FRONTEND=1, confirming the Rust frontend was the process answering (it exits on startup if it is not). Same 1024x1024 image in every request, only mm_processor_kwargs differs:

request prompt_tokens
no kwargs (model default) 1391
{"max_pixels": 200704} 278
{"max_pixels": 50176} 86
{"merge_kernel_size": [2, 2]} (unknown key) 1391

{"max_pixels": "lots"} returns HTTP 400 with invalid mm_processor_kwargs: invalid type: string "lots", expected usize and "type": "invalid_request_error".

So the override reaches the image processor and changes the token count, an unknown key is forwarded through extra without breaking the request, and a bad value is a client error rather than a 500.

AI assistance was used for this change.

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

@mergify mergify Bot added the rust label Jul 28, 2026
@BugenZhao

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fbb6f29953

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rust/src/chat/src/multimodal/image.rs
Comment thread rust/src/chat/src/multimodal.rs
Comment thread rust/src/chat/src/multimodal.rs
@mergify

mergify Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @almogtavor.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jul 29, 2026
The Rust frontend rejected `mm_processor_kwargs` outright. Accept it and
merge it onto the model's resolved `PreProcessorConfig` before the image
and video preprocessors run, so per-request overrides such as
`min_pixels` and `max_pixels` take effect.

Known keys are type checked by deserializing the request map as a
`PreProcessorConfig`, and only keys the request sets override the model
default. Keys the struct does not name land in its `extra` catch-all,
which is where model-specific keys from `preprocessor_config.json`
already go, so they still reach the processor. A bad value is a request
validation error and surfaces as HTTP 400.

`media_io_kwargs` stays rejected: it has to reach the media loader, and
`MediaConnectorConfig` in `llm-multimodal` carries no per-request IO
kwargs to forward it into.

Part of vllm-project#44280.

Signed-off-by: almogtavor <almogtavor@gmail.com>
@almogtavor
almogtavor force-pushed the rust-mm-processor-kwargs branch from fbb6f29 to d6eb2f6 Compare July 31, 2026 23:00
@almogtavor

almogtavor commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@BugenZhao Rebased on main, and all three review points are addressed.

Cache key. This was a real bug. The overrides change the tensors, but the item hash came straight from the raw image or clip hash, so the same image sent twice with different max_pixels would have shared an encoder cache entry. Media hashes now carry a digest of the effective kwargs, canonicalised through a BTreeMap so the digest does not depend on map iteration order. Two tests cover it: different overrides give different keys, and no overrides leave the upstream hash untouched.

Audio. Rejected rather than silently ignored, since the audio preprocessor takes a different config type and would drop the overrides.

Error conversion. Now uses to_report_string() instead of to_string(), per rust/AGENTS.md.

One TODO remains, on the field list in merge_mm_processor_kwargs. PreProcessorConfig derives Deserialize but not Serialize, so a generic JSON merge is not possible and the typed fields have to be listed. Anything not listed still reaches the processor through the struct's extra catch-all, so a new upstream field degrades to pass-through rather than being dropped.

@almogtavor

almogtavor commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@BugenZhao this implements the mm_processor_kwargs item from #44280 for chat completions. Per-request kwargs are merged onto a clone of the model's PreProcessorConfig before processor.preprocess, so unknown keys still flow through extra the way the crate handles model-specific fields.

Verified at runtime rather than only in unit tests: built vllm-rs from this branch against the image's own vLLM commit and served Qwen2-VL, confirming the Rust frontend was the process answering. Same image each request, only the kwargs differ:

no kwargs            1391 prompt_tokens
max_pixels=200704     278
max_pixels=50176       86
unknown key          1391   (forwarded via extra, no error)
max_pixels="lots"    HTTP 400  invalid mm_processor_kwargs: invalid type: string "lots", expected usize

vllm-project#50368 added a prepare_multimodal call for the gRPC and /inference/generate
paths after this branch changed the signature. Those callers carry no
per-request kwargs, so the model config applies unchanged.

Signed-off-by: almogtavor <almogtavor@gmail.com>
@almogtavor

Copy link
Copy Markdown
Contributor Author

@BugenZhao ping on this when you get a chance. all three codex findings are fixed and the threads are resolved, and i just merged main which needed one line because #50368 added a prepare_media call site that now passes None for the kwargs

@mergify

mergify Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @almogtavor.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants