feat(integrations/verl): swap adapter to arctic_platform.client (unified client) - #51
Closed
sfc-gh-kganesan wants to merge 1 commit into
Conversation
…nditional) Move the verl RemoteBackend adapter off `arctic_platform.rl` and onto the unified `arctic_platform.client`. Backend selection collapses to one yaml knob (`remote_backend.backend`) resolved inside the client by `make_transport(config)`; the adapter itself no longer branches on "cortex" vs "onprem". - Imports swap `arctic_platform.rl` -> `arctic_platform.client`. - `ArcticRLRayServerState` moved to a `TYPE_CHECKING` import from `arctic_platform.client.transports.onprem_ray` so a Cortex-only install (no ray) still imports the adapter cleanly. - `_initialize_client` reads `backend` from yaml (default `onprem`) and forwards a whitelisted set of cortex keys (`cortex_host`/`_database`/`_schema`/`_endpoint`/`_pat_env_var`/ `_base_url`, `max_seq_len`) when a `remote_backend.cortex` sub-block is present. - Drop the hardcoded `backend="local"` and `log_prob_engine="deepspeed"`. Legacy aliases live on `ArcticRLClientConfig` now (compat PR #50); if a stale yaml still sets `backend: local` the client warns and coerces. - `CUDA_VISIBLE_DEVICES` widening only runs on the on-prem path — the driver actor on Cortex has no local GPU placement to widen. - Drop `await` on every `self._client.*` call (unified client is sync). The `RemoteBackend` interface stays `async def` (verl requirement); private `_send_*` helpers become plain `def` — their bodies were already synchronous once you strip the awaits. No behavioral change on the on-prem path (the four-fields commit in #50 threads `ds_worker_config` / `arctic_inference_config` / `log_prob_ds_config` / `full_determinism` through the unified init). Cortex path is enabled by setting `remote_backend.backend: cortex` in the arctic.yaml + populating the `remote_backend.cortex` sub-block. Depends on #50 (compat layer + four fields). PR against `sfc-gh-kganesan/skyrl-verl-cortex-compat`. Co-authored-by: Cursor <cursoragent@cursor.com>
Collaborator
Author
|
Closing this PR — after re-reading the merged upstream integrations (NovaSky-AI/SkyRL#1837, verl-project/verl#6422) I confirmed neither integration should have to change to gain Cortex support. Both the merged SkyRL Rewiring will land as new commits on #50; this branch will be deleted. |
This was referenced Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on / stacked on top of #50 (base branch is
sfc-gh-kganesan/skyrl-verl-cortex-compat, notmain) so the diff is only the adapter delta. Do not merge before #47 and #50.Tracked by #49.
Why
arctic_platform/integrations/verl/adapter.pystill imports from the pre-unificationarctic_platform.rlpackage. Every call site through that module isasync defeven though the underlying HTTP/Ray calls are already synchronous, backend selection is hardcoded tobackend="local", and there's no way to point the adapter at Cortex without forking it.This PR does the minimal swap onto the unified
arctic_platform.clientshipped by #45–#47 + #50. Combined they give verl a serverless-capable backend switchable by a single yaml knob.What
arctic_platform/integrations/verl/adapter.pyImport swap —
arctic_platform.rl→arctic_platform.client:ArcticRLClientConfig,create_arctic_rl_clientfrom the unified package.ArcticRLRayServerStatemoved to aTYPE_CHECKINGimport fromarctic_platform.client.transports.onprem_ray, so a Cortex-only install (which never pullsrayin) still imports the adapter cleanly. Reconnect-path parameter typing preserved.One backend knob, no adapter-side branching:
_initialize_clientreadsbackendfrom yaml (remote_backend.backend, default"onprem") and passes it straight through. Dispatch toRayTransport/HttpTransport/CortexTransporthappens insideArcticRLClient.__init__viamake_transport(config)— the adapter has zero knowledge of Cortex-specifics.remote_backend.cortex.*) is whitelisted through intoArcticRLClientConfig:cortex_host,cortex_database,cortex_schema,cortex_endpoint,cortex_pat_env_var,cortex_base_url,max_seq_len. Any missing key falls back toCortexTransportdefaults orCORTEX_*env vars.backend=\"local\"andlog_prob_engine=\"deepspeed\". If a stale yaml still setsbackend: local, the client's legacy alias (in feat(rl): Cortex-serverless dispatch via arctic_platform.rl (zero integration change) #50) warns and coerces toonprem.CUDA_VISIBLE_DEVICESwidening (needed because Arctic's driver actor is scheduled withnum_gpus=0) is now gated onbackend == \"onprem\"— driver-side GPU placement is meaningless on Cortex.Sync-under-async:
arctic_platform.clientare synchronous. Everyawait self._client.*becomes a plain call; everyawait self._send_*becomes a plain call.RemoteBackend's interface methods (compute_log_prob,update_actor,generate,save_checkpoint,update_weights,wake_up_inference,sleep_inference,reset_prefix_cache,destroy) stayasync def— verl'sRemoteBackendTrainerawaits them and swapping the interface would be a breaking change I don't want in this PR._send_compute_ref_log_prob/_send_compute_log_prob/_send_update_actorbecome plaindef; their bodies were already effectively synchronous once you strip the awaits.What this PR does NOT touch
_prepare_padded_arctic_batch_dict,_no_padding_2_padding_prompt_response,_create_ds_config,_create_ds_worker_config,_send_update_actor's left-pad handling) — byte-identical tomain, so on-prem behavior is unchanged.response[\"batch\"][\"log_probs\"],.pop(\"logprobs\"),response[\"metrics\"]aggregation) — same reads; the compat layer in feat(rl): Cortex-serverless dispatch via arctic_platform.rl (zero integration change) #50 makes the Cortex path emit the same shape.RemoteBackendinterface. No signature changes visible to verl.Tests
Existing
tests/client/*pass (69 pass; the compat test suite from #50 pins every call site the adapter makes against the client). No new adapter-level tests in this PR — the compat suite already covers the client-facing contract; an integration test lives on the E2E smoke below.Test plan
python -m pytest tests/client/— 69 pass on this branch.async, 3 private helpers become sync).recipes/rl/skyrl/simple_gsm8k/run_qwen3_0.6b_gsm8k_grpo_arl.shusingremote_backend.backend: onprem. Loss curves vsmainmust match to within numerical noise.remote_backend.backend: cortex+ a populatedremote_backend.cortexblock, once the Cortex-side blockers in Cortex-serverless enablement for verl + SkyRL via the unified ArcticRLClient #49 §2 land (fwd-no-grad endpoint, log-probs endpoint,metricsblock onfwd_bwd/stepresponses).Follow-ups (see #49)
POST /{job_id}/forward-no-grad,POST /{job_id}/log-probs.fwd_bwd/stepresponses grow ametrics: {grad_norm, ppo_kl, pg_clipfrac, pg_loss, kl_loss, kl_coef}block.Snowflake-AI-Research/arctic-skyrl(same import swap, same backend knob).Made with Cursor