Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 9 additions & 1 deletion backend/python/sglang/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@


_ONE_DAY_IN_SECONDS = 60 * 60 * 24

# proto3 has no field presence, so an explicit 0 is indistinguishable from
# "unset" and the zero-filter below would drop it. These two fields have a
# meaningful zero a caller can actually intend: temperature 0 is greedy
# decoding, and 0 is a valid seed. Silently substituting a default for either
# turns a reproducible request into a random one.
_EXPLICIT_ZERO_FIELDS = ("Temperature", "Seed")

MAX_WORKERS = int(os.environ.get('PYTHON_GRPC_MAX_WORKERS', '1'))


Expand Down Expand Up @@ -323,7 +331,7 @@ def _build_sampling_params(self, request) -> dict:
if not hasattr(request, proto_field):
continue
value = getattr(request, proto_field)
if proto_field != "Temperature" and value in (None, 0, 0.0, [], False, ""):
if proto_field not in _EXPLICIT_ZERO_FIELDS and value in (None, 0, 0.0, [], False, ""):
continue
# repeated fields come back as RepeatedScalarContainer — convert
if hasattr(value, "__iter__") and not isinstance(value, (str, bytes)):
Expand Down
13 changes: 10 additions & 3 deletions backend/python/sglang/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,14 @@ def kwargs_for(metadata):
self.assertNotIn("enable_thinking", kwargs_for({}))
self.assertIs(kwargs_for({"enable_thinking": "FALSE"})["enable_thinking"], False)

def test_explicit_zero_temperature_is_preserved(self):
"""Temperature=0 is valid greedy decoding, not an unset value."""
def test_explicit_zero_temperature_and_seed_are_preserved(self):
"""Temperature=0 is greedy decoding and 0 is a valid seed — neither is
an unset value. A dropped seed turns a reproducible request random."""
from types import SimpleNamespace

servicer = self._servicer()
import sys as _sys
_SEED_KEY_FOR_TEST = _sys.modules["backend"]._SEED_KEY
request = SimpleNamespace(
Temperature=0,
N=0,
Expand All @@ -154,8 +157,12 @@ def test_explicit_zero_temperature_is_preserved(self):

params = servicer._build_sampling_params(request)
self.assertEqual(params["temperature"], 0)
# Other protobuf-default scalar fields must remain filtered.
self.assertEqual(params[_SEED_KEY_FOR_TEST], 0)
# Other protobuf-default scalar fields must remain filtered. top_k=0 in
# particular is not a value sglang accepts (-1 disables it), so it must
# keep falling through to the engine default.
self.assertNotIn("top_p", params)
self.assertNotIn("top_k", params)


if __name__ == "__main__":
Expand Down
10 changes: 9 additions & 1 deletion backend/python/vllm/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@

_ONE_DAY_IN_SECONDS = 60 * 60 * 24

# proto3 has no field presence, so an explicit 0 is indistinguishable from
# "unset". These two fields have a meaningful zero a caller can intend:
# temperature 0 is greedy decoding, and 0 is a valid seed.
_EXPLICIT_ZERO_FIELDS = ("Temperature", "Seed")


# If MAX_WORKERS are specified in the environment use it, otherwise default to 1
MAX_WORKERS = int(os.environ.get('PYTHON_GRPC_MAX_WORKERS', '1'))

Expand Down Expand Up @@ -553,7 +559,9 @@ def _build_sampling_params(self, request):
for request_field, param_field in request_to_sampling_params.items():
if hasattr(request, request_field):
value = getattr(request, request_field)
if request_field == "Temperature" or value not in (None, 0, [], False):
# See _EXPLICIT_ZERO_FIELDS: temperature 0 is greedy decoding
# and 0 is a valid seed, so neither may be filtered out.
if request_field in _EXPLICIT_ZERO_FIELDS or value not in (None, 0, [], False):
setattr(sampling_params, param_field, value)

return sampling_params
Expand Down
8 changes: 5 additions & 3 deletions backend/python/vllm/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,18 @@ def test_sampling_params(self):
finally:
self.tearDown()

def test_explicit_zero_temperature_is_preserved(self):
"""Temperature=0 is valid greedy decoding, not an unset value."""
def test_explicit_zero_temperature_and_seed_are_preserved(self):
"""Temperature=0 is greedy decoding and 0 is a valid seed — neither is
an unset value. A dropped seed turns a reproducible request random."""
import sys, os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from backend import BackendServicer

servicer = BackendServicer()
request = backend_pb2.PredictOptions(Prompt="hello", Temperature=0)
request = backend_pb2.PredictOptions(Prompt="hello", Temperature=0, Seed=0)
sampling_params = servicer._build_sampling_params(request)
self.assertEqual(sampling_params.temperature, 0)
self.assertEqual(sampling_params.seed, 0)
# Other protobuf-default scalar fields must remain filtered.
self.assertEqual(sampling_params.top_p, 0.9)

Expand Down