lunarflu HF Staff commited on
Commit
6c32dc3
·
1 Parent(s): 039a7f6

Synced repo using 'sync_with_huggingface' Github Action

Browse files
Files changed (2) hide show
  1. app.py +301 -0
  2. requirements.txt +1 -1
app.py CHANGED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import glob
3
+ import os
4
+ import pathlib
5
+ import random
6
+ import threading
7
+
8
+ import gradio as gr
9
+ import discord
10
+ from gradio_client import Client
11
+ from PIL import Image
12
+ from discord.ext import commands
13
+
14
+ from discord.ui import Button, View
15
+
16
+ # test2
17
+
18
+ HF_TOKEN = os.getenv("HF_TOKEN")
19
+ deepfloydif_client = Client("huggingface-projects/IF", HF_TOKEN)
20
+ DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
21
+ intents = discord.Intents.all()
22
+ bot = commands.Bot(command_prefix="/", intents=intents)
23
+
24
+
25
+ @bot.event
26
+ async def on_ready():
27
+ print(f"Logged in as {bot.user} (ID: {bot.user.id})")
28
+ synced = await bot.tree.sync()
29
+ print(f"Synced commands: {', '.join([s.name for s in synced])}.")
30
+ print("------")
31
+
32
+
33
+ @bot.hybrid_command(
34
+ name="deepfloydif",
35
+ description="Enter a prompt to generate an image! Can generate realistic text, too!",
36
+ )
37
+ async def deepfloydif(ctx, prompt: str):
38
+ """DeepfloydIF stage 1 generation"""
39
+ try:
40
+ await deepfloydif_generate64(ctx, prompt)
41
+ except Exception as e:
42
+ print(f"Error: {e}")
43
+
44
+
45
+ def deepfloydif_generate64_inference(prompt):
46
+ """Generates four images based on a prompt"""
47
+ negative_prompt = ""
48
+ seed = random.randint(0, 1000)
49
+ number_of_images = 4
50
+ guidance_scale = 7
51
+ custom_timesteps_1 = "smart50"
52
+ number_of_inference_steps = 50
53
+ (
54
+ stage_1_images,
55
+ stage_1_param_path,
56
+ path_for_upscale256_upscaling,
57
+ ) = deepfloydif_client.predict(
58
+ prompt,
59
+ negative_prompt,
60
+ seed,
61
+ number_of_images,
62
+ guidance_scale,
63
+ custom_timesteps_1,
64
+ number_of_inference_steps,
65
+ api_name="/generate64",
66
+ )
67
+ return [stage_1_images, stage_1_param_path, path_for_upscale256_upscaling]
68
+
69
+
70
+ def deepfloydif_upscale256_inference(index, path_for_upscale256_upscaling):
71
+ """Upscales one of the images from deepfloydif_generate64_inference based on the chosen index"""
72
+ selected_index_for_upscale256 = index
73
+ seed_2 = 0
74
+ guidance_scale_2 = 4
75
+ custom_timesteps_2 = "smart50"
76
+ number_of_inference_steps_2 = 50
77
+ result_path = deepfloydif_client.predict(
78
+ path_for_upscale256_upscaling,
79
+ selected_index_for_upscale256,
80
+ seed_2,
81
+ guidance_scale_2,
82
+ custom_timesteps_2,
83
+ number_of_inference_steps_2,
84
+ api_name="/upscale256",
85
+ )
86
+ return result_path
87
+
88
+
89
+ def deepfloydif_upscale1024_inference(index, path_for_upscale256_upscaling, prompt):
90
+ """Upscales to stage 2, then stage 3"""
91
+ selected_index_for_upscale256 = index
92
+ seed_2 = 0 # default seed for stage 2 256 upscaling
93
+ guidance_scale_2 = 4 # default for stage 2
94
+ custom_timesteps_2 = "smart50" # default for stage 2
95
+ number_of_inference_steps_2 = 50 # default for stage 2
96
+ negative_prompt = "" # empty (not used, could add in the future)
97
+
98
+ seed_3 = 0 # default for stage 3 1024 upscaling
99
+ guidance_scale_3 = 9 # default for stage 3
100
+ number_of_inference_steps_3 = 40 # default for stage 3
101
+
102
+ result_path = deepfloydif_client.predict(
103
+ path_for_upscale256_upscaling,
104
+ selected_index_for_upscale256,
105
+ seed_2,
106
+ guidance_scale_2,
107
+ custom_timesteps_2,
108
+ number_of_inference_steps_2,
109
+ prompt,
110
+ negative_prompt,
111
+ seed_3,
112
+ guidance_scale_3,
113
+ number_of_inference_steps_3,
114
+ api_name="/upscale1024",
115
+ )
116
+ return result_path
117
+
118
+
119
+ def load_image(png_files, stage_1_images):
120
+ """Opens images as variables so we can combine them later"""
121
+ results = []
122
+ for file in png_files:
123
+ png_path = os.path.join(stage_1_images, file)
124
+ results.append(Image.open(png_path))
125
+ return results
126
+
127
+
128
+ def combine_images(png_files, stage_1_images, partial_path):
129
+ if os.environ.get("TEST_ENV") == "True":
130
+ print("Combining images for deepfloydif_generate64")
131
+ images = load_image(png_files, stage_1_images)
132
+ combined_image = Image.new("RGB", (images[0].width * 2, images[0].height * 2))
133
+ combined_image.paste(images[0], (0, 0))
134
+ combined_image.paste(images[1], (images[0].width, 0))
135
+ combined_image.paste(images[2], (0, images[0].height))
136
+ combined_image.paste(images[3], (images[0].width, images[0].height))
137
+ combined_image_path = os.path.join(stage_1_images, f"{partial_path}.png")
138
+ combined_image.save(combined_image_path)
139
+ return combined_image_path
140
+
141
+
142
+ async def deepfloydif_generate64(ctx, prompt):
143
+ """DeepfloydIF command (generate images with realistic text using slash commands)"""
144
+ try:
145
+ channel = ctx.channel
146
+ # interaction.response message can't be used to create a thread, so we create another message
147
+ message = await ctx.send(f"**{prompt}** - {ctx.author.mention} (generating...)")
148
+
149
+ loop = asyncio.get_running_loop()
150
+ result = await loop.run_in_executor(None, deepfloydif_generate64_inference, prompt)
151
+ stage_1_images = result[0]
152
+ path_for_upscale256_upscaling = result[2]
153
+
154
+ partial_path = pathlib.Path(path_for_upscale256_upscaling).name
155
+ png_files = list(glob.glob(f"{stage_1_images}/**/*.png"))
156
+
157
+ if png_files:
158
+ await message.delete()
159
+ combined_image_path = combine_images(png_files, stage_1_images, partial_path)
160
+ if os.environ.get("TEST_ENV") == "True":
161
+ print("Images combined for deepfloydif_generate64")
162
+
163
+ with Image.open(combined_image_path) as img:
164
+ width, height = img.size
165
+ new_width = width * 3
166
+ new_height = height * 3
167
+ resized_img = img.resize((new_width, new_height))
168
+ x2_combined_image_path = combined_image_path
169
+ resized_img.save(x2_combined_image_path)
170
+
171
+ # making image bigger, more readable
172
+ with open(x2_combined_image_path, "rb") as f: # was combined_image_path
173
+ button1 = Button(custom_id="0", emoji="↖")
174
+ button2 = Button(custom_id="1", emoji="↗")
175
+ button3 = Button(custom_id="2", emoji="↙")
176
+ button4 = Button(custom_id="3", emoji="↘")
177
+
178
+ async def button_callback(interaction):
179
+ index = int(interaction.data["custom_id"]) # 0,1,2,3
180
+
181
+ await interaction.response.send_message(
182
+ f"{interaction.user.mention} (upscaling...)", ephemeral=True
183
+ )
184
+ result_path = await deepfloydif_upscale256(index, path_for_upscale256_upscaling)
185
+
186
+ # create and use upscale 1024 button
187
+ with open(result_path, "rb") as f:
188
+ upscale1024 = Button(label="High-quality upscale (x4)", custom_id=str(index))
189
+ upscale1024.callback = upscale1024_callback
190
+ view = View(timeout=None)
191
+ view.add_item(upscale1024)
192
+
193
+ await interaction.delete_original_response()
194
+ await channel.send(
195
+ content=(
196
+ f"{interaction.user.mention} Here is the upscaled image! Click the button"
197
+ " to upscale even more!"
198
+ ),
199
+ file=discord.File(f, f"{prompt}.png"),
200
+ view=view,
201
+ )
202
+
203
+ async def upscale1024_callback(interaction):
204
+ index = int(interaction.data["custom_id"])
205
+
206
+ await interaction.response.send_message(
207
+ f"{interaction.user.mention} (upscaling...)", ephemeral=True
208
+ )
209
+ result_path = await deepfloydif_upscale1024(index, path_for_upscale256_upscaling, prompt)
210
+
211
+ with open(result_path, "rb") as f:
212
+ await interaction.delete_original_response()
213
+ await channel.send(
214
+ content=f"{interaction.user.mention} Here's your high-quality x16 image!",
215
+ file=discord.File(f, f"{prompt}.png"),
216
+ )
217
+
218
+ button1.callback = button_callback
219
+ button2.callback = button_callback
220
+ button3.callback = button_callback
221
+ button4.callback = button_callback
222
+
223
+ view = View(timeout=None)
224
+ view.add_item(button1)
225
+ view.add_item(button2)
226
+ view.add_item(button3)
227
+ view.add_item(button4)
228
+
229
+ # could store this message as combined_image_dfif in case it's useful for future testing
230
+ await channel.send(
231
+ f"**{prompt}** - {ctx.author.mention} Click a button to upscale! (make larger + enhance quality)",
232
+ file=discord.File(f, f"{partial_path}.png"),
233
+ view=view,
234
+ )
235
+ else:
236
+ await ctx.send(f"{ctx.author.mention} No PNG files were found, cannot post them!")
237
+
238
+ except Exception as e:
239
+ print(f"Error: {e}")
240
+
241
+
242
+ async def deepfloydif_upscale256(index: int, path_for_upscale256_upscaling):
243
+ """upscaling function for images generated using /deepfloydif"""
244
+ try:
245
+ loop = asyncio.get_running_loop()
246
+ result_path = await loop.run_in_executor(
247
+ None, deepfloydif_upscale256_inference, index, path_for_upscale256_upscaling
248
+ )
249
+ return result_path
250
+
251
+ except Exception as e:
252
+ print(f"Error: {e}")
253
+
254
+
255
+ async def deepfloydif_upscale1024(index: int, path_for_upscale256_upscaling, prompt):
256
+ """upscaling function for images generated using /deepfloydif"""
257
+ try:
258
+ loop = asyncio.get_running_loop()
259
+ result_path = await loop.run_in_executor(
260
+ None, deepfloydif_upscale1024_inference, index, path_for_upscale256_upscaling, prompt
261
+ )
262
+ return result_path
263
+
264
+ except Exception as e:
265
+ print(f"Error: {e}")
266
+
267
+
268
+ def run_bot():
269
+ bot.run(DISCORD_TOKEN)
270
+
271
+
272
+ threading.Thread(target=run_bot).start()
273
+
274
+
275
+ welcome_message = """
276
+ ## Add this bot to your server by clicking this link:
277
+
278
+ https://discord.com/api/oauth2/authorize?client_id=1154395078735953930&permissions=51200&scope=bot
279
+
280
+ ## How to use it?
281
+
282
+ The bot can be triggered via `/deepfloydif` followed by your text prompt.
283
+
284
+ This will generate images based on the text prompt. You can upscale the images using the buttons up to 16x!
285
+
286
+ ⚠️ Note ⚠️: Please make sure this bot's command does have the same name as another command in your server.
287
+
288
+ ⚠️ Note ⚠️: Bot commands do not work in DMs with the bot as of now.
289
+ """
290
+
291
+
292
+ with gr.Blocks() as demo:
293
+ gr.Markdown(f"""
294
+ # Discord bot of https://huggingface.co/spaces/DeepFloyd/IF
295
+ {welcome_message}
296
+ """)
297
+
298
+
299
+ demo.queue(concurrency_count=100)
300
+ demo.queue(max_size=100)
301
+ demo.launch()
requirements.txt CHANGED
@@ -1,2 +1,2 @@
1
  discord.py
2
- gradio
 
1
  discord.py
2
+ gradio