Use vLLM's own server instead of TRL's - #6765
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 659619393f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
827c4df to
73a0661
Compare
73a0661 to
4284a70
Compare
`trl vllm-serve` ran a custom FastAPI app around `LLM`, with its own data-parallel fan-out and a worker extension for weight sync. vLLM's server covers all of it, so the app is deleted and the command becomes a deprecated wrapper that translates its flags into `vllm serve`, prints the equivalent command, and forwards anything it does not know about. - generation goes to `/v1/completions` for token IDs. Multimodal prompts have no OpenAI-compatible endpoint that takes token IDs and images at once, so the images are processed on their own and the resulting features are paired with the trainer's token IDs on `/inference/v1/generate`, which keeps multi-turn generation working with images - weight sync uses vLLM's NCCL weight-transfer engine: the tensors are announced once and streamed in a single packed broadcast, rather than one HTTP request and one broadcast per tensor - teacher logprobs for distillation come from `prompt_logprobs` - the docs teach `vllm serve` directly, and the web-server dependencies go The request sets `output_kind` explicitly, as the server would otherwise drop completions when `n > 1` (vllm-project/vllm#52399).
4284a70 to
92abffe
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 92abffe. Configure here.
The sections explaining vLLM's own workers, tensor parallelism and PagedAttention belong to vLLM's documentation, more so now that TRL runs its server rather than its own. The throughput plots went with them: they were measured on older vLLM versions and the warning underneath already told readers not to follow the data parallel advice they show.
The required settings are listed in the table below, the reward and loss steps belong to the trainer docs, and the separate-GPUs example appears verbatim right after the quickstart. What is left is the part specific to TRL: which endpoints the trainer calls, and which way the weights travel.
`trl vllm-serve`'s custom app, and with it `/get_sequence_logprobs/`, goes away in huggingface#6765, so the rollout worker teacher-forces the student's completion through vLLM's own endpoint instead: `max_tokens=1` with `prompt_logprobs=teacher_top_k`, sliced from `len(prompt_ids)`. Same request `VLLMClient.get_sequence_logprobs` issues for the synchronous server-teacher trainers. The response is parsed here rather than through that client: it truncates each position to exactly `top_logprobs` after rank-sorting and reports the realized token in separate fields, which would drop that token wherever it ranks below k, zeroing the teacher signal there at `beta=1.0`. Parsing the raw `prompt_logprobs` mapping keeps it at any rank, so the candidate rows stay `teacher_top_k + 1` wide and `_narrow_top1_actual_support` keeps finding what it indexes. `/v1/completions` names the model it addresses and, under MOPD, every teacher serves a different one, so each teacher's served id is resolved from its `/v1/models` at worker startup. That doubles as the teachers' readiness wait. Teacher servers are now plain `vllm serve` and need `--logprobs-mode processed_logprobs` (or `teacher_temperature` never reaches their logprobs) and `--max-logprobs -1` (or `teacher_top_k > 20` is rejected). Documented, along with the pre-existing requirement that every teacher share the student's tokenizer, since teacher candidate ids index the student's vocabulary directly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

trl vllm-serveran a custom FastAPI app aroundLLM, with its own data-parallel fan-out and a worker extension forweight sync. vLLM's server covers all of it, so the app is gone and the command is now a deprecated wrapper that
translates its flags into
vllm serveand prints the equivalent command.Changes
trl/scripts/vllm_serve.pygoes from 1218 to ~130 lines! It adds the three settings TRL needs(
--weight-transfer-config,--logprobs-mode processed_logprobs,--max-logprobs -1), setsVLLM_SERVER_DEV_MODE=1, and forwards any other argument tovllm serve.fastapi,uvicornandpydanticleave thevllmextra./v1/completionsfor token IDs. No OpenAI-compatible endpoint takes token IDs and images, somultimodal prompts have their images processed on their own and the resulting features paired with the trainer's
token IDs on
/inference/v1/generate, which keeps multi-turn generation working with images.prompt_logprobs.vllm serveis the documented way to start the server.No change to training code:
vllm_mode,vllm_server_base_url,vllm_group_portand the rest behave as before,trl vllm-servestill accepts the same flags, and GRPO and RLOO are untouched.Benchmark
GRPO in server mode on H100s, Qwen2.5-1.5B (text) and Qwen2.5-VL-3B (VLM), same seed and same data, server on its own GPUs and a two-process trainer.
Same behaviour: with a fixed generation seed the two implementations produce bit-identical completions (16/16 over 4 prompts x n=4, logprobs identical to 0.0 over 499 tokens). The training curves still do not lie on top of each
other, for reasons that have nothing to do with this PR.
Why the curves do not overlap exactly
The text curves diverge because each run talks to its own server process. Against the same server, two runs of
the same code are bit-identical, so the trainer itself is deterministic:
Give each run its own server — which comparing two implementations necessarily does — and they drift apart, because a
fresh engine returns slightly different logits and one flipped token changes every later step. That drift is as large
between two runs of
mainas it is betweenmainand this PR:The VLM curves sit apart for a real reason. The server returns the processed image already cast to the model
dtype, while handing the engine the image directly preprocesses in float32. The values are otherwise the same:
So the image is the same image, rounded to the dtype the model runs in. That moves logprobs by ~0.04 and occasionally flips a greedy argmax: over three greedy generations the two implementations agreed on two and differed by one word on the third, both naming the colour correctly.
Validation
On H100s against vLLM 0.27.1:
tests/test_vllm_client_server.py -m slow: 34 passedTwo fixes came out of this: vllm-project/vllm#52399, where
/inference/v1/generatedrops completions whenn > 1(the client setsoutput_kindexplicitly until it lands), andthe client here no longer builds its NCCL communicator on an unindexed device, which on
mainbreaks asingle-process trainer with
this nccl communicator is created to work on cuda, but the input tensor is on cuda:0.Note
High Risk
Large change to server-mode vLLM integration (HTTP APIs, NCCL weight sync, multimodal routing); training configs stay the same but runtime depends on vLLM dev endpoints and correct server flags.
Overview
Replaces TRL's custom vLLM FastAPI server with vLLM's built-in
vllm serve.trl vllm-serveis now a deprecated thin wrapper that maps flags tovllm serve, setsVLLM_SERVER_DEV_MODE=1, and forwards extra CLI args; the large in-process server implementation is removed.fastapi/uvicorn/pydanticdrop out of thetrl[vllm]extra.VLLMClientno longer hits TRL-only routes (/generate/,/chat/, per-tensor/update_named_param/). It uses OpenAI-style/v1/completionsand/v1/chat/completions, vLLM dev endpoints for NCCL weight transfer (/init_weight_transfer_engine,/start_weight_update,/update_weights,/finish_weight_update), and/inference/v1/generatefor multimodal generation from trainer token IDs plus precomputed image features (image_features+parse_logprobs). Teacher sequence logprobs go throughprompt_logprobson/v1/completionsinstead of a custom binary API.VLLMGenerationand Online DPO adopt the new client paths (batched packed weight sync,weight_update()context, chat for multimodal server prompts). Docs and examples now documentvllm servewith the required TRL flags (--weight-transfer-config,--logprobs-mode processed_logprobs,--max-logprobs -1).Reviewed by Cursor Bugbot for commit ec6b582. Bugbot is set up for automated code reviews on this repo. Configure here.