Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions components/src/dynamo/vllm/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,19 @@ def build_sampling_params(
if value is not None and hasattr(sampling_params, key):
setattr(sampling_params, key, value)

# routed_experts_prompt_start (RL capture offset) rides nvext, not the
# standard sampling_options (Dynamo's chat schema rejects unknown top-level
# fields). Apply it onto SamplingParams so vLLM trims the leading prompt rows
# from the returned routing engine-side (instead of the client trimming the
# full-sequence blob after it crosses the wire).
for source in _iter_nvext_sources(request):
reps_nvext = source.get("routed_experts_prompt_start")
if reps_nvext is not None and hasattr(
sampling_params, "routed_experts_prompt_start"
):
sampling_params.routed_experts_prompt_start = reps_nvext
break

# routed_experts_prompt_start (RL capture offset) must be a non-negative
# int; reject bad client values so the worker emits a sane `start` instead
# of a bogus offset the consumer cannot align (vLLM clamps the upper bound).
Expand Down
27 changes: 27 additions & 0 deletions components/src/dynamo/vllm/tests/test_vllm_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,33 @@ def test_build_sampling_params_maps_max_thinking_tokens():
assert sp.thinking_token_budget == 1024


def test_build_sampling_params_applies_nvext_routed_experts_prompt_start():
"""routed_experts_prompt_start rides nvext (not sampling_options) and is
applied onto SamplingParams so vLLM trims routing engine-side."""
import pytest
Comment thread
biswapanda marked this conversation as resolved.
Outdated
from vllm.sampling_params import SamplingParams

from dynamo.vllm.handlers import build_sampling_params
Comment thread
biswapanda marked this conversation as resolved.
Outdated

if not hasattr(SamplingParams(), "routed_experts_prompt_start"):
pytest.skip("installed vLLM has no routed_experts_prompt_start support")

request = {
"token_ids": [1, 2, 3],
"sampling_options": {},
"stop_conditions": {},
"output_options": {},
"nvext": {"routed_experts_prompt_start": 4},
}
sp = build_sampling_params(request, default_sampling_params={})
assert sp.routed_experts_prompt_start == 4

# negative / bad values are clamped to 0
request["nvext"]["routed_experts_prompt_start"] = -1
sp = build_sampling_params(request, default_sampling_params={})
assert sp.routed_experts_prompt_start == 0


def _make_dynamo_config(**overrides):
"""Build a minimal fake DynamoConfig for update_engine_config_with_dynamo tests."""
defaults = {
Expand Down
6 changes: 6 additions & 0 deletions lib/llm/src/preprocessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,12 @@ impl OpenAIPreprocessor {
if nvext.token_data.is_some() {
nvext_passthrough.insert("token_in".to_string(), serde_json::Value::Bool(true));
}
if let Some(start) = nvext.routed_experts_prompt_start {
nvext_passthrough.insert(
"routed_experts_prompt_start".to_string(),
serde_json::json!(start),
);
}
}

if !nvext_passthrough.contains_key("cache_salt")
Expand Down
11 changes: 11 additions & 0 deletions lib/llm/src/protocols/openai/nvext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,17 @@ pub struct NvExt {
#[builder(default, setter(strip_option))]
pub cache_salt: Option<String>,

/// RL routed-experts capture offset (MoE expert replay).
///
/// When set, Dynamo forwards this to the backend's
/// `SamplingParams.routed_experts_prompt_start` so the engine trims the
/// leading prompt rows from the returned routing tensor (rather than the
/// client trimming after the full-sequence blob crosses the wire). Backends
/// without routed-experts capture ignore it.
#[serde(default, skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub routed_experts_prompt_start: Option<u32>,

/// Extra fields to be included in the response's nvext
/// This is a list of field names that should be populated in the response
/// Supported fields include "worker_id", "timing", "routed_experts", "engine_data",
Expand Down
Loading