Repository navigation
feat(frontend): direct mode for stock vLLM gRPC engines - #100
ishandhanani wants to merge 3 commits into
Conversation
Live validation: vLLM 0.28.0 (
|
| request | TTFT | mean ITL |
|---|---|---|
| 0 | 133.7 ms | 16.84 ms |
| 1 | 118.0 ms | 16.79 ms |
| 2 | 121.2 ms | 16.69 ms |
ITL reflects this vLLM build (FlashInfer sampler disabled because the host CUDA toolkit does not match the wheel), not the routing path; the SGLang run on the same GPUs in #99 saw ~1.4 ms.
No sidecar, etcd or NATS ran at any point; the frontend used --discovery-backend mem.
Split LLMEngine::generate into prepare_generate (validation and wire translation) and open_and_consume (stream open and response translation) so the sidecar and the frontend's direct dispatcher share one wire contract. The dispatcher sends Control.Abort on cancellation itself, keeping the decode-leg deferral until the KV transfer completes, since no backend-common adapter runs on the direct path. The direct module's probe runs the sidecar's Control discovery and GetKvEventSources against one vllm-rs server and produces what the sidecar would have registered, including the ZMQ KV-event and replay endpoints. VllmDirectDispatch implements DirectBackend and StreamingDispatch with one lazily connected channel pool per instance. vLLM's ServerInfo carries no disaggregation role, so the operator's prefill list decides it. The card's parser fields stay empty: vLLM names its parsers differently from Dynamo (qwen3_xml where Dynamo has qwen3) and the vLLM sidecar likewise takes Dynamo's parsers from the operator, never from the engine. Signed-off-by: Ishan Dhanani <ishandhanani@gmail.com>
The bindings probe vLLM engines through the shared DirectFleet when --direct-backend is vllm. The engine's own parser names are not Dynamo's, so --dyn-tool-call-parser and --dyn-reasoning-parser are how a vLLM deployment gets tool and reasoning parsing. Signed-off-by: Ishan Dhanani <ishandhanani@gmail.com>
The direct integration test is generic over the mocker fixture and runs the round-robin, KV-routing and prefill/decode scenarios for both SGLang and vLLM; the vLLM handoff has no bootstrap rendezvous, so prefill completes before decode starts. The vLLM fixture honors the KV-event port. Docs cover the vLLM recipe, the parser flags and the sidecar-only operations surface. Signed-off-by: Ishan Dhanani <ishandhanani@gmail.com>
088f297 to
64c03ca
Compare
2b63548 to
23b17a0
Compare
Stacked on #99 (SGLang backend), which stacks on #102 (infrastructure). Only the last commits are this PR's.
Summary
Adds vLLM to the frontend's direct mode:
python -m dynamo.frontend --direct --direct-backend vllm --engine-url http://host:30001 ...routes to stockvllm-rs serve --grpc-portservers over their native gRPC API with no sidecar.dynamo-vllm-sidecar::direct: probe over the existingVllmClientdiscovery (GetModelInfo,GetServerInfo,GetKvEventSources, including the replay socket) and aVllmDirectDispatchwhose stream body is shared withLLMEngine::generatethroughprepare_generate/open_and_consume. On the direct path the dispatcher sendsControl.Aborton cancellation itself, keeping the decode-leg deferral until the KV transfer completes.ServerInfohas no such field), so roles come from the operator:--prefill-engine-urllists prefill engines,--engine-urlthe rest.--dyn-*flags: vLLM names its parsers differently from Dynamo (qwen3_xmlwhere Dynamo hasqwen3), so the probe leaves the card's parser fields empty and reports the engine's names in its probe log. Found live: the first start against a stock vLLM engine failed the card's parser check onqwen3_xml.--direct-backend vllm; the direct integration tests run for both engine families; docs cover the vLLM recipe and the operations surface that still needs the sidecar (dynamic LoRA, RL controls, encode role).Validation
cargo clippy -D warnings --testsclean ondynamo-sidecar-common,dynamo-sglang-sidecar,dynamo-vllm-sidecar,dynamo-llm,dynamo-sidecar-testkit; bindingscargo check;cargo fmt --check; pre-commit clean.dynamo-vllm-sidecar133 unit tests (one new: the probed card leaves parsers to the operator).direct_mocker_integration.rs6/6, the three scenarios for both the SGLang and vLLM mockers.test_frontend_direct_args.py6/6.Live vLLM 0.28.0 (
vllm-rs) on 2x H100: aggregated with KV routing and disaggregated over NIXL, see the comment below (recorded on the pre-split branch; the code is the same).