Spaces:
Running on Zero
Running on Zero
| """Serverless backend using Hugging Face Inference Providers. | |
| Runs the ``dx8152/Qwen-Edit-2509-Multiple-angles`` model through the | |
| ``InferenceClient.image_to_image`` API. Requires an HF token but **no local | |
| GPU**, so it works on a basic CPU Space or from a robot-arm client machine. | |
| """ | |
| from __future__ import annotations | |
| import io | |
| from typing import Optional | |
| from PIL import Image | |
| from ..config import ANGLES_INFERENCE_MODEL | |
| from ..images import fit_image | |
| from .base import ImageEditBackend | |
| class InferenceProvidersBackend(ImageEditBackend): | |
| source = "hf_inference_providers" | |
| def __init__( | |
| self, | |
| token: str, | |
| image_size: int, | |
| provider: str = "auto", | |
| model: str = ANGLES_INFERENCE_MODEL, | |
| ) -> None: | |
| self.token = token | |
| self.image_size = image_size | |
| self.provider = provider | |
| self.model = model | |
| self._client = None | |
| def prepare(self) -> None: | |
| from huggingface_hub import InferenceClient # local import: heavy dep | |
| if not self.token or not self.token.strip(): | |
| raise RuntimeError("An HF token is required for the Inference Providers backend.") | |
| # The dx8152 multi-angle LoRA is currently served ONLY by WaveSpeed, so | |
| # provider="auto" fails to route it. Default to WaveSpeed unless the | |
| # caller explicitly pinned a different provider. | |
| provider = self.provider | |
| if provider in (None, "", "auto"): | |
| provider = "wavespeed" | |
| self._client = InferenceClient(provider=provider, api_key=self.token.strip()) | |
| def edit( | |
| self, | |
| image: Image.Image, | |
| prompt: str, | |
| seed: int, | |
| num_inference_steps: int, | |
| true_guidance_scale: float, | |
| ) -> Image.Image: | |
| base = fit_image(image.convert("RGB"), self.image_size) | |
| if not prompt.strip(): | |
| return base | |
| if self._client is None: | |
| raise RuntimeError("Backend not prepared; call prepare() first.") | |
| buffer = io.BytesIO() | |
| base.save(buffer, format="PNG") | |
| result = self._client.image_to_image( | |
| buffer.getvalue(), | |
| prompt=prompt, | |
| model=self.model, | |
| ) | |
| if not isinstance(result, Image.Image): | |
| raise RuntimeError("Inference Providers returned an unexpected response type.") | |
| # Normalise back to the requested geometry. | |
| return fit_image(result.convert("RGB"), self.image_size) | |