[Rust Frontend] Keep `--max-model-len` engine-owned (#49944)
Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Bugen Zhao committed
Jul 27, 2026 at 14:50 UTC
fd9d2ede6fa05313e4a7482c5edb88bf8c565230
3 files changed
+63
-17
rust/src/cmd/src/cli.rs
-6
@@ -148,11 +148,6 @@ pub struct SharedRuntimeArgs {
148
#[arg(long)]
149
#[serde(default)]
150
pub language_model_only: bool,
151
- /// Override the maximum model context length. When set, the frontend uses
152
- /// this value instead of the model's `max_position_embeddings` from
153
- /// `config.json`.
154
- #[arg(long)]
155
- pub max_model_len: Option<u32>,
151
/// Maximum number of log probabilities to return when `logprobs` is
152
/// specified in sampling parameters. `-1` means no cap.
153
#[arg(long, value_parser = clap::value_parser!(i32).range(-1..), allow_negative_numbers = true)]
@@ -664,7 +659,6 @@ impl ServeArgs {
659
660
self.managed_engine.clone().into_config(
661
self.runtime.model.clone(),
667
- self.runtime.max_model_len,
662
self.runtime.max_logprobs,
663
profiler_config,
664
reasoning_parser.as_deref(),
rust/src/cmd/src/cli/tests.rs
+55
-8
@@ -58,9 +58,6 @@ fn serve_args_forward_python_flags_with_separator() {
58
reasoning_parser: Auto,
59
renderer: Auto,
60
language_model_only: false,
61
- max_model_len: Some(
62
- 512,
63
- ),
61
max_logprobs: None,
62
grpc_port: None,
63
shutdown_timeout: 0,
@@ -102,6 +99,9 @@ fn serve_args_forward_python_flags_with_separator() {
99
handshake_port: None,
100
data_parallel_size: 1,
101
data_parallel_size_local: None,
102
+ max_model_len: Some(
103
+ "512",
104
+ ),
105
python_args: [
106
"--dtype",
107
"float16",
@@ -756,7 +756,6 @@ fn frontend_args_accept_json() {
756
reasoning_parser: None,
757
renderer: Auto,
758
language_model_only: false,
759
- max_model_len: None,
759
max_logprobs: None,
760
grpc_port: None,
761
shutdown_timeout: 0,
@@ -823,11 +822,32 @@ fn frontend_args_json_applies_defaults() {
822
assert_eq!(args.runtime.tool_call_parser, ParserSelection::None);
823
assert_eq!(args.runtime.reasoning_parser, ParserSelection::None);
824
assert_eq!(args.runtime.renderer, RendererSelection::Auto);
826
- assert_eq!(args.runtime.max_model_len, None);
825
assert_eq!(args.runtime.max_logprobs, None);
826
assert_eq!(args.runtime.shutdown_timeout, 0);
827
}
828
829
+#[test]
830
+fn frontend_args_json_ignores_engine_owned_max_model_len() {
831
+ let cli = Cli::try_parse_from([
832
+ "vllm-rs",
833
+ "frontend",
834
+ "--listen-fd",
835
+ "3",
836
+ "--input-address",
837
+ "ipc:///tmp/input.sock",
838
+ "--output-address",
839
+ "ipc:///tmp/output.sock",
840
+ "--args-json",
841
+ r#"{"model_tag":"Qwen/Qwen3-0.6B","max_model_len":-1}"#,
842
+ ])
843
+ .unwrap();
844
+
845
+ let Command::Frontend(args) = cli.command else {
846
+ panic!("expected frontend args");
847
+ };
848
+ assert_eq!(args.runtime.model, "Qwen/Qwen3-0.6B");
849
+}
850
+
851
#[test]
852
fn frontend_args_json_accepts_supported_non_default_fields() {
853
let cli = Cli::try_parse_from([
@@ -840,7 +860,7 @@ fn frontend_args_json_accepts_supported_non_default_fields() {
860
"--output-address",
861
"ipc:///tmp/output.sock",
862
"--args-json",
843
- r#"{"model_tag":"Qwen/Qwen3-0.6B","engine_ready_timeout_secs":42,"tool_call_parser":"hermes","reasoning_parser":"qwen3_thinking","tokenizer_mode":"deepseek_v32","language_model_only":true,"max_model_len":8192,"max_logprobs":-1,"shutdown_timeout":3}"#,
863
+ r#"{"model_tag":"Qwen/Qwen3-0.6B","engine_ready_timeout_secs":42,"tool_call_parser":"hermes","reasoning_parser":"qwen3_thinking","tokenizer_mode":"deepseek_v32","language_model_only":true,"max_logprobs":-1,"shutdown_timeout":3}"#,
864
])
865
.unwrap();
866
@@ -858,11 +878,38 @@ fn frontend_args_json_accepts_supported_non_default_fields() {
878
);
879
assert_eq!(args.runtime.renderer, RendererSelection::DeepSeekV32);
880
assert!(args.runtime.language_model_only);
861
- assert_eq!(args.runtime.max_model_len, Some(8192));
881
assert_eq!(args.runtime.max_logprobs, Some(-1));
882
assert_eq!(args.runtime.shutdown_timeout, 3);
883
}
884
885
+#[test]
886
+fn serve_args_forward_auto_max_model_len_to_managed_engine() {
887
+ let cli = Cli::try_parse_from([
888
+ "vllm-rs",
889
+ "serve",
890
+ "Qwen/Qwen3-0.6B",
891
+ "--max-model-len",
892
+ "auto",
893
+ ])
894
+ .unwrap();
895
+
896
+ let Command::Serve(args) = cli.command else {
897
+ panic!("expected serve args");
898
+ };
899
+ assert_eq!(args.managed_engine.max_model_len.as_deref(), Some("auto"));
900
+
901
+ let config = args.to_managed_engine_config(5555);
902
+ expect![[r#"
903
+ [
904
+ "--max-model-len",
905
+ "auto",
906
+ "--reasoning-parser",
907
+ "qwen3",
908
+ ]
909
+ "#]]
910
+ .assert_debug_eq(&config.python_args);
911
+}
912
+
913
#[test]
914
fn serve_args_accept_none_reasoning_parser() {
915
let cli = Cli::try_parse_from([
@@ -1278,7 +1325,6 @@ fn serve_args_accept_handshake_aliases() {
1325
reasoning_parser: Auto,
1326
renderer: Auto,
1327
language_model_only: false,
1281
- max_model_len: None,
1328
max_logprobs: None,
1329
grpc_port: None,
1330
shutdown_timeout: 0,
@@ -1322,6 +1368,7 @@ fn serve_args_accept_handshake_aliases() {
1368
),
1369
data_parallel_size: 4,
1370
data_parallel_size_local: None,
1371
+ max_model_len: None,
1372
python_args: [],
1373
},
1374
},
rust/src/managed-engine/src/cli.rs
+8
-3
@@ -39,6 +39,12 @@ pub struct ManagedEngineArgs {
39
/// Number of data parallel replicas to run on this node.
40
#[arg(long)]
41
pub data_parallel_size_local: Option<usize>,
42
+ /// Maximum model context length forwarded to the managed Python engine.
43
+ ///
44
+ /// Rust leaves validation to Python so values such as `auto` and
45
+ /// human-readable integers retain their engine-owned semantics.
46
+ #[arg(long)]
47
+ pub max_model_len: Option<String>,
48
49
/// Additional arguments forwarded to `python -m vllm.entrypoints.cli.main
50
/// serve ...`.
@@ -78,7 +84,6 @@ impl ManagedEngineArgs {
84
pub fn into_config(
85
self,
86
model: String,
81
- max_model_len: Option<u32>,
87
max_logprobs: Option<i32>,
88
profiler_config: Option<String>,
89
reasoning_parser: Option<&str>,
@@ -89,9 +94,9 @@ impl ManagedEngineArgs {
94
) -> ManagedEngineConfig {
95
let mut python_args = self.python_args;
96
// Manually forward some args to the Python engine.
92
- if let Some(max_model_len) = max_model_len {
97
+ if let Some(max_model_len) = self.max_model_len {
98
python_args.push("--max-model-len".to_string());
94
- python_args.push(max_model_len.to_string());
99
+ python_args.push(max_model_len);
100
}
101
if let Some(max_logprobs) = max_logprobs {
102
python_args.push("--max-logprobs".to_string());