Skip to content

feat(dynamo): support LoRA lifecycle - #3179

Open
biswapanda wants to merge 2 commits into
PrimeIntellect-ai:mainfrom
biswapanda:pr/dynamo-lora
Open

feat(dynamo): support LoRA lifecycle#3179
biswapanda wants to merge 2 commits into
PrimeIntellect-ai:mainfrom
biswapanda:pr/dynamo-lora

Conversation

@biswapanda

@biswapanda biswapanda commented Aug 3, 2026

Copy link
Copy Markdown

Summary

  • discover Dynamo worker LoRA update endpoints
  • pause all engines, load the filesystem adapter on every worker, wait for frontend visibility, then resume
  • preserve the existing non-Dynamo LoRA update path

Dependency

This branch includes the prerequisite commit because it targets main. Its effective diff will shrink when #3176 merges.

Test plan

  • ruff check on the discovery, LoRA, and test files
  • focused Dynamo discovery and LoRA lifecycle tests
  • included in the aggregate branch validation: 37 focused tests passed

Note

Medium Risk
Changes the orchestrator weight-update and inference discovery paths for Dynamo and LoRA; misconfigured inference_world_size or partial worker capability can block startup or leave engines paused if resume fails (mitigated by finally resume in tests).

Overview
Adds Dynamo-based inference pool setup via dynamo_discovery_url and /v1/rl/workers, replacing static admin_base_url for worker admin endpoints and per-engine world_size. Discovery retries until the summed worker world_size matches weight_broadcast.inference_world_size, which is now required on the orchestrator when Dynamo is enabled and can be set on shared NCCL/NIXL/filesystem broadcast for runs without a local inference config.

DynamoInferencePool extends the static pool with discovered admin clients, optional per-worker update/load_lora system URLs, and readiness that also checks the frontend /v1/models. LoRA weight updates on Dynamo pause engines on admin clients, POST adapters to /v1/loras on every worker’s system endpoint, wait until the adapter appears on the frontend, then resume; non-LoRA updates still use the existing admin path. StaticInferencePool can inject pre-built admin clients for this flow.

Config validation blocks mixing Dynamo with admin_base_url or elastic discovery; RL resolution propagates weight_broadcast to the orchestrator and relaxes the single-node NCCL “two local GPUs” rule when inference_world_size is set for external inference.

Reviewed by Cursor Bugbot for commit 5ff9be2. Bugbot is set up for automated code reviews on this repo. Configure here.

@biswapanda
biswapanda marked this pull request as ready for review August 3, 2026 21:44

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5ff9be2. Configure here.

timeout=httpx.Timeout(None),
)
for url in urls
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Control clients omit auth headers

Medium Severity

_setup_control_clients builds worker admin and LoRA system clients without the API key or custom headers that setup_admin_clients always attaches. With VLLM_API_KEY or configured headers set, Dynamo pause/resume//v1/loras calls can fail auth while frontend readiness checks still succeed.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5ff9be2. Configure here.

def __init__(self, client_config: ClientConfig, workers: tuple[DiscoveredDynamoWorker, ...], **kwargs):
admin_clients = _setup_control_clients([worker.admin_base_url for worker in workers])
super().__init__(client_config, admin_clients=admin_clients, **kwargs)
self._admin_world_sizes = [worker.world_size for worker in workers]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Discovered world sizes unused

Medium Severity

DynamoInferencePool stores per-worker _admin_world_sizes from discovery but never reads them. NCCL/NIXL init still derives rank offsets as inference_world_size // len(admin_clients), so heterogeneous Dynamo topologies (for example different prefill vs decode TP) get incorrect broadcast ranks.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5ff9be2. Configure here.

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.

1 participant