Currently, HF is buggy.

#4
by John6666 - opened

https://huggingface.co/spaces/zero-gpu-explorers/README/discussions/104
Hello.
HF is currently debugging several huge bugs.
Especially Zero GPU and Diffusers projects that seem to be related to stablepy also.
Workarounds on the user side:

  • Comment out Examples (especially None value) of Gradio
  • Be careful with functions with @spaces decorators
  • Also add @spaces decorator when loading model

Thanks for the heads-up @John6666
I’ve made some changes and will keep your tips in mind

Thank you for always maintaining the library.😸
I will close the Discussion.

BTW, I wonder if streamtest is going away and gone without being officially merged...
I've moved to dev2, but I've seen a few people using DiffuseCraft, which is a streamtest-only implementation version (yield images, seed).
Well, I'm sure it will be fixed in sync if they haven't modified it too much... just wondering.

John6666 changed discussion status to closed

Hello, I have added the function to the main branch

Hi, Thanks for the contact!
I'll try to transplant it.

Successfully confirmed that True/False in image_previews changes the number of return values (3 if on). However, since the Zero GPU space has recently been sped up, the step is often completed before the previews appear. (Like noise -> complete). It would be helpful to have Seed returned.
This would not be a problem for anyone using either the old or new implementation. Thanks.

https://huggingface.co/posts/cbensimon/747180194960645
The HF bug is about 70% fixed, but it's still there, and it's easy to have trouble with CUDA onloading and offloading, especially after starting the demo. stablepy is probably able to work around it thanks to frequent offloading, but libraries that assume only a CUDA environment are in trouble. If the tensor straddles the CPU and GPU, the program is sure to die.

By the way, this is totally unrelated.
It seems to be customary for Civitai and others to write metadata into image files.
I've added my own code for an image generation space that uses Serverless Inference, but as far as DiffuseCraft is concerned, I'd like to keep in line with the original as much as possible.

Although it would be so much easier if stablepy returned it, since stablepy returns images, not image files (And it should be.), I'm thinking it would be just before or after the yield in DiffuseCraft's app.py, but the timing is more difficult than I thought, especially considering the stream of the yield, even if it ends with a return...
Any ideas?

The metadata looks like this, which is probably originally WebUI's own format, so there should be no strict definition.
https://huggingface.co/spaces/cagliostrolab/animagine-xl-3.1/blob/main/app.py
https://huggingface.co/spaces/cagliostrolab/animagine-xl-3.1/blob/main/utils.py

    metadata = {
        "prompt": prompt,
        "negative_prompt": negative_prompt,
        "resolution": f"{width} x {height}",
        "guidance_scale": guidance_scale,
        "num_inference_steps": num_inference_steps,
        "seed": seed,
        "sampler": sampler,
        "sdxl_style": style_selector,
        "add_quality_tags": add_quality_tags,
        "quality_tags": quality_selector,
    }

        metadata["use_upscaler"] = None
        metadata["Model"] = {
            "Model": DESCRIPTION,
            "Model hash": "e3c47aedb0",
        }

def save_image(image, metadata, output_dir, is_colab):
    if is_colab:
        current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"image_{current_time}.png"   
    else:
        filename = str(uuid.uuid4()) + ".png"
    os.makedirs(output_dir, exist_ok=True)
    filepath = os.path.join(output_dir, filename)
    metadata_str = json.dumps(metadata)
    info = PngImagePlugin.PngInfo()
    info.add_text("metadata", metadata_str)
    image.save(filepath, "PNG", pnginfo=info)
    return filepath

My version

https://huggingface.co/spaces/John6666/flux-lora-the-explorer/blob/main/mod.py

