Skip to content

[Frontend] Add /v1/responses/render endpoint and refactor responses preprocessing - #38084

Closed
hyeongyun0916 wants to merge 4 commits into
vllm-project:mainfrom
moreh-dev:add-responses-render-endpoint
Closed

hyeongyun0916 wants to merge 4 commits into
vllm-project:mainfrom
moreh-dev:add-responses-render-endpoint

Conversation

@hyeongyun0916

@hyeongyun0916 hyeongyun0916 commented Mar 25, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Add a /v1/responses/render endpoint for the Responses API, following the same pattern as the existing /v1/chat/completions/render and /v1/completions/render endpoints.

This refactors the preprocessing logic out of OpenAIServingResponses into OpenAIServingRender, enabling:

  • GPU-less render servers to preprocess Responses API requests
  • Consistent architecture across all three API types (completion, chat, responses)

Changes

  • vllm/entrypoints/serve/render/serving.py: Add render_responses(), render_responses_request(), and move Harmony-related methods (_make_responses_request_with_harmony, _construct_responses_input_with_harmony, _construct_responses_harmony_system_message, _extract_responses_system_message) from OpenAIServingResponses
  • vllm/entrypoints/openai/responses/serving.py: Add render_responses_request() (thin wrapper with engine-aware checks), refactor create_responses() to delegate to it, remove moved methods, share stores via OpenAIServingRender
  • vllm/entrypoints/serve/render/api_router.py: Add POST /v1/responses/render endpoint
  • vllm/entrypoints/openai/generate/api_router.py: Share tool_server with OpenAIServingRender

Test Plan

# Unit tests (no GPU required)
pytest tests/entrypoints/openai/responses/test_serving_responses.py -v
pytest tests/entrypoints/openai/responses/test_responses_utils.py -v
pytest tests/entrypoints/openai/responses/test_protocol.py -v
pytest tests/entrypoints/openai/responses/test_sampling_params.py -v
pytest tests/entrypoints/openai/responses/test_errors.py -v
pytest tests/entrypoints/openai/responses/test_function_call_parsing.py -v

# New render endpoint tests (GPU-less render server)
pytest tests/entrypoints/serve/render/test_render.py -v -k "responses"

Essential Elements of an Effective PR Description Checklist
  • The purpose of the PR, such as "Fix some issue (link existing issues this PR will resolve)".
  • The test plan, such as providing test command.
  • The test results, such as pasting the results comparison before and after, or e2e results
  • (Optional) The necessary documentation update, such as updating supported_models.md and examples for a new model.
  • (Optional) Release notes update. If your change is user facing, please update the release notes draft in the Google Doc.

Signed-off-by: HyunKyun Moon <mhg5303@gmail.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

# FIXME: If enable_store=True, this may cause a memory leak since we
# never remove messages from the store.
self.msg_store: dict[str, list[ChatCompletionMessageParam]] = {}
# Stores are managed by OpenAIServingRender so that

@DarkLight1337 DarkLight1337 Mar 25, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO renderer shouldn't be in charge of dealing with state. Let's keep that part specific to Responses API. Otherwise I'm worried this will interfere with the ongoing effort to move the stateful part out of vLLM (see #feat-responses on Slack).

cc @qandrew @chaunceyjiang

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve incorporated your feedback in commit 13c8510

@mergify

mergify Bot commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @hyeongyun0916.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Mar 25, 2026
…ses and messages

Signed-off-by: HyunKyun Moon <mhg5303@gmail.com>
…onses-render-endpoint

Signed-off-by: HyunKyun Moon <mhg5303@gmail.com>
@mergify mergify Bot removed the needs-rebase label Mar 26, 2026
…etter type safety

Signed-off-by: HyunKyun Moon <mhg5303@gmail.com>
@mergify

mergify Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @hyeongyun0916.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label May 23, 2026
@franciscojavierarceo

Copy link
Copy Markdown
Contributor

thanks for working on this. we’ve been prototyping this boundary in [vllm-agentic-api](https://github.com/vllm-project/agentic-api), where HTTP and WebSocket Responses requests go through the same stateful executor. previous_response_id is rehydrated at the gateway, inherited tools and tool choice are resolved, and the ID is cleared before forwarding a self-contained request to vLLM.

we also prototyped token-in/token-out generation and prompt-cache replay in a local vLLM branch. the useful lesson was that vLLM should own deterministic rendering and token identity, while durable Responses state should remain outside the renderer.

with that model, I think /v1/responses/render needs to fail closed on stateful inputs. currently render_responses_request() accepts previous_response_id but calls render_responses() with prev_response=None and prev_messages=None, so a continuation is silently rendered as a new conversation. I’d reject previous_response_id here and require callers to submit fully rehydrated input.

there’s a similar issue with built-in tools on the GPU-less server: tool_server remains unset, so GPT-OSS requests using web search, code interpreter, or container tools silently lose their tool descriptions during rendering. either the renderer needs access to the relevant tool metadata, or those requests should be rejected rather than producing a different prompt.

this will also need rebasing onto the current OnlineRenderer / ServingRender split. my preferred contract would be: self-contained Responses input plus render configuration produces deterministic token IDs or a GenerateRequest; state lookup and history rehydration remain outside vLLM.

CC @tjtanaa @maralbahari

@andrewbcohere

Copy link
Copy Markdown
Contributor

Hi @hyeongyun0916 , just wondering if you have time to address the changes requested by franciscojavierarceo above or if you no longer have time for this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants