Fix/adjust diffusion: round 30 P1 + P2 batch for PR #5754
Four actionable findings from round 30. Skipped P1 #1 / #2 / #3 (huggingface-hub bump in studio.txt / single-env / colab-new) because the live B200 Studio that successfully generated FLUX.2 klein images runs the exact combo the reviewer flags as broken: huggingface_hub 0.36.2 + transformers 4.57.6 + diffusers 0.37.1 Flux2KleinPipeline: True (imports cleanly) The is_offline_mode ImportError only fires with transformers 5.x, and the standard install path pins transformers==4.57.6 via constraints. The round 26 fix bumped no-torch-runtime.txt + pyproject huggingfacenotorch where the --no-deps install path can land on transformers 5.x; that remains the correct surface. 1. core/inference/diffusion.py: preflight transformers + accelerate via importlib.util.find_spec BEFORE any destructive GPU-owner unload. Diffusers can expose stub pipeline classes when transformers / accelerate are missing, so the load used to drop chat first and fail later inside from_pretrained. find_spec keeps existing tests that stub these modules passing because no real module is executed (round 30 P1 #11). 2. models/export.py ExportGGUFRequest.quantization_method: extend the embedded HF token validator to this field too. Round 23 added the control-char guard but not the token guard; the value is forwarded into worker command lines and reflected in error / success text (round 30 P1 #5). 3. models/data_recipe.py SeedInspectUploadRequest: add _no_control_chars + _reject_embedded_hf_token field_validators to filename and to each entry of file_names. Mirrors the sibling SeedInspectRequest.dataset_name hardening (round 30 P1 #6). 4. frontend/src/features/images/images-page.tsx: defer the initial refreshStatus() call via queueMicrotask so the synchronous setRefreshingStatus(true) inside it does not trip the react-hooks/set-state-in-effect lint on mount (round 30 P2 #12). Deferred (need larger surgery / out of scope for this round): P1 #4 native_path_lease for diffusion local-path loads P1 #7-#10 helper/advisor + public-start window mutual lock symmetry Tests: 98 targeted (diffusion + cached_gguf + inference_validation) pass locally; frontend npm run typecheck passes.
This commit is contained in:
parent
b8152a5cec
commit
3b60d40f92
4 changed files with 63 additions and 1 deletions
|
|
@ -800,6 +800,23 @@ class DiffusionBackend:
|
|||
"loading an image model."
|
||||
) from exc
|
||||
|
||||
# Round 30 P1 #11: also preflight transformers + accelerate
|
||||
# BEFORE any destructive unload. Diffusers can expose stub
|
||||
# pipeline classes when transformers is missing or broken, so
|
||||
# the load would otherwise tear down chat first and fail
|
||||
# later inside from_pretrained. Use find_spec (no module
|
||||
# execution) so test environments that stub these modules
|
||||
# still pass the preflight without us actually importing them.
|
||||
import importlib.util as _ilu
|
||||
for _mod in ("transformers", "accelerate"):
|
||||
if _ilu.find_spec(_mod) is None:
|
||||
raise RuntimeError(
|
||||
"Diffusion image generation requires the Studio torch "
|
||||
f"runtime. Missing dependency: {_mod}. Install the "
|
||||
"Studio torch runtime (re-run setup.sh / install.ps1) "
|
||||
"before loading an image model."
|
||||
)
|
||||
|
||||
fam = detect_family(repo_id, override_family = family_override)
|
||||
if fam is None:
|
||||
# Round 22 P2 #4: route the repo label through
|
||||
|
|
|
|||
|
|
@ -119,6 +119,37 @@ class SeedInspectUploadRequest(BaseModel):
|
|||
unstructured_chunk_size: int | None = Field(default = None, ge = 1, le = 20000)
|
||||
unstructured_chunk_overlap: int | None = Field(default = None, ge = 0, le = 20000)
|
||||
|
||||
# Round 30 P1 #6: filename / file_names are reflected as dataset
|
||||
# names + error/log messages; harden them the same way the sibling
|
||||
# SeedInspectRequest hardens dataset_name.
|
||||
@field_validator("filename")
|
||||
@classmethod
|
||||
def _no_filename_control_chars(cls, v, info):
|
||||
return _no_control_chars(v, info.field_name)
|
||||
|
||||
@field_validator("filename")
|
||||
@classmethod
|
||||
def _no_filename_embedded_hf_tokens(cls, v, info):
|
||||
return _reject_embedded_hf_token(v, info.field_name)
|
||||
|
||||
@field_validator("file_names")
|
||||
@classmethod
|
||||
def _no_file_names_control_chars(cls, v):
|
||||
if v is None:
|
||||
return v
|
||||
for i, entry in enumerate(v):
|
||||
_no_control_chars(entry, f"file_names[{i}]")
|
||||
return v
|
||||
|
||||
@field_validator("file_names")
|
||||
@classmethod
|
||||
def _no_file_names_embedded_hf_tokens(cls, v):
|
||||
if v is None:
|
||||
return v
|
||||
for i, entry in enumerate(v):
|
||||
_reject_embedded_hf_token(entry, f"file_names[{i}]")
|
||||
return v
|
||||
|
||||
@model_validator(mode = "after")
|
||||
def _check_mutual_exclusivity(self) -> "SeedInspectUploadRequest":
|
||||
has_legacy = self.content_base64 is not None
|
||||
|
|
|
|||
|
|
@ -218,6 +218,14 @@ class ExportGGUFRequest(BaseModel):
|
|||
def _no_quantization_control_chars(cls, v, info):
|
||||
return _no_control_chars(v, info.field_name)
|
||||
|
||||
# Round 30 P1 #5: quantization_method is forwarded into worker
|
||||
# command lines and reflected in error / success text, so also
|
||||
# reject embedded HF tokens to mirror the repo_id hardening.
|
||||
@field_validator("quantization_method")
|
||||
@classmethod
|
||||
def _no_quantization_embedded_hf_tokens(cls, v, info):
|
||||
return _reject_embedded_hf_token(v, info.field_name)
|
||||
|
||||
|
||||
class ExportLoRAAdapterRequest(ExportCommonOptions):
|
||||
"""Request for exporting only the LoRA adapter (not merged)."""
|
||||
|
|
|
|||
|
|
@ -145,7 +145,13 @@ export function ImagesPage() {
|
|||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
void refreshStatus();
|
||||
// Round 30 P2 #12: defer the first refreshStatus call via
|
||||
// queueMicrotask so the synchronous setRefreshingStatus(true)
|
||||
// inside it does not trip the react-hooks/set-state-in-effect
|
||||
// lint rule on the mount render.
|
||||
queueMicrotask(() => {
|
||||
void refreshStatus();
|
||||
});
|
||||
}, [refreshStatus]);
|
||||
|
||||
// Round 27 P2: when the backend is mid-load (is_loading=true) the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue