Repository navigation
v0.0.8
Highlights
Sampling pools. Sampling now goes through pools (#386, design in #324). The API server adds each sample request to a Redis Stream for the model's pool (#336). A dispatcher reads the stream, sends each request to a sampler, and saves exactly one result per request (#354). A sampler that stops does not lose requests. A shared pool serves its jobs in round-robin order, so one job's large batch does not block the other jobs. A request that no sampler answers within OPEN_RL_SAMPLE_DEADLINE_SECONDS fails with an error. A pool with one owner runs its sampler in process, as before. Shared LoRA pools and pools with two or more replicas run vllm serve replicas behind a dispatcher pod with Envoy and the llm-d endpoint picker. The dispatcher loads each new FFT revision onto every replica (#357).
Inspection API. The API server now serves read-only routes under /api/v1/inspect/ for agents and dashboards (#388, #389, #392, #393, #395, #396, #397):
inventorylists each run with its model, recipe, lifecycle, pods and nodes. It also lists the cluster's nodes, GPUs and problem pods.runslists one line per run.runs/{run_id}/summaryexplains why a run does not behave: pace, goodput, lost requests, failures, saves and placement.runs/{run_id}/stepsreturns each step's ops, timing and metrics, including the density of each sparse delta (#404).activityreturns one lane per Workload with its GPUs, runs, held interval, time-slicer turns and waits (#411).logs?run_id=<id>pages a run's logs. SetOPEN_RL_LOG_STORE=cloud-loggingon the API server to enable it.query?name=runs named PromQL queries such asgpu_utilandgpu_busy. SetOPEN_RL_PROMETHEUS_URLto enable it.
The scheduler now records the GPU UUIDs, the placement time and the release time on each Workload's status (#393). Each DRA node lists its GPUs by name, UUID, product and memory (#409). Trainers and samplers record their activity in Redis (#396). One flusher thread per process writes the records every 5 seconds, so the request path makes no Redis calls.
Fleet demo app. k8s/deploy/demo adds a web app over the inspection API (#412). It starts a sweep of RL client Jobs and shows the fleet as one row per GPU. It also draws an occupancy timeline and shows the sparse deltas of each FFT run. It runs on the API server image with its code in a ConfigMap, so there is no image to build.
GPU metrics in every bundle. The lora and fft bundles now ship the DCGM exporter (#391). Before, only the distributed-fft-timeslice bundle had it. docs/configuration.md lists the Workload Identity grants that the inspection API needs for metrics and logs on GKE.
Faster job start.
- If you set
openrl.recipe=rlinTINKER_TAGSoruser_metadata,create_modelstarts the sampler together with the trainer (#368). Before, the sampler started at the first sample request. In an eight-job fleet test, every job reached its first step 17 to 60 seconds sooner. - Sampler pods keep vLLM's compile cache on the shared volume (#358). The first sampler for a model, GPU type and engine setup compiles and saves the result. Later samplers load it in 2 to 6 seconds instead of 42 to 83 seconds.
- The sampler records CUDA graphs for power-of-two batch sizes only (#359).
- The gemma-4 LoRA sampler loads the text-only model (#360). Set
VLLM_ENABLE_MULTIMODAL=1to keep the full model. - Trainers read a checkpoint on nfs or lustre into the page cache with eight threads before they load it (#380).
- The client image installs the projects at build time, so a client container starts 8 to 27 seconds sooner (#410).
Faster training steps.
- If
OPEN_RL_TRAIN_TOKEN_BUDGETis unset orauto, the trainer groups sequences into passes of up to 16384 tokens, or fewer on a small GPU (#350). Before, an unset budget meant one sequence per pass. A 64-sequence gemma-4-E2B LoRA step on an A100 takes 3.5 s instead of 43 s. - The trainer starts a new pass when padding would exceed 25% of a pass (#351).
- The trainer computes target log-probabilities in chunks of 1024 positions, so loss memory no longer grows with tokens × vocabulary size (#348). This raises the token budget for large-vocabulary models such as gemma-4.
Fleet placement.
OPEN_RL_LORA_JOBS_PER_RUNTIMEcaps the LoRA jobs on one shared trainer and sampler (#371). The next job on the same base model starts a second runtime with its own workers. Unset or0keeps one runtime.- The scheduler flag
--max-seats-per-claim(OPEN_RL_MAX_SEATS_PER_CLAIM) caps the time-sliced workers on one shared GPU (#394). A worker that finds every claim full waits for a free GPU or a free seat. The default0sets no limit.
Shared volume class and size. make render takes STORAGE_CLASS and STORAGE_SIZE and patches open-rl-shared-pvc with them (#384). Unset keeps standard-rwx and 1Ti, so the release bundles do not change. A five-job fleet finished in 412 s on a Filestore Zonal volume instead of 950 s on Basic HDD.
Performance comparison script. scripts/perf_compare.py runs the same 23-job GSM8K workload on a "before" and an "after" image set (#385). Its report compares total time, time to the first step, step time by phase and peak GPU memory. Run it with make perf-compare PERF_BEFORE=... PERF_AFTER=....
Breaking changes
- Sampling pools (#386). Drain every job before you upgrade. Old samplers read the old queue, and the owner names of shared LoRA runtimes change. Apply the Role before the image. The API server needs new
listverbs on Deployments and NetworkPolicies. Rebuild custom trainer images, because the trainer now freezes each LoRA save for the sampler. This release removes the old queue sampler. - Sampling settings (#352). vLLM no longer applies a checkpoint's default sampling settings, such as Qwen3's temperature of 0.6. A request gets exactly what the client asks for. vLLM now uses prefix caching.
- Token budget default (#350). An unset
OPEN_RL_TRAIN_TOKEN_BUDGETnow meansauto. Set it to0to keep one sequence per pass. - PodMonitoring CRD (#391). The
loraandfftbundles now need the PodMonitoring CRD, which GKE's Managed Prometheus provides.
Fixes
- A time-sliced sampler now wakes its weights, applies the delta, and then wakes its KV cache (#425). Before, a large delta ran out of memory because the KV cache took the GPU first.
- A sampler that exits during a turn now lets its park finish before it unregisters (#427). Before, the process died with
readuntil() called while another coroutine is already waiting. - A time-sliced sampler can restart while the llm-d snapshot agent still holds its job as SAVED. That sampler now fails its pending requests with the reason in seconds (#428). Before, it restarted for an hour until the client hit the 3600 s deadline. The job still cannot recover under the same name.
- The FFT trainer writes a full sampler save when no earlier save holds the base of a sparse delta, for example after
load_from_state(#357). Before, the sampler could end up on the wrong weights. - The
gpu_busyquery falls back toDCGM_FI_DEV_GPU_UTILwhen Managed Service for Prometheus answersnullfor a query with no series (#408). - The
openrlskill'sSKILL.mdfrontmatter now parses as YAML (#356).
Docs and site
- Sampling pools design (#324).
- The NVIDIA DRA driver install now sets
gpuResourcesEnabledOverride=true, which chart 25.8.0 requires (#418). - Blog posts: OpenRL in October (#334, #335) and Delta Weight Sync in OpenRL (#346).
- The slide deck has a new section on the problems OpenRL solves, and controls for background, text and presenter (#367).
New Contributors
- @sunnythecode made their first contribution in #346
- @linde made their first contribution in #356
Full Changelog: v0.0.7...v0.0.8