Download app.py from acek99/acek: direct link, hf CLI and curl.
- Browser
- Download file 3.35 kB
-
https://huggingface.co/spaces/acek99/acek/resolve/main/app.py
- Command line
-
hf download hf://spaces/acek99/acek/app.py
-
curl -L -o app.py https://huggingface.co/spaces/acek99/acek/resolve/main/app.py
3.35 kB
| """Bang Story image Space: draws clip pictures on Hugging Face ZeroGPU. | |
| Upload this file together with requirements.txt and README.md into a Gradio Space, set the Space's | |
| hardware to ZeroGPU, and Bang Story can use it as its image service — free, with no credits and no | |
| API keys. The app calls the `generate` function through the Space's Gradio API. | |
| """ | |
| import os | |
| import gradio as gr | |
| import spaces | |
| import torch | |
| from diffusers import DiffusionPipeline | |
| # Tried in order, first one that loads wins. The official repository gives the best quality but is gated: | |
| # without the licence accepted and a read token in the HF_TOKEN secret it answers 401. The open mirrors | |
| # below are the same model, so the Space still comes up instead of dying on a missing token. | |
| MODEL_CHAIN = [ | |
| os.environ.get("MODEL_ID") or "black-forest-labs/FLUX.1-schnell", | |
| "Niansuh/FLUX.1-schnell", | |
| "playgroundai/playground-v2.5-1024px-aesthetic", | |
| ] | |
| # A distilled model like schnell needs very few steps; a full pipeline needs many more. | |
| MAX_STEPS = 8 | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| def load(): | |
| """Loads the first model of the chain that works, so one blocked repository cannot kill the Space.""" | |
| last = None | |
| for model in MODEL_CHAIN: | |
| if not model: | |
| continue | |
| try: | |
| print(f"[bang-story] loading {model} ...", flush=True) | |
| pipe = DiffusionPipeline.from_pretrained(model, torch_dtype=torch.bfloat16).to(device) | |
| print(f"[bang-story] ready: {model} on {device}", flush=True) | |
| return pipe, model | |
| except Exception as e: | |
| last = e | |
| print(f"[bang-story] {model} failed: {type(e).__name__}: {e}", flush=True) | |
| raise RuntimeError(f"Tidak ada model yang bisa dimuat. Error terakhir: {last}") | |
| pipe, MODEL = load() | |
| IS_FLUX = "flux" in MODEL.lower() | |
| def generate(prompt: str, width: int = 1024, height: int = 576, steps: int = 4): | |
| """Draws one picture. Bang Story calls this through the Gradio API.""" | |
| kwargs = {"prompt": prompt, "width": int(width), "height": int(height)} | |
| if IS_FLUX: | |
| kwargs["num_inference_steps"] = max(1, min(MAX_STEPS, int(steps))) | |
| # schnell is distilled: it runs without classifier-free guidance. | |
| kwargs["guidance_scale"] = 0.0 | |
| else: | |
| kwargs["num_inference_steps"] = max(20, min(35, int(steps) * 5)) | |
| kwargs["guidance_scale"] = 7.0 | |
| return pipe(**kwargs).images[0] | |
| with gr.Blocks(title="Bang Story — Image") as demo: | |
| gr.Markdown( | |
| f"Draws the clip pictures for **Bang Story** with `{MODEL}`.\n\n" | |
| "Bang Story calls this Space from its Settings, so you normally never touch this page. " | |
| "It is left open so you can try a prompt yourself." | |
| ) | |
| prompt = gr.Textbox(label="Prompt", lines=5, placeholder="Describe the picture...") | |
| with gr.Row(): | |
| width = gr.Slider(256, 1536, value=1024, step=16, label="Width") | |
| height = gr.Slider(256, 1536, value=576, step=16, label="Height") | |
| steps = gr.Slider(1, MAX_STEPS, value=4, step=1, label="Steps") | |
| run = gr.Button("Generate", variant="primary") | |
| out = gr.Image(label="Result", type="pil") | |
| run.click(generate, [prompt, width, height, steps], out) | |
| prompt.submit(generate, [prompt, width, height, steps], out) | |
| demo.launch() | |