[Diffusion] Support LoRA in step-wise execution (#3639)

Signed-off-by: samithuang <285365963@qq.com>
This commit is contained in:
Samit authored and GitHub committed 2026-05-20 22:26:18 +08:00
1 parent f74cba84ac
commit 083b5e363f
8 files changed
+338 -60

No files matched your search

+42 -7
View File
@@ -185,6 +185,10 @@ class DiffusionWorker:
self.model_runner: DiffusionModelRunner | None = None
self._sleep_saved_buffers: dict[str, torch.Tensor] = {}
self.lora_manager: DiffusionLoRAManager | None = None
# Worker-side cache of (lora_request, lora_scale) per scheduled
# request id. Used by step mode to recover LoRA identity for cached
# requests, which only carry their sched_req_id in subsequent ticks.
self._step_lora_state: dict[str, tuple[LoRARequest | None, float]] = {}
self.stage_id = getattr(od_config, "stage_id", 0)
self.init_device()
# Create model runner using the platform-specified class
@@ -367,13 +371,7 @@ class DiffusionWorker:
def execute_stepwise(self, scheduler_output: DiffusionSchedulerOutput) -> BaseRunnerOutput:
"""Execute one diffusion step by delegating to the model runner."""
assert self.model_runner is not None, "Model runner not initialized"
if self.lora_manager is not None:
# Step mode does not support LoRA yet. Clear any previously active
# adapter first so worker-local LoRA state cannot leak in.
self.lora_manager.set_active_adapter(None)
if any(new_req.req.sampling_params.lora_request is not None for new_req in scheduler_output.scheduled_new_reqs):
raise ValueError("Step mode does not support LoRA yet.")
self._activate_step_lora(scheduler_output)
profiler = self._get_profiler()
ctx = profiler.annotate_context_manager("diffusion_step") if profiler else nullcontext()
with ctx:
@@ -382,6 +380,43 @@ class DiffusionWorker:
profiler.step()
return output
def _activate_step_lora(self, scheduler_output: DiffusionSchedulerOutput) -> None:
"""Activate the LoRA adapter for the scheduled step batch.
Newly scheduled requests register their (lora_request, lora_scale)
in ``_step_lora_state`` so cached requests can resolve to the same
adapter on later ticks. Finished requests are evicted. Batch
homogeneity is enforced by the scheduler via ``SamplingParamsKey``,
so any scheduled request id resolves to the active LoRA identity.
"""
for sched_req_id in scheduler_output.finished_req_ids:
self._step_lora_state.pop(sched_req_id, None)
for new_req in scheduler_output.scheduled_new_reqs:
sampling = new_req.req.sampling_params
self._step_lora_state[new_req.sched_req_id] = (
sampling.lora_request,
sampling.lora_scale,
)
if self.lora_manager is None:
return
lora_request: LoRARequest | None = None
lora_scale = 1.0
for sched_req_id in scheduler_output.scheduled_req_ids:
entry = self._step_lora_state.get(sched_req_id)
if entry is not None:
lora_request, lora_scale = entry
break
try:
self.lora_manager.set_active_adapter(lora_request, lora_scale)
except Exception as exc:
if lora_request is not None:
raise
logger.warning("LoRA activation skipped: %s", exc)
def load_weights(self, weights) -> set[str]:
"""Load weights by delegating to the model runner."""
assert self.model_runner is not None, "Model runner not initialized"