A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 15, 03:30 UTC
[Platform] Add custom default max tokens (#18557)
Signed-off-by: Gabriel Marinho <gmarinho@ibm.com>
Gabriel Marinho committed
Jul 3, 2025 at 23:50 UTC
a4113b035cd4ee90ec02de0658b75d47f0007ede
5 files changed
+59
-60
vllm/entrypoints/openai/protocol.py
+10
-49
@@ -229,7 +229,6 @@ class ChatCompletionRequest(OpenAIBaseModel):
229
logit_bias: Optional[dict[str, float]] = None
230
logprobs: Optional[bool] = False
231
top_logprobs: Optional[int] = 0
232
- # TODO(#9845): remove max_tokens when field is removed from OpenAI API
232
max_tokens: Optional[int] = Field(
233
default=None,
234
deprecated=
@@ -433,23 +432,10 @@ class ChatCompletionRequest(OpenAIBaseModel):
432
}
433
434
def to_beam_search_params(
436
- self,
437
- default_max_tokens: int,
438
- default_sampling_params: Optional[dict] = None
439
- ) -> BeamSearchParams:
440
- # TODO(#9845): remove max_tokens when field is removed from OpenAI API
441
- max_tokens = self.max_completion_tokens or self.max_tokens
435
+ self, max_tokens: int,
436
+ default_sampling_params: dict) -> BeamSearchParams:
437
443
- if default_sampling_params is None:
444
- default_sampling_params = {}
438
n = self.n if self.n is not None else 1
446
-
447
- # Use minimum of context window, user request & server limit.
448
- max_tokens = min(
449
- val for val in (default_max_tokens, max_tokens,
450
- default_sampling_params.get("max_tokens", None))
451
- if val is not None)
452
-
439
if (temperature := self.temperature) is None:
440
temperature = default_sampling_params.get(
441
"temperature", self._DEFAULT_SAMPLING_PARAMS["temperature"])
@@ -465,21 +451,10 @@ class ChatCompletionRequest(OpenAIBaseModel):
451
452
def to_sampling_params(
453
self,
468
- default_max_tokens: int,
454
+ max_tokens: int,
455
logits_processor_pattern: Optional[str],
470
- default_sampling_params: Optional[dict] = None,
456
+ default_sampling_params: dict,
457
) -> SamplingParams:
472
- # TODO(#9845): remove max_tokens when field is removed from OpenAI API
473
- max_tokens = self.max_completion_tokens or self.max_tokens
474
-
475
- if default_sampling_params is None:
476
- default_sampling_params = {}
477
-
478
- # Use minimum of context window, user request & server limit.
479
- max_tokens = min(
480
- val for val in (default_max_tokens, max_tokens,
481
- default_sampling_params.get("max_tokens", None))
482
- if val is not None)
458
459
# Default parameters
460
if (repetition_penalty := self.repetition_penalty) is None:
@@ -898,22 +873,15 @@ class CompletionRequest(OpenAIBaseModel):
873
}
874
875
def to_beam_search_params(
901
- self,
902
- default_max_tokens: int,
903
- default_sampling_params: Optional[dict] = None
876
+ self,
877
+ max_tokens: int,
878
+ default_sampling_params: Optional[dict] = None,
879
) -> BeamSearchParams:
905
- max_tokens = self.max_tokens
880
881
if default_sampling_params is None:
882
default_sampling_params = {}
883
n = self.n if self.n is not None else 1
884
911
- # Use minimum of context window, user request & server limit.
912
- max_tokens = min(
913
- val for val in (default_max_tokens, max_tokens,
914
- default_sampling_params.get("max_tokens", None))
915
- if val is not None)
916
-
885
if (temperature := self.temperature) is None:
886
temperature = default_sampling_params.get("temperature", 1.0)
887
@@ -928,21 +896,14 @@ class CompletionRequest(OpenAIBaseModel):
896
897
def to_sampling_params(
898
self,
931
- default_max_tokens: int,
899
+ max_tokens: int,
900
logits_processor_pattern: Optional[str],
901
default_sampling_params: Optional[dict] = None,
902
) -> SamplingParams:
935
- max_tokens = self.max_tokens
903
904
if default_sampling_params is None:
905
default_sampling_params = {}
906
940
- # Use minimum of context window, user request & server limit.
941
- max_tokens = min(
942
- val for val in (default_max_tokens, max_tokens,
943
- default_sampling_params.get("max_tokens", None))
944
- if val is not None)
945
-
907
# Default parameters
908
if (repetition_penalty := self.repetition_penalty) is None:
909
repetition_penalty = default_sampling_params.get(
@@ -1813,7 +1774,7 @@ class TranscriptionRequest(OpenAIBaseModel):
1774
self,
1775
default_max_tokens: int,
1776
default_sampling_params: Optional[dict] = None) -> SamplingParams:
1816
- # TODO(#9845): remove max_tokens when field is removed from OpenAI API
1777
+
1778
max_tokens = default_max_tokens
1779
1780
if default_sampling_params is None:
@@ -2029,7 +1990,7 @@ class TranslationRequest(OpenAIBaseModel):
1990
self,
1991
default_max_tokens: int,
1992
default_sampling_params: Optional[dict] = None) -> SamplingParams:
2032
- # TODO(#9845): remove max_tokens when field is removed from OpenAI API
1993
+
1994
max_tokens = default_max_tokens
1995
1996
if default_sampling_params is None:
vllm/entrypoints/openai/serving_chat.py
+13
-5
@@ -34,6 +34,7 @@ from vllm.entrypoints.openai.serving_models import OpenAIServingModels
34
from vllm.entrypoints.openai.tool_parsers import ToolParser, ToolParserManager
35
from vllm.entrypoints.openai.tool_parsers.mistral_tool_parser import (
36
MistralToolCall)
37
+from vllm.entrypoints.utils import get_max_tokens
38
from vllm.logger import init_logger
39
from vllm.outputs import CompletionOutput, RequestOutput
40
from vllm.reasoning import ReasoningParser, ReasoningParserManager
@@ -233,15 +234,22 @@ class OpenAIServingChat(OpenAIServing):
234
try:
235
for i, engine_prompt in enumerate(engine_prompts):
236
sampling_params: Union[SamplingParams, BeamSearchParams]
236
- default_max_tokens = self.max_model_len - len(
237
- engine_prompt["prompt_token_ids"])
237
+
238
+ if self.default_sampling_params is None:
239
+ self.default_sampling_params = {}
240
+
241
+ max_tokens = get_max_tokens(
242
+ max_model_len=self.max_model_len,
243
+ request=request,
244
+ input_length=len(engine_prompt["prompt_token_ids"]),
245
+ default_sampling_params=self.default_sampling_params)
246
+
247
if request.use_beam_search:
248
sampling_params = request.to_beam_search_params(
240
- default_max_tokens, self.default_sampling_params)
249
+ max_tokens, self.default_sampling_params)
250
else:
251
sampling_params = request.to_sampling_params(
243
- default_max_tokens,
244
- self.model_config.logits_processor_pattern,
252
+ max_tokens, self.model_config.logits_processor_pattern,
253
self.default_sampling_params)
254
255
self._log_inputs(request_id,
vllm/entrypoints/openai/serving_completion.py
+12
-4
@@ -33,6 +33,7 @@ from vllm.entrypoints.openai.serving_engine import (OpenAIServing,
33
is_text_tokens_prompt)
34
# yapf: enable
35
from vllm.entrypoints.openai.serving_models import OpenAIServingModels
36
+from vllm.entrypoints.utils import get_max_tokens
37
from vllm.inputs.data import (EmbedsPrompt, TokensPrompt, is_embeds_prompt,
38
is_tokens_prompt)
39
from vllm.logger import init_logger
@@ -160,15 +161,22 @@ class OpenAIServingCompletion(OpenAIServing):
161
input_length = len(engine_prompt["prompt_token_ids"])
162
else:
163
assert_never(engine_prompt)
163
- default_max_tokens = self.max_model_len - input_length
164
+
165
+ if self.default_sampling_params is None:
166
+ self.default_sampling_params = {}
167
+
168
+ max_tokens = get_max_tokens(
169
+ max_model_len=self.max_model_len,
170
+ request=request,
171
+ input_length=input_length,
172
+ default_sampling_params=self.default_sampling_params)
173
174
if request.use_beam_search:
175
sampling_params = request.to_beam_search_params(
167
- default_max_tokens, self.default_sampling_params)
176
+ max_tokens, self.default_sampling_params)
177
else:
178
sampling_params = request.to_sampling_params(
170
- default_max_tokens,
171
- self.model_config.logits_processor_pattern,
179
+ max_tokens, self.model_config.logits_processor_pattern,
180
self.default_sampling_params)
181
182
request_id_item = f"{request_id}-{i}"
vllm/entrypoints/utils.py
+20
-2
@@ -5,13 +5,17 @@ import argparse
5
import asyncio
6
import functools
7
import os
8
-from typing import Any, Optional
8
+import sys
9
+from typing import Any, Optional, Union
10
11
from fastapi import Request
12
from fastapi.responses import JSONResponse, StreamingResponse
13
from starlette.background import BackgroundTask, BackgroundTasks
14
15
+from vllm.entrypoints.openai.protocol import (ChatCompletionRequest,
16
+ CompletionRequest)
17
from vllm.logger import init_logger
18
+from vllm.platforms import current_platform
19
20
logger = init_logger(__name__)
21
@@ -181,7 +185,6 @@ def _validate_truncation_size(
185
186
def show_filtered_argument_or_group_from_help(parser: argparse.ArgumentParser,
187
subcommand_name: list[str]):
184
- import sys
188
189
# Only handle --help=<keyword> for the current subcommand.
190
# Since subparser_init() runs for all subcommands during CLI setup,
@@ -242,3 +245,18 @@ def show_filtered_argument_or_group_from_help(parser: argparse.ArgumentParser,
245
print(f"\nNo group or parameter matching '{search_keyword}'")
246
print("Tip: use `--help=listgroup` to view all groups.")
247
sys.exit(1)
248
+
249
+
250
+def get_max_tokens(max_model_len: int, request: Union[ChatCompletionRequest,
251
+ CompletionRequest],
252
+ input_length: int, default_sampling_params: dict) -> int:
253
+
254
+ max_tokens = getattr(request, "max_completion_tokens",
255
+ None) or request.max_tokens
256
+ default_max_tokens = max_model_len - input_length
257
+ max_output_tokens = current_platform.get_max_output_tokens(input_length)
258
+
259
+ return min(val
260
+ for val in (default_max_tokens, max_tokens, max_output_tokens,
261
+ default_sampling_params.get("max_tokens"))
262
+ if val is not None)
vllm/platforms/interface.py
+4
@@ -4,6 +4,7 @@ import enum
4
import os
5
import platform
6
import random
7
+import sys
8
from datetime import timedelta
9
from platform import uname
10
from typing import TYPE_CHECKING, NamedTuple, Optional, Union
@@ -164,6 +165,9 @@ class Platform:
165
def is_out_of_tree(self) -> bool:
166
return self._enum == PlatformEnum.OOT
167
168
+ def get_max_output_tokens(self, prompt_len: int) -> int:
169
+ return sys.maxsize
170
+
171
def is_cuda_alike(self) -> bool:
172
"""Stateless version of [torch.cuda.is_available][]."""
173
return self._enum in (PlatformEnum.CUDA, PlatformEnum.ROCM)