Skip to content

Unified client recipes - #93

Merged
sfc-gh-mwyatt merged 10 commits into
mainfrom
mwyatt/unified-client-recipes
Aug 27, 2026
Merged

Unified client recipes#93
sfc-gh-mwyatt merged 10 commits into
mainfrom
mwyatt/unified-client-recipes

Conversation

@sfc-gh-mwyatt

@sfc-gh-mwyatt sfc-gh-mwyatt commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Ports cortex-client recipes to unified client. Largely a move/refactor, with some fixes to support these recipes properly on cortex backend. Next steps will be support with onprem backend.

  • Port two standalone training recipes (recipes/sft/standalone/, recipes/rl/standalone/) from cortex-client to the unified arctic_platform.client.
  • Fix forward-backward 400s on Cortex: restore force_chunk in the DSSST1 encoder and send the wire's own fwd-bwd operation label in chunk metadata.
  • Fix KeyError: 'request_id' on weight sync: Cortex's /operations interface have inconsistent behavior. weight-sync returns a request_id to poll, while reset-prefix-cache and four other ops answer inline. Dispatch on the response instead of assuming everything is async.
  • Make wake/sleep no-ops on Cortex, which never colocates training and sampling, so shared client flows like sync_weights() stay backend-portable.
  • Support LoRA on Cortex: add TrainingConfig.peft, forward it through to_cortex(), and add weight_format to sync_weights().
  • Fail fast instead of silently dropping config: validators reject training.peft and weight_format against on-prem, and HTTP errors now carry the server's response body.

Some of the fixes listed above were cherrypicked from #55

sfc-gh-kganesan added a commit that referenced this pull request Aug 26, 2026
Rebase of the Cortex shim onto #93, dropping only what #93 already provides
rather than dropping capability. Both frameworks keep the end-to-end path that
was validated pre-rebase (verl val@10 0.311 / SkyRL 0.308 on GSM8K).

The three places Cortex diverges from on-prem now live in CortexTransport, so
no integration carries its own copy and #93's recipes are unaffected:

  - forward-backward is lowered from verl's {batch, meta} to Cortex's
    {args, kwargs, context}; frames already in Cortex's shape pass through.
  - forward is zero-filled, because Cortex has no such sub-job. Sound only for
    single-epoch on-policy GRPO without KL, so the verl adapter refuses the
    knobs that would read those values before the client is built.
  - avg_loss / last_lr, which Cortex returns at the top level, are mirrored
    into `metrics`. step has no `metrics` key at all, which would otherwise
    KeyError in verl's _send_update_actor.

Dropped as genuinely redundant with #93: its cortex.py changes (a strict
superset of ours), the shim's fake-async wrapper (AsyncArcticRLClient), its
response flattener and its payload reshape. That shrinks _cortex_dispatch from
147 lines to config translation plus the legacy accessors SkyRL reads.

Also folds in the remote_urls fix from tire-kicking: pinned SkyRL asserts
num_engines == len(remote_urls), so the recipe never ran as documented.

Backend imports in create_arctic_rl_client are now lazy, which is what a
CPU-only Cortex driver needs and incidentally fixes tests/rl/test_cpu_import.py.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sfc-gh-mwyatt
sfc-gh-mwyatt marked this pull request as ready for review August 27, 2026 16:02
Comment thread recipes/rl/standalone/README.md Outdated
Comment thread recipes/rl/standalone/requirements.txt Outdated
Comment thread recipes/sft/standalone/README.md Outdated
@sfc-gh-mwyatt
sfc-gh-mwyatt merged commit 18a5028 into main Aug 27, 2026
3 checks passed
@sfc-gh-mwyatt
sfc-gh-mwyatt deleted the mwyatt/unified-client-recipes branch August 27, 2026 20:45
sfc-gh-kganesan added a commit that referenced this pull request Aug 28, 2026
#93 landed _NOOP_OPS, _INLINE_OPERATION_TYPES and _submitted verbatim from
this branch, so the rebase left two identical definitions of each. Python
binds the last one, which is why tests still passed -- but the shadowed
copies are a trap for the next reader.

What remains here is the terminal-state diagnostic: main raises a bare
"reached terminal state 'failed'", which is what made the provisioning
failures during this integration so slow to diagnose. Attaching the server's
reason and the per-sub-job states distinguishes rate limits and allowlist
rejections from genuine crashes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants