John6666 commited on
Commit
a009ad0
·
verified ·
1 Parent(s): d00ca06

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +1 -1
  2. app.py +89 -126
  3. hft2is.py +232 -0
  4. requirements.txt +1 -12
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 🪈
4
  colorFrom: purple
5
  colorTo: yellow
6
  sdk: gradio
7
- sdk_version: 5.4.0
8
  app_file: app.py
9
  pinned: false
10
  license: other
 
4
  colorFrom: purple
5
  colorTo: yellow
6
  sdk: gradio
7
+ sdk_version: 5.14.0
8
  app_file: app.py
9
  pinned: false
10
  license: other
app.py CHANGED
@@ -1,126 +1,89 @@
1
- import os
2
- import spaces
3
- import torch
4
- from diffusers import StableDiffusionXLPipeline, EulerAncestralDiscreteScheduler
5
- import gradio as gr
6
- import random
7
- import tqdm
8
-
9
- # Enable TQDM progress tracking
10
- tqdm.monitor_interval = 0
11
-
12
- # Load the diffusion pipeline
13
- pipe = StableDiffusionXLPipeline.from_pretrained(
14
- "kayfahaarukku/UrangDiffusion-2.0",
15
- torch_dtype=torch.float16,
16
- custom_pipeline="lpw_stable_diffusion_xl",
17
- )
18
- pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
19
-
20
- # Function to generate an image
21
- @spaces.GPU # Adjust the duration as needed
22
- def generate_image(prompt, negative_prompt, use_defaults, resolution, guidance_scale, num_inference_steps, seed, randomize_seed, progress=gr.Progress()):
23
- pipe.to('cuda') # Move the model to GPU when the function is called
24
-
25
- if randomize_seed:
26
- seed = random.randint(0, 99999999)
27
- if use_defaults:
28
- prompt = f"{prompt}, best quality, amazing quality, very aesthetic"
29
- negative_prompt = f"nsfw, lowres, (bad), text, error, fewer, extra, missing, worst quality, jpeg artifacts, low quality, watermark, unfinished, displeasing, oldest, early, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract], {negative_prompt}"
30
- generator = torch.manual_seed(seed)
31
-
32
- def callback(step, timestep, latents):
33
- progress(step / num_inference_steps)
34
- return
35
-
36
- width, height = map(int, resolution.split('x'))
37
- image = pipe(
38
- prompt,
39
- negative_prompt=negative_prompt,
40
- width=width,
41
- height=height,
42
- guidance_scale=guidance_scale,
43
- num_inference_steps=num_inference_steps,
44
- generator=generator,
45
- callback=callback,
46
- callback_steps=1
47
- ).images[0]
48
-
49
- torch.cuda.empty_cache()
50
-
51
- metadata_text = f"{prompt}\nNegative prompt: {negative_prompt}\nSteps: {num_inference_steps}, Sampler: Euler a, Size: {width}x{height}, Seed: {seed}, CFG scale: {guidance_scale}"
52
-
53
- return image, seed, metadata_text
54
-
55
- # Define Gradio interface
56
- def interface_fn(prompt, negative_prompt, use_defaults, resolution, guidance_scale, num_inference_steps, seed, randomize_seed, progress=gr.Progress()):
57
- image, seed, metadata_text = generate_image(prompt, negative_prompt, use_defaults, resolution, guidance_scale, num_inference_steps, seed, randomize_seed, progress)
58
- return image, seed, gr.update(value=metadata_text)
59
-
60
- def reset_inputs():
61
- return gr.update(value=''), gr.update(value=''), gr.update(value=True), gr.update(value='832x1216'), gr.update(value=7), gr.update(value=28), gr.update(value=0), gr.update(value=True), gr.update(value='')
62
-
63
- with gr.Blocks(title="UrangDiffusion 2.0 Demo", theme="NoCrypt/miku@1.2.1") as demo:
64
- gr.HTML(
65
- "<h1>UrangDiffusion 2.0 Demo</h1>"
66
- "This demo is intended to showcase what the model is capable of and is not intended to be the main generation platform. Results produced with Diffusers are not the best, and it's highly recommended for you to get the model running inside Stable Diffusion WebUI or ComfyUI."
67
- )
68
- with gr.Row():
69
- with gr.Column():
70
- prompt_input = gr.Textbox(lines=2, placeholder="Enter prompt here", label="Prompt")
71
- negative_prompt_input = gr.Textbox(lines=2, placeholder="Enter negative prompt here", label="Negative Prompt")
72
- use_defaults_input = gr.Checkbox(label="Use Default Quality Tags and Negative Prompt", value=True)
73
- resolution_input = gr.Radio(
74
- choices=[
75
- "1024x1024", "1152x896", "896x1152", "1216x832", "832x1216",
76
- "1344x768", "768x1344", "1536x640", "640x1536"
77
- ],
78
- label="Resolution",
79
- value="832x1216"
80
- )
81
- guidance_scale_input = gr.Slider(minimum=1, maximum=20, step=0.5, label="Guidance Scale", value=7)
82
- num_inference_steps_input = gr.Slider(minimum=1, maximum=100, step=1, label="Number of Inference Steps", value=28)
83
- seed_input = gr.Slider(minimum=0, maximum=999999999, step=1, label="Seed", value=0, interactive=True)
84
- randomize_seed_input = gr.Checkbox(label="Randomize Seed", value=True)
85
- generate_button = gr.Button("Generate")
86
- reset_button = gr.Button("Reset")
87
-
88
- with gr.Column():
89
- output_image = gr.Image(type="pil", label="Generated Image")
90
- with gr.Accordion("Parameters", open=False):
91
- gr.Markdown(
92
- """
93
- This parameter is compatible with Stable Diffusion WebUI's parameter importer.
94
- """
95
- )
96
- metadata_textbox = gr.Textbox(lines=6, label="Image Parameters", interactive=False, max_lines=6)
97
- gr.Markdown(
98
- """
99
- ### Recommended prompt formatting:
100
- `1girl/1boy, character name, from what series, everything else in any order, best quality, amazing quality, very aesthetic,`
101
-
102
- **PS:** `best quality, amazing quality, very aesthetic,` is automatically added when "Use Default Quality Tags and Negative Prompt" is enabled
103
-
104
- ### Recommended settings:
105
- - Steps: 25-30
106
- - CFG: 5-7
107
- """
108
- )
109
-
110
- generate_button.click(
111
- interface_fn,
112
- inputs=[
113
- prompt_input, negative_prompt_input, use_defaults_input, resolution_input, guidance_scale_input, num_inference_steps_input, seed_input, randomize_seed_input
114
- ],
115
- outputs=[output_image, seed_input, metadata_textbox]
116
- )
117
-
118
- reset_button.click(
119
- reset_inputs,
120
- inputs=[],
121
- outputs=[
122
- prompt_input, negative_prompt_input, use_defaults_input, resolution_input, guidance_scale_input, num_inference_steps_input, seed_input, randomize_seed_input, metadata_textbox
123
- ]
124
- )
125
-
126
- demo.queue(max_size=20).launch(share=False)
 
1
+ import spaces
2
+ import gradio as gr
3
+ from hft2is import load_models, warm_models, generate_image_hf
4
+
5
+ MODELS = ["kayfahaarukku/UrangDiffusion-2.0", "kayfahaarukku/irAsu-1.0"]
6
+ load_models(MODELS)
7
+ warm_models(MODELS)
8
+
9
+ # Define Gradio interface
10
+ def interface_fn(prompt, negative_prompt="", use_defaults=True, resolution="832x1216", guidance_scale=7, num_inference_steps=28, seed=0, randomize_seed=True, model_name=MODELS[0], progress=gr.Progress()):
11
+ image, seed, metadata_text = generate_image_hf(model_name, prompt, negative_prompt, use_defaults, resolution, guidance_scale, num_inference_steps, seed, randomize_seed, progress)
12
+ return image, seed, gr.update(value=metadata_text)
13
+
14
+ def reset_inputs():
15
+ return gr.update(value=''), gr.update(value=''), gr.update(value=True), gr.update(value='832x1216'), gr.update(value=7), gr.update(value=28), gr.update(value=0), gr.update(value=True), gr.update(value=''), gr.update(value=MODELS[0])
16
+
17
+ with gr.Blocks(title="UrangDiffusion 2.0 Demo", theme="NoCrypt/miku@1.2.1") as demo:
18
+ gr.HTML(
19
+ "<h1>UrangDiffusion 2.0 Demo</h1>"
20
+ "This demo is intended to showcase what the model is capable of and is not intended to be the main generation platform. Results produced with Diffusers are not the best, and it's highly recommended for you to get the model running inside Stable Diffusion WebUI or ComfyUI."
21
+ )
22
+ with gr.Row():
23
+ with gr.Column():
24
+ prompt_input = gr.Textbox(lines=2, placeholder="Enter prompt here", label="Prompt")
25
+ negative_prompt_input = gr.Textbox(lines=2, placeholder="Enter negative prompt here", label="Negative Prompt")
26
+ use_defaults_input = gr.Checkbox(label="Use Default Quality Tags and Negative Prompt", value=True)
27
+ resolution_input = gr.Radio(
28
+ choices=[
29
+ "1024x1024", "1152x896", "896x1152", "1216x832", "832x1216",
30
+ "1344x768", "768x1344", "1536x640", "640x1536"
31
+ ],
32
+ label="Resolution",
33
+ value="832x1216"
34
+ )
35
+ guidance_scale_input = gr.Slider(minimum=1, maximum=20, step=0.5, label="Guidance Scale", value=7)
36
+ num_inference_steps_input = gr.Slider(minimum=1, maximum=100, step=1, label="Number of Inference Steps", value=28)
37
+ seed_input = gr.Slider(minimum=0, maximum=999999999, step=1, label="Seed", value=0, interactive=True)
38
+ randomize_seed_input = gr.Checkbox(label="Randomize Seed", value=True)
39
+ model_name = gr.Dropdown(label="Model", choices=MODELS, value=MODELS[0])
40
+ generate_button = gr.Button("Generate")
41
+ reset_button = gr.Button("Reset")
42
+
43
+ with gr.Column():
44
+ output_image = gr.Image(type="pil", label="Generated Image")
45
+ with gr.Accordion("Parameters", open=False):
46
+ gr.Markdown(
47
+ """
48
+ This parameter is compatible with Stable Diffusion WebUI's parameter importer.
49
+ """
50
+ )
51
+ metadata_textbox = gr.Textbox(lines=6, label="Image Parameters", interactive=False, max_lines=6)
52
+ gr.Markdown(
53
+ """
54
+ ### Recommended prompt formatting:
55
+ `1girl/1boy, character name, from what series, everything else in any order, best quality, amazing quality, very aesthetic,`
56
+
57
+ **PS:** `best quality, amazing quality, very aesthetic,` is automatically added when "Use Default Quality Tags and Negative Prompt" is enabled
58
+
59
+ ### Recommended settings:
60
+ - Steps: 25-30
61
+ - CFG: 5-7
62
+ """
63
+ )
64
+ examples = gr.Examples(
65
+ examples = [
66
+ ["1girl"],
67
+ ["beautiful sunset"],
68
+ ],
69
+ inputs=[prompt_input],
70
+ cache_examples=False,
71
+ )
72
+
73
+ generate_button.click(
74
+ interface_fn,
75
+ inputs=[
76
+ prompt_input, negative_prompt_input, use_defaults_input, resolution_input, guidance_scale_input, num_inference_steps_input, seed_input, randomize_seed_input, model_name,
77
+ ],
78
+ outputs=[output_image, seed_input, metadata_textbox]
79
+ )
80
+
81
+ reset_button.click(
82
+ reset_inputs,
83
+ inputs=[],
84
+ outputs=[
85
+ prompt_input, negative_prompt_input, use_defaults_input, resolution_input, guidance_scale_input, num_inference_steps_input, seed_input, randomize_seed_input, metadata_textbox, model_name,
86
+ ]
87
+ )
88
+
89
+ demo.launch(ssr_mode=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
hft2is.py ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import asyncio
3
+ from threading import RLock
4
+ from pathlib import Path
5
+ import os
6
+ from typing import Union
7
+
8
+
9
+ HF_TOKEN = os.getenv("HF_TOKEN", None)
10
+ server_timeout = 600
11
+ inference_timeout = 600
12
+
13
+
14
+ lock = RLock()
15
+ loaded_models = {}
16
+
17
+
18
+ def rename_image(image_path: Union[str, None], model_name: str, save_path: Union[str, None] = None):
19
+ import shutil
20
+ from datetime import datetime, timezone, timedelta
21
+ if image_path is None: return None
22
+ dt_now = datetime.now(timezone(timedelta(hours=9)))
23
+ filename = f"{model_name.split('/')[-1]}_{dt_now.strftime('%Y%m%d_%H%M%S')}.png"
24
+ try:
25
+ if Path(image_path).exists():
26
+ png_path = "image.png"
27
+ if str(Path(image_path).resolve()) != str(Path(png_path).resolve()): shutil.copy(image_path, png_path)
28
+ if save_path is not None:
29
+ new_path = str(Path(png_path).resolve().rename(Path(save_path).resolve()))
30
+ else:
31
+ new_path = str(Path(png_path).resolve().rename(Path(filename).resolve()))
32
+ return new_path
33
+ else:
34
+ return None
35
+ except Exception as e:
36
+ print(e)
37
+ return None
38
+
39
+
40
+ # https://github.com/gradio-app/gradio/blob/main/gradio/external.py
41
+ # https://huggingface.co/docs/huggingface_hub/package_reference/inference_client
42
+ from typing import Literal
43
+ def load_from_model(model_name: str, hf_token: Union[str, Literal[False], None] = None):
44
+ import httpx
45
+ import huggingface_hub
46
+ from gradio.exceptions import ModelNotFoundError, TooManyRequestsError
47
+ model_url = f"https://huggingface.co/{model_name}"
48
+ api_url = f"https://api-inference.huggingface.co/models/{model_name}"
49
+ print(f"Fetching model from: {model_url}")
50
+
51
+ headers = ({} if hf_token in [False, None] else {"Authorization": f"Bearer {hf_token}"})
52
+ response = httpx.request("GET", api_url, headers=headers)
53
+ if response.status_code != 200:
54
+ raise ModelNotFoundError(
55
+ f"Could not find model: {model_name}. If it is a private or gated model, please provide your Hugging Face access token (https://huggingface.co/settings/tokens) as the argument for the `hf_token` parameter."
56
+ )
57
+ p = response.json().get("pipeline_tag")
58
+ if p != "text-to-image": raise ModelNotFoundError(f"This model isn't for text-to-image or unsupported: {model_name}.")
59
+ headers["X-Wait-For-Model"] = "true"
60
+ kwargs = {}
61
+ if hf_token is not None: kwargs["token"] = hf_token
62
+ client = huggingface_hub.InferenceClient(model=model_name, headers=headers, timeout=server_timeout, **kwargs)
63
+ inputs = gr.components.Textbox(label="Input")
64
+ outputs = gr.components.Image(label="Output")
65
+ fn = client.text_to_image
66
+
67
+ def query_huggingface_inference_endpoints(*data, **kwargs):
68
+ try:
69
+ data = fn(*data, **kwargs) # type: ignore
70
+ except huggingface_hub.utils.HfHubHTTPError as e:
71
+ print(e)
72
+ if "429" in str(e): raise TooManyRequestsError() from e
73
+ except Exception as e:
74
+ print(e)
75
+ raise Exception() from e
76
+ return data
77
+
78
+ interface_info = {
79
+ "fn": query_huggingface_inference_endpoints,
80
+ "inputs": inputs,
81
+ "outputs": outputs,
82
+ "title": model_name,
83
+ }
84
+ return gr.Interface(**interface_info)
85
+
86
+
87
+ def load_model(model_name: str):
88
+ global loaded_models
89
+ global model_info_dict
90
+ if model_name in loaded_models.keys(): return loaded_models[model_name]
91
+ try:
92
+ loaded_models[model_name] = load_from_model(model_name, hf_token=HF_TOKEN)
93
+ print(f"Loaded: {model_name}")
94
+ except Exception as e:
95
+ if model_name in loaded_models.keys(): del loaded_models[model_name]
96
+ print(f"Failed to load: {model_name}")
97
+ print(e)
98
+ return None
99
+ return loaded_models[model_name]
100
+
101
+
102
+ def load_models(models: list):
103
+ for model in models:
104
+ load_model(model)
105
+
106
+
107
+ def warm_model(model_name: str):
108
+ model = load_model(model_name)
109
+ if model:
110
+ try:
111
+ print(f"Warming model: {model_name}")
112
+ infer_body(model, model_name, " ")
113
+ except Exception as e:
114
+ print(e)
115
+
116
+
117
+ def warm_models(models: list[str]):
118
+ for model in models:
119
+ asyncio.new_event_loop().run_in_executor(None, warm_model, model)
120
+
121
+
122
+ # https://huggingface.co/docs/api-inference/detailed_parameters
123
+ # https://huggingface.co/docs/huggingface_hub/package_reference/inference_client
124
+ def infer_body(client: Union[gr.Interface, object], model_str: str, prompt: str, neg_prompt: str = "",
125
+ height: int = 0, width: int = 0, steps: int = 0, cfg: int = 0, seed: int = -1):
126
+ png_path = "image.png"
127
+ kwargs = {}
128
+ if height > 0: kwargs["height"] = height
129
+ if width > 0: kwargs["width"] = width
130
+ if steps > 0: kwargs["num_inference_steps"] = steps
131
+ if cfg > 0: cfg = kwargs["guidance_scale"] = cfg
132
+ if seed == -1: kwargs["seed"] = randomize_seed()
133
+ else: kwargs["seed"] = seed
134
+ try:
135
+ if isinstance(client, gr.Interface): image = client.fn(prompt=prompt, negative_prompt=neg_prompt, **kwargs)
136
+ else: return None
137
+ if isinstance(image, tuple): return None
138
+ return save_image(image, png_path, model_str, prompt, neg_prompt, height, width, steps, cfg, seed)
139
+ except Exception as e:
140
+ print(e)
141
+ raise Exception(e) from e
142
+
143
+
144
+ async def infer(model_name: str, prompt: str, neg_prompt: str ="", height: int = 0, width: int = 0,
145
+ steps: int = 0, cfg: int = 0, seed: int = -1,
146
+ save_path: str | None = None, timeout: float = inference_timeout):
147
+ model = load_model(model_name)
148
+ if not model: return None
149
+ task = asyncio.create_task(asyncio.to_thread(infer_body, model, model_name, prompt, neg_prompt,
150
+ height, width, steps, cfg, seed))
151
+ await asyncio.sleep(0)
152
+ try:
153
+ result = await asyncio.wait_for(task, timeout=timeout)
154
+ except asyncio.TimeoutError as e:
155
+ print(e)
156
+ print(f"Task timed out: {model_name}")
157
+ if not task.done(): task.cancel()
158
+ result = None
159
+ raise Exception(f"Task timed out: {model_name}") from e
160
+ except Exception as e:
161
+ print(e)
162
+ if not task.done(): task.cancel()
163
+ result = None
164
+ raise Exception(e) from e
165
+ if task.done() and result is not None:
166
+ with lock:
167
+ image = rename_image(result, model_name, save_path)
168
+ return image
169
+ return None
170
+
171
+
172
+ def save_image(image, savefile, modelname, prompt, nprompt, height=0, width=0, steps=0, cfg=0, seed=-1):
173
+ from PIL import Image, PngImagePlugin
174
+ import json
175
+ try:
176
+ metadata = {"prompt": prompt, "negative_prompt": nprompt, "Model": {"Model": modelname.split("/")[-1]}}
177
+ if steps > 0: metadata["num_inference_steps"] = steps
178
+ if cfg > 0: metadata["guidance_scale"] = cfg
179
+ if seed != -1: metadata["seed"] = seed
180
+ if width > 0 and height > 0: metadata["resolution"] = f"{width} x {height}"
181
+ metadata_str = json.dumps(metadata)
182
+ info = PngImagePlugin.PngInfo()
183
+ info.add_text("metadata", metadata_str)
184
+ image.save(savefile, "PNG", pnginfo=info)
185
+ return str(Path(savefile).resolve())
186
+ except Exception as e:
187
+ print(f"Failed to save image file: {e}")
188
+ raise Exception(f"Failed to save image file:") from e
189
+
190
+
191
+ def randomize_seed():
192
+ from random import seed, randint
193
+ MAX_SEED = 2**32-1
194
+ seed()
195
+ rseed = randint(0, MAX_SEED)
196
+ return rseed
197
+
198
+
199
+ def gen_image(model_name: str, prompt: str, neg_prompt: str = "", height: int = 0, width: int = 0,
200
+ steps: int = 0, cfg: int = 0, seed: int = -1):
201
+ if model_name in ["NA", ""]: return gr.update()
202
+ try:
203
+ loop = asyncio.get_running_loop()
204
+ except Exception:
205
+ loop = asyncio.new_event_loop()
206
+ try:
207
+ result = loop.run_until_complete(infer(model_name, prompt, neg_prompt, height, width,
208
+ steps, cfg, seed, None, inference_timeout))
209
+ except (Exception, asyncio.CancelledError) as e:
210
+ print(e)
211
+ print(f"Task aborted: {model_name}, Error: {e}")
212
+ result = None
213
+ raise gr.Error(f"Task aborted: {model_name}, Error: {e}")
214
+ finally:
215
+ loop.close()
216
+ return result
217
+
218
+
219
+ def generate_image_hf(model_name: str, prompt: str, negative_prompt: str, use_defaults: bool, resolution: str,
220
+ guidance_scale: float, num_inference_steps: int, seed: int, randomize_seed: bool, progress=gr.Progress()):
221
+
222
+ if randomize_seed: seed = -1
223
+ if use_defaults:
224
+ prompt = f"{prompt}, best quality, amazing quality, very aesthetic"
225
+ negative_prompt = f"nsfw, lowres, (bad), text, error, fewer, extra, missing, worst quality, jpeg artifacts, low quality, watermark, unfinished, displeasing, oldest, early, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract], {negative_prompt}"
226
+
227
+ width, height = map(int, resolution.split('x'))
228
+ image = gen_image(model_name, prompt, negative_prompt, height, width, num_inference_steps, guidance_scale)
229
+
230
+ metadata_text = f"{prompt}\nNegative prompt: {negative_prompt}\nSteps: {num_inference_steps}, Sampler: Euler a, Size: {width}x{height}, Seed: {seed}, CFG scale: {guidance_scale}"
231
+
232
+ return image, seed, metadata_text
requirements.txt CHANGED
@@ -1,12 +1 @@
1
- torch==2.0.1
2
- diffusers>=0.26.3
3
- transformers==4.38.1
4
- accelerate==0.27.2
5
- safetensors>=0.3.1
6
- gradio==4.20.0
7
- tqdm==4.66.4
8
- invisible-watermark==0.2.0
9
- Pillow==10.2.0
10
- spaces==0.24.0
11
- omegaconf==2.3.0
12
- timm==0.9.10
 
1
+ huggingface_hub