Skip to content

fix: support approx routing in mm router - #8135

Open
zhongdaor-nv wants to merge 4 commits into
mainfrom
zhongdaor/support_approx_routing_mm_router
Open

fix: support approx routing in mm router#8135
zhongdaor-nv wants to merge 4 commits into
mainfrom
zhongdaor/support_approx_routing_mm_router

Conversation

@zhongdaor-nv

@zhongdaor-nv zhongdaor-nv commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Overview:

Details:

  • Add --no-router-kv-events flag to the MM Router Worker to switch between exact and approximate KV routing. Default is exact routing (listens to worker KV events); passing the flag enables approximate mode where the router infers cache state from its own routing decisions via prefix hashing.
  • Add Qwen3.5 launch script (examples/backends/vllm/qwen35/launch.sh) with three-tier architecture: Frontend (round-robin) → MM Router Worker (approximate KV) → vLLM Worker.
  • Parametrize the e2e test suite over both routing modes (exact_kv, approx_kv) so all tests run against both configurations with the same assertions.

Where should the reviewer start?

Test plan

  • pytest tests/mm_router/test_vllm_mm_router_e2e.py -v -s -k "exact_kv" — exact routing with KV events from vLLM worker
  • pytest tests/mm_router/test_vllm_mm_router_e2e.py -v -s -k "approx_kv" — approximate routing without KV events

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

  • closes GitHub issue: #xxx

Summary by CodeRabbit

Release Notes

  • New Features

    • Added launch script for Qwen3.5 multimodal model with hybrid KV routing support
    • New CLI option to configure router KV event handling for optimized multimodal deployments
  • Tests

    • Enhanced end-to-end test coverage for exact and approximate KV routing modes

Signed-off-by: zhongdaor <zhongdaor@nvidia.com>
@github-actions github-actions Bot added fix backend::vllm Relates to the vllm backend labels Apr 13, 2026
Signed-off-by: zhongdaor <zhongdaor@nvidia.com>
@zhongdaor-nv
zhongdaor-nv marked this pull request as ready for review April 13, 2026 23:10
@zhongdaor-nv
zhongdaor-nv requested review from a team April 13, 2026 23:10
@zhongdaor-nv
zhongdaor-nv requested review from a team as code owners April 13, 2026 23:10
@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This pull request introduces support for approximate KV routing mode in vLLM multimodal router setups. Changes include a new CLI flag to disable router KV events, a bash launch script for Qwen3.5 model orchestration with three-process setup, and parametrized test fixtures to validate both exact and approximate routing configurations.

Changes

Cohort / File(s) Summary
MM Router CLI Configuration
examples/backends/vllm/mm_router_worker/mm_router_worker.py
Added --no-router-kv-events CLI flag to disable KV event caching in router. Updated --namespace default from fixed "default" to environment variable DYN_NAMESPACE (or "dynamo"). Added router configuration construction with conditional use_kv_events setting. Updated startup logging to report chosen use_kv_events value.
Qwen3.5 Multimodal Launch Script
examples/backends/vllm/qwen35/launch.sh
New executable bash script that orchestrates three-process vLLM multimodal setup: vLLM worker with multimodal and hybrid KV routing support, MM Router Worker with --no-router-kv-events flag, and frontend dispatcher in round-robin mode. Includes environment configuration for TCP transport, default runtime parameters, and example curl commands.
Router Test Parametrization
tests/mm_router/test_vllm_mm_router_e2e.py
Made kv_event_port optional (defaults to None) in VLLMWorkerProcess. Added approx_routing parameter to VLLMMMRouterWorkerProcess. Modified pytest fixture to parametrize end-to-end tests for both exact_kv mode (with 4 ports) and approx_kv mode (with 3 ports, no KV events).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding support for approximate KV routing in the multimodal router, which aligns with the core changes across the three modified files.
Description check ✅ Passed The description provides substantive details on changes (KV routing modes, launch script, e2e test parametrization) and includes test commands, but the 'Where should the reviewer start' and 'Related Issues' sections lack specific file pointers and issue references.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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

🧹 Nitpick comments (1)
examples/backends/vllm/qwen35/launch.sh (1)

51-51: Avoid fixed fallback ports in a new launch script.

Defaulting to 8000/8081/8082 makes this example fail unnecessarily when another local stack is already up. Prefer reserving ports dynamically when the env vars are unset, then thread the resolved values through the banner and child processes.

Based on learnings, "Flag hard-coded portability-reducing constants in shell/scripts across the repository (e.g., static ports). Prefer portable alternatives available in the repo: use alloc_port for dynamic ports."

Also applies to: 97-97, 113-113

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/backends/vllm/qwen35/launch.sh` at line 51, Replace the hard-coded
fallbacks for HTTP/WS ports with dynamic allocation: when DYN_HTTP_PORT (and the
other env vars used at the other assignments) are unset, call the repository's
alloc_port helper to reserve an available port and assign that to HTTP_PORT (and
the corresponding WS/other port variables), then export these resolved variables
so the banner and the child processes receive the same values; update the
references to DYN_HTTP_PORT/HTTP_PORT (and the other port variables present
later in the script) to use the newly allocated values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/backends/vllm/qwen35/launch.sh`:
- Line 51: The script computes HTTP_PORT but never passes it into the frontend
invocation, so the banner/curl examples can point at the wrong socket; update
each call to dynamo.frontend (the frontend command invocation seen near the
HTTP_PORT assignment around line 51 and the other invocation around lines
121-122) to accept the resolved port by supplying "$HTTP_PORT" (or the
appropriate --port "$HTTP_PORT" flag) as an argument or environment variable so
the actual frontend listens on the same port printed in banners and curl
examples.

