Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| """Strict local FLUX backend. | |
| This module is deliberately import-safe: it should not require torch/diffusers unless | |
| its functions are called. The backend refuses to synthesize or fetch fallback tiles. | |
| To enable real FLUX tile generation, point P5_FLUX_MODEL_DIR at a local diffusers | |
| checkpoint directory and install the optional deps (torch, diffusers, transformers). | |
| """ | |
| from dataclasses import dataclass | |
| from pathlib import Path | |
| import os | |
| import time | |
| class FluxConfig: | |
| model_id: str = "black-forest-labs/FLUX.2-klein-base-4B" | |
| model_dir: str = "" | |
| steps: int = 4 | |
| guidance_scale: float | None = None | |
| seed: int = 0 | |
| height: int = 512 | |
| width: int = 512 | |
| def _load_config(size: int = 512) -> FluxConfig: | |
| model_id = os.environ.get("P5_FLUX_MODEL_ID", "black-forest-labs/FLUX.2-klein-base-4B").strip() | |
| model_dir = os.environ.get("P5_FLUX_MODEL_DIR", "").strip() | |
| steps = int(os.environ.get("P5_FLUX_STEPS", "4")) | |
| guidance_raw = os.environ.get("P5_FLUX_GUIDANCE", "").strip() | |
| guidance_scale = float(guidance_raw) if guidance_raw else None | |
| seed = int(os.environ.get("P5_FLUX_SEED", "0")) | |
| return FluxConfig( | |
| model_id=model_id, | |
| model_dir=model_dir, | |
| steps=steps, | |
| guidance_scale=guidance_scale, | |
| seed=seed, | |
| height=size, | |
| width=size, | |
| ) | |
| def available() -> bool: | |
| """Heuristic: do we have a local directory pointer for FLUX weights?""" | |
| model_dir = os.environ.get("P5_FLUX_MODEL_DIR", "").strip() | |
| return bool(model_dir and Path(model_dir).exists()) | |
| def try_generate(prompt: str, size: int = 512): | |
| """Generate a tile with locally available FLUX weights. | |
| Returns: | |
| (image, meta) where image is a PIL Image, meta includes backend details. | |
| Raises: | |
| RuntimeError if optional deps are missing or the local model isn't usable. | |
| """ | |
| cfg = _load_config(size=size) | |
| started_at = time.perf_counter() | |
| # Import lazily so unit tests and lightweight installs don't pay torch/diffusers. | |
| try: | |
| import torch # type: ignore | |
| except Exception as exc: | |
| raise RuntimeError("torch is not installed; cannot run FLUX backend") from exc | |
| try: | |
| import diffusers # type: ignore | |
| except Exception as exc: | |
| raise RuntimeError("diffusers is not installed; cannot run FLUX backend") from exc | |
| if not cfg.model_dir: | |
| raise RuntimeError("P5_FLUX_MODEL_DIR is not set; real FLUX generation requires a local checkpoint directory") | |
| model_ref: str = cfg.model_dir | |
| # Prefer the explicit Flux2KleinPipeline if present; otherwise fall back to FluxPipeline or DiffusionPipeline. | |
| PipelineCls = getattr(diffusers, "Flux2KleinPipeline", None) | |
| if PipelineCls is None: | |
| PipelineCls = getattr(diffusers, "FluxPipeline", None) | |
| if PipelineCls is None: | |
| from diffusers import DiffusionPipeline as PipelineCls # type: ignore | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| dtype = torch.float16 if device == "cuda" else torch.float32 | |
| # Force offline behavior. | |
| os.environ.setdefault("HF_HUB_OFFLINE", "1") | |
| os.environ.setdefault("TRANSFORMERS_OFFLINE", "1") | |
| pipe = PipelineCls.from_pretrained( | |
| model_ref, | |
| torch_dtype=dtype, | |
| local_files_only=True, | |
| ) | |
| pipe = pipe.to(device) | |
| generator = torch.Generator(device=device) | |
| generator.manual_seed(cfg.seed) | |
| kwargs = { | |
| "prompt": prompt, | |
| "num_inference_steps": cfg.steps, | |
| "height": cfg.height, | |
| "width": cfg.width, | |
| "generator": generator, | |
| } | |
| if cfg.guidance_scale is not None: | |
| kwargs["guidance_scale"] = cfg.guidance_scale | |
| result = pipe(**kwargs) | |
| images = getattr(result, "images", None) | |
| if not images: | |
| raise RuntimeError("FLUX pipeline returned no images") | |
| image = images[0] | |
| elapsed_ms = round((time.perf_counter() - started_at) * 1000.0, 2) | |
| generation_stats = { | |
| "steps": cfg.steps, | |
| "guidance_scale": cfg.guidance_scale, | |
| "seed": cfg.seed, | |
| "height": cfg.height, | |
| "width": cfg.width, | |
| "elapsed_ms": elapsed_ms, | |
| "device": device, | |
| "dtype": str(dtype), | |
| } | |
| meta = { | |
| "adapter_name": "flux-diffusers", | |
| "backend": "flux-diffusers", | |
| "device": device, | |
| "dtype": str(dtype), | |
| "model_dir": cfg.model_dir, | |
| "model_id": cfg.model_id, | |
| "generation_stats": generation_stats, | |
| } | |
| return image, meta | |