From 3ee2df30337a301164c46ae444b76ee67e71c106 Mon Sep 17 00:00:00 2001 From: Vinay R Damodaran Date: Tue, 11 Aug 2026 21:48:58 -0700 Subject: [PATCH] [Frontend] Make `model` optional on all `/derender` request classes (#51463) Signed-off-by: Vinay Damodaran Co-authored-by: Claude Opus 5 (1M context) --- .../scale_out/derender/test_derender.py | 19 ++++++++++++++++++ .../entrypoints/scale_out/derender/serving.py | 20 +++++++++++-------- .../scale_out/token_in_token_out/protocol.py | 12 +++++------ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/tests/entrypoints/scale_out/derender/test_derender.py b/tests/entrypoints/scale_out/derender/test_derender.py index 3167e00b96..a30e487450 100644 --- a/tests/entrypoints/scale_out/derender/test_derender.py +++ b/tests/entrypoints/scale_out/derender/test_derender.py @@ -308,6 +308,25 @@ async def test_derender_chat_unknown_model(client): assert response.status_code == 404 +@pytest.mark.asyncio +async def test_derender_chat_model_omitted_resolves_served_name(client): + """Omitting `model` resolves the served name rather than rejecting. + + Mirrors test_serving_chat.py's "full name is returned when no model is + specified" assertion for the derender path. Asserts the resolved value, + not just the status, so the fallback is proven to have fired. + """ + gen_req = await _render_chat(client) + synthetic_ids = gen_req["token_ids"][:3] + + response = await client.post( + "/v1/chat/completions/derender", + json={"generate_response": _make_generate_response(synthetic_ids)}, + ) + assert response.status_code == 200 + assert response.json()["model"] == MODEL_NAME + + # --------------------------------------------------------------------------- # Completion derender tests # --------------------------------------------------------------------------- diff --git a/vllm/entrypoints/scale_out/derender/serving.py b/vllm/entrypoints/scale_out/derender/serving.py index 4b72ce2e9f..d9e0919c00 100644 --- a/vllm/entrypoints/scale_out/derender/serving.py +++ b/vllm/entrypoints/scale_out/derender/serving.py @@ -166,16 +166,17 @@ class ServingDerender(BaseServing): total_tokens=prompt_tokens + completion_tokens, ) + model_name = request.model or self.models.model_name() logger.debug( "derender_chat request_id=%s model=%s choices=%d completion_tokens=%d", gen.request_id, - request.model, + model_name, len(choices), completion_tokens, ) return ChatCompletionResponse( id=gen.request_id, - model=request.model, + model=model_name, created=int(time.time()), choices=choices, usage=usage, @@ -231,17 +232,18 @@ class ServingDerender(BaseServing): total_tokens=total_prompt_tokens + total_completion_tokens, ) + model_name = request.model or self.models.model_name() logger.debug( "derender_completion request_id=%s model=%s choices=%d" " completion_tokens=%d", first.request_id, - request.model, + model_name, len(choices), total_completion_tokens, ) return CompletionResponse( id=first.request_id, - model=request.model, + model=model_name, created=int(time.time()), choices=choices, usage=usage, @@ -264,9 +266,10 @@ class ServingDerender(BaseServing): if error_check_ret is not None: return error_check_ret + model_name = request.model or self.models.model_name() try: chunk, updated_state = await self.online_derenderer.derender_chat_stream( - model=request.model, + model=model_name, generate_chunk=request.generate_chunk, state=request.stream_state, chat_request=request.chat_request, @@ -284,7 +287,7 @@ class ServingDerender(BaseServing): logger.debug( "derender_chat_stream request_id=%s model=%s delta_tokens=%d", request.generate_chunk.request_id, - request.model, + model_name, sum( len(c.token_ids) for c in request.generate_chunk.choices if c.token_ids ), @@ -304,12 +307,13 @@ class ServingDerender(BaseServing): if error_check_ret is not None: return error_check_ret + model_name = request.model or self.models.model_name() try: ( chunk, updated_state, ) = await self.online_derenderer.derender_completion_stream( - model=request.model, + model=model_name, generate_chunk=request.generate_chunk, state=request.stream_state, prompt_tokens=request.prompt_tokens, @@ -325,7 +329,7 @@ class ServingDerender(BaseServing): logger.debug( "derender_completion_stream request_id=%s model=%s delta_tokens=%d", request.generate_chunk.request_id, - request.model, + model_name, sum( len(c.token_ids) for c in request.generate_chunk.choices if c.token_ids ), diff --git a/vllm/entrypoints/scale_out/token_in_token_out/protocol.py b/vllm/entrypoints/scale_out/token_in_token_out/protocol.py index 606989c31d..1db05282ba 100644 --- a/vllm/entrypoints/scale_out/token_in_token_out/protocol.py +++ b/vllm/entrypoints/scale_out/token_in_token_out/protocol.py @@ -277,8 +277,8 @@ class DerenderChatRequest(BaseModel): # --8<-- [start:derender-chat-request] stream: Literal[False] = False - model: str - """Served model name.""" + model: str | None = None + """Served model name. Defaults to the server's served model name.""" generate_response: GenerateResponse """The complete token-in / token-out engine response to derender.""" @@ -311,8 +311,8 @@ class DerenderCompletionRequest(BaseModel): # --8<-- [start:derender-completion-request] stream: Literal[False] = False - model: str - """Served model name.""" + model: str | None = None + """Served model name. Defaults to the server's served model name.""" generate_responses: list[GenerateResponse] """One response per prompt, parallel to the list[GenerateRequest] @@ -428,7 +428,7 @@ class DerenderChatStreamRequest(BaseModel): stream: Literal[True] - model: str + model: str | None = None generate_chunk: GenerateStreamResponse """One SSE chunk from ``/inference/v1/generate`` (``stream=True``).""" @@ -452,7 +452,7 @@ class DerenderCompletionStreamRequest(BaseModel): stream: Literal[True] - model: str + model: str | None = None generate_chunk: GenerateStreamResponse """One SSE chunk from ``/inference/v1/generate``."""