In `@tests/mm_router/test_vllm_mm_router_e2e.py`:
- Around line 216-230: The start_vllm_mm_services fixture currently calls
allocate_ports(...) manually and branches on request.param; replace that manual
port allocation by adding num_system_ports and the runtime fixtures
(runtime_services_dynamic_ports and dynamo_dynamic_ports) to the fixture
signature and consume the dynamic port lists they provide; when approx_routing
is True pull three ports from runtime_services_dynamic_ports, otherwise pull
four ports (including an extra kv_event port) by combining
runtime_services_dynamic_ports and dynamo_dynamic_ports as needed, removing
allocate_ports and start_port usage and keeping the rest of the fixture logic
unchanged so xdist-safe dynamic port allocation is used.

---

Nitpick comments:
In `@examples/backends/vllm/qwen35/launch.sh`:
- Line 51: Replace the hard-coded fallbacks for HTTP/WS ports with dynamic
allocation: when DYN_HTTP_PORT (and the other env vars used at the other
assignments) are unset, call the repository's alloc_port helper to reserve an
available port and assign that to HTTP_PORT (and the corresponding WS/other port
variables), then export these resolved variables so the banner and the child
processes receive the same values; update the references to
DYN_HTTP_PORT/HTTP_PORT (and the other port variables present later in the
script) to use the newly allocated values.
🪄 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: Pro

Run ID: 3908be6a-1169-4466-8737-03926bb9ecc0

📥 Commits

Reviewing files that changed from the base of the PR and between e3e728a and e96984b.

📒 Files selected for processing (3)
  • examples/backends/vllm/mm_router_worker/mm_router_worker.py
  • examples/backends/vllm/qwen35/launch.sh
  • tests/mm_router/test_vllm_mm_router_e2e.py


MAX_MODEL_LEN="${MAX_MODEL_LEN:-4096}"
MAX_CONCURRENT_SEQS="${MAX_CONCURRENT_SEQS:-2}"
HTTP_PORT="${DYN_HTTP_PORT:-8000}"

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.

⚠️ Potential issue | 🟠 Major

Pass the resolved frontend port into dynamo.frontend.

HTTP_PORT drives the banner and curl examples, but the frontend command never consumes it. That makes the documented port override path rely on implicit frontend behavior and can leave the printed curl command pointing at the wrong socket.

🔧 Proposed fix
 python -m dynamo.frontend \
+    --http-port "$HTTP_PORT" \
     --router-mode round-robin &

Also applies to: 121-122

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/backends/vllm/qwen35/launch.sh` at line 51, The script computes
HTTP_PORT but never passes it into the frontend invocation, so the banner/curl
examples can point at the wrong socket; update each call to dynamo.frontend (the
frontend command invocation seen near the HTTP_PORT assignment around line 51
and the other invocation around lines 121-122) to accept the resolved port by
supplying "$HTTP_PORT" (or the appropriate --port "$HTTP_PORT" flag) as an
argument or environment variable so the actual frontend listens on the same port
printed in banners and curl examples.

Comment on lines +216 to +230
@pytest.fixture(scope="module", params=[False, True], ids=["exact_kv", "approx_kv"])
def start_vllm_mm_services(
request, mm_runtime_services
) -> Generator[tuple[int, ManagedProcess], None, None]:
frontend_port, vllm_port, router_port, kv_event_port = allocate_ports(
count=4, start_port=10000
)
approx_routing = request.param

if approx_routing:
frontend_port, vllm_port, router_port = allocate_ports(
count=3, start_port=10000
)
kv_event_port = None
else:
frontend_port, vllm_port, router_port, kv_event_port = allocate_ports(
count=4, start_port=10000
)

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.

⚠️ Potential issue | 🟠 Major

Use the repo’s dynamic service/port fixtures here instead of extending the hand-rolled setup.

Adding the exact/approx split on top of manual allocate_ports(..., start_port=10000) keeps this module outside the xdist-safe path the rest of the suite uses. Please request the needed system ports via num_system_ports and consume runtime_services_dynamic_ports + dynamo_dynamic_ports instead of branching port allocation manually here.

As per coding guidelines, "Use runtime_services_dynamic_ports and dynamo_dynamic_ports fixtures together for xdist/parallel safety" and "Use num_system_ports parametrize ... to request multiple system ports."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/mm_router/test_vllm_mm_router_e2e.py` around lines 216 - 230, The
start_vllm_mm_services fixture currently calls allocate_ports(...) manually and
branches on request.param; replace that manual port allocation by adding
num_system_ports and the runtime fixtures (runtime_services_dynamic_ports and
dynamo_dynamic_ports) to the fixture signature and consume the dynamic port
lists they provide; when approx_routing is True pull three ports from
runtime_services_dynamic_ports, otherwise pull four ports (including an extra
kv_event port) by combining runtime_services_dynamic_ports and
dynamo_dynamic_ports as needed, removing allocate_ports and start_port usage and
keeping the rest of the fixture logic unchanged so xdist-safe dynamic port
allocation is used.

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

Thank you

--enable-multimodal \
--mamba-cache-mode align \
--block-size "$BLOCK_SIZE" \
--enforce-eager \

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.

should we leave this out?
for perf reasons, we should not enforce eager by default.
people can pass this as extra_args

@furionw

furionw commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Thanks for working on these! just want to make sure you two are aware of these parallel work and coordinate

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

Labels

backend::vllm Relates to the vllm backend fix size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants