Report unsupported global CPU offload profiles (#104)

Handle unresolved auto preload through its Qwen fallback and avoid a false warning.
This commit is contained in:
Diego authored and GitHub committed 2026-09-05 12:30:00 -07:00
1 parent efeec825c1
commit 697e11f2ab
7 files changed
+196 -17

No files matched your search

@@ -61,6 +61,16 @@ PROFILE_ADAPTIVE_POLISH = {
AUTO_PROFILE: False,
}
# Which profiles let ``--cpu-offload`` reach their GLOBAL stack. The face stage
# honours the flag everywhere, because residency lives on the shared base, but the
# global stack is each profile's own: only qwen-zimage streams it, through
# ``_qwen_vram_config``. chroma-zimage and sdxl-zimage load theirs with a plain
# ``.to(device)``, so on a card below the face-stage residency floor the flag has
# nothing left to change and the run behaves as if it were absent. Data rather than
# a subclass attribute, because the caller that must warn cannot import a profile
# module without pulling in Diffusers.
GLOBAL_OFFLOAD_PROFILES = frozenset({QWEN_ZIMAGE_PROFILE})
SDXL_LIGHTNING_MODEL_ID = "ByteDance/SDXL-Lightning"
SDXL_LIGHTNING_PATTERN = "sdxl_lightning_4step_lora.safetensors"
@@ -221,6 +231,19 @@ def resolve_adaptive_polish(adaptive_polish: bool | None, pipeline: str) -> bool
return PROFILE_ADAPTIVE_POLISH.get(normalize_profile(pipeline), True)
def global_offload_supported(pipeline: str) -> bool:
"""Whether ``--cpu-offload`` reaches this profile's global stack.
Per-image ``auto`` runs resolve before loading a stack. An explicit preload is
the only unresolved ``auto`` load, and that path deliberately uses qwen-zimage
as its fallback, so it has the same offload support as qwen-zimage.
"""
profile = normalize_profile(pipeline)
if profile == AUTO_PROFILE:
profile = resolve_auto_profile(None)
return profile in GLOBAL_OFFLOAD_PROFILES
def strength_default_help() -> str:
"""Describe the live default policy without duplicating its values."""
return (
@@ -19,6 +19,7 @@ from remove_ai_watermarks._internal.watermark_profiles import (
QWEN_ZIMAGE_PROFILE,
REMOVAL_MODULES,
SDXL_ZIMAGE_PROFILE,
global_offload_supported,
normalize_profile,
resolve_auto_profile,
resolve_seed,
@@ -153,8 +154,27 @@ class WatermarkRemover:
"""Materialize the selected model stack before the first request."""
self._load_qwen_zimage_pipeline().preload(global_only=global_only)
def _warn_if_global_offload_unsupported(self) -> None:
"""Say so when --cpu-offload cannot reach the stack it was asked for.
Warned here rather than at construction because ``auto`` picks its engine
per-image. A normal run reaches this point with a concrete profile; preload
reaches it as unresolved ``auto`` and builds its qwen-zimage fallback.
Either way this remains ahead of the model load the user is waiting on.
"""
if not self.cpu_offload or global_offload_supported(self.model_profile):
return
logger.warning(
"--cpu-offload does not reach the global stack of the '%s' pipeline: only "
"qwen-zimage streams its global model between CUDA calls. The face stage "
"still honours the flag, so below the face-stage residency floor this run "
"behaves as if --cpu-offload were absent.",
self.model_profile,
)
def _load_qwen_zimage_pipeline(self) -> Any:
if self._qwen_zimage_pipeline is None:
self._warn_if_global_offload_unsupported()
if self.model_profile == SDXL_ZIMAGE_PROFILE:
from remove_ai_watermarks._internal.sdxl_zimage_pipeline import (
SdxlZImagePipeline as _Pipeline,
+4 -2
View File
@@ -337,8 +337,10 @@ _cpu_offload_option = click.option(
default=False,
help=(
"Offload model components to CPU between CUDA calls instead of keeping the "
"whole pipeline in VRAM, at the cost of speed. For qwen-zimage, forces the "
"face stack to offload instead of using automatic residency."
"whole pipeline in VRAM, at the cost of speed. Forces the face stack to "
"offload instead of using automatic residency, on every profile. It reaches "
"the global stack of qwen-zimage only: chroma-zimage and sdxl-zimage keep "
"theirs resident either way."
),
)
+4 -3
View File
@@ -170,9 +170,10 @@ class InvisibleEngine:
controlnet_conditioning_scale: Canny ControlNet structure-preservation
strength on the global stage (not used by chroma-zimage).
cpu_offload: Offload model components to CPU between CUDA calls instead
of keeping the whole pipeline in VRAM, at the cost of speed. For
qwen-zimage, force the face stack to offload instead of using automatic
residency. CUDA only.
of keeping the whole pipeline in VRAM, at the cost of speed. Forces
the face stack to offload instead of using automatic residency, on
every profile; reaches the global stack of qwen-zimage only.
CUDA only.
"""
from remove_ai_watermarks._internal.watermark_remover import WatermarkRemover