def save_image(image, savefile, modelname, prompt, height, width, steps, cfg, seed):
    import uuid
    from PIL import Image, PngImagePlugin
    import json
    try:
        if savefile is None: savefile = f"{modelname.split('/')[-1]}_{str(uuid.uuid4())}.png"
        metadata = {"prompt": prompt, "Model": {"Model": modelname.split("/")[-1]}}
        metadata["num_inference_steps"] = steps
        metadata["guidance_scale"] = cfg
        metadata["seed"] = seed
        metadata["resolution"] = f"{width} x {height}"
        metadata_str = json.dumps(metadata)
        info = PngImagePlugin.PngInfo()
        info.add_text("metadata", metadata_str)
        image.save(savefile, "PNG", pnginfo=info)
        return str(Path(savefile).resolve())
    except Exception as e:
        print(f"Failed to save image file: {e}")
        raise Exception(f"Failed to save image file:") from e

I'm setting up a lighter stream to improve performance. For the metadata, I'm currently using a plain text format like in automatic1111, but I might switch to a dictionary format like you suggested.
In the yield, I use if image_path: to identify the last loop for returning the metadata. I'm not sure if this will be helpful to you, though

I'm setting up a lighter stream to improve performance.

Preview is now perfect.

For the metadata, I'm currently using a plain text format like in automatic1111,

I think A1111 is more standard. You have already written...

I use if image_path: to identify the last loop for returning the metadata.

It can be a great help!

P.S.
The metadata is then successfully embedded.
Since Gradio's Image and Gallery components do not destroy the image metadata, I decided to insert the processing in this line, a little wildly, so that the GUI side does not need to be modified.
This is easy enough to rewrite in the event of a DiffuseCraft update.
Thank you very much!🤗
https://huggingface.co/spaces/John6666/DiffuseCraftMod

from PIL import Image
def save_images(images: list[Image.Image], metadatas: list[str]):
    from PIL import PngImagePlugin
    import uuid
    try:
        output_images = []
        for image, metadata in zip(images, metadatas):
            info = PngImagePlugin.PngInfo()
            info.add_text("metadata", metadata)
            savefile = f"{str(uuid.uuid4())}.png"
            image.save(savefile, "PNG", pnginfo=info)
            output_images.append(str(Path(savefile).resolve()))
        return output_images
    except Exception as e:
        print(f"Failed to save image file: {e}")
        raise Exception(f"Failed to save image file:") from e

                info_state = info_state + "<br>" + "GENERATION DATA:<br>" + "<br>-------<br>".join(metadata).replace("\n", "<br>")

                img = save_images(img, metadata)
                
            yield img, info_state

20240920_163052_1.png

Owner

Sorry for the late response :D that’s actually expected behavior. Hires tends to refine the whole image, so it ends up ignoring the mask. A little workaround is to set the Hires steps to 0, that way you don’t get too many unwanted changes in the final image.

Thanks! Ah, I see. That's the kind of problem it was.

BTW, an unrelated ongoing (?) weird issue. Maybe server settings or front-end glitch.
https://huggingface.co/spaces/John6666/DiffuseCraftMod/discussions/23#68cc01a87cbd3b9ae5c10efc

Owner

Yep, I’ve noticed that too. For now I turned off xet with HF_HUB_DISABLE_XET to see if it helps.

Oh. The symptom is “not rendering,” but it hasn't happened on my setup (Windows, Chrome, occasionally Firefox) so far...
Plus, looking at the runtime logs, other people are using it successfully. There's probably no issue on the backend side. But some people still can't use it.
So I think it's similar to those bugs we had before, like environment-dependent routing, cookies, or the old ssr_mode=True bug.
In other words... while there might be workarounds, the only real solution is probably to wait for HF to fix it.🥶

Owner

Maybe we just need to wait.
I noticed the spaces module got updated recently and now I can’t see the logs for failed or aborted GPU tasks, same thing happening to you?

Yeah. Maybe need to wait.

I didn't notice about error messages matter, so I just experimented with it.
I think it is no longer aborting when I specify a duration value that is clearly not enough for the process...
So, no error message so far...😅

I may have found part of the cause. The dependencies for the Gradio client have changed significantly for Gradio 6.
I think the impact of websocket is mainly related to Gradio 3, but something else might be affecting 4 or 5...

Owner

I didn’t notice they’re already planning a version 6 and I just updated to 5 😬

Sign up or log in to comment