ginipick commited on
Commit
f308c8b
·
verified ·
1 Parent(s): 6b2fe4d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1 -353
app.py CHANGED
@@ -1,354 +1,2 @@
1
- import spaces
2
- import argparse
3
  import os
4
- import time
5
- from os import path
6
- import shutil
7
- from datetime import datetime
8
- from safetensors.torch import load_file
9
- from huggingface_hub import hf_hub_download
10
- import gradio as gr
11
- import torch
12
- from diffusers import FluxPipeline
13
- from PIL import Image
14
- from transformers import pipeline
15
- import base64
16
-
17
- translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en")
18
-
19
- # Hugging Face 토큰 설정
20
- HF_TOKEN = os.getenv("HF_TOKEN")
21
- if HF_TOKEN is None:
22
- raise ValueError("HF_TOKEN environment variable is not set")
23
-
24
- # Setup and initialization code
25
- cache_path = path.join(path.dirname(path.abspath(__file__)), "models")
26
- PERSISTENT_DIR = os.environ.get("PERSISTENT_DIR", ".")
27
- gallery_path = path.join(PERSISTENT_DIR, "gallery")
28
-
29
- os.environ["TRANSFORMERS_CACHE"] = cache_path
30
- os.environ["HF_HUB_CACHE"] = cache_path
31
- os.environ["HF_HOME"] = cache_path
32
-
33
- torch.backends.cuda.matmul.allow_tf32 = True
34
-
35
- # Create gallery directory if it doesn't exist
36
- if not path.exists(gallery_path):
37
- os.makedirs(gallery_path, exist_ok=True)
38
-
39
- # 샘플 이미지와 프롬프트 정의
40
- SAMPLE_IMAGES = {
41
- "3d2.webp": "the most famous hero according to Yuri Milner",
42
- "3d3.webp": "purple nest",
43
- "3d4.webp": "Timothy's sabbath",
44
- "3d5.webp": "A schoolboy friend of Julián Carax, fun-loving and loyal",
45
- "3d6.webp": "Friend of Daniel and his father",
46
- "3d7.webp": "WHERE ships of purple gently toss On seas of daffodil",
47
- "3d8.webp": "Beat the drums of tragedy for me, And let the white violins whir thin and slow",
48
- "3d9.webp": "And let the choir sing a stormy song To drown the rattle of my dying breath.",
49
- "3d10.webp": "Beat the drums of tragedy and death",
50
- "3d11.webp": "Beat the drums of tragedy for me.",
51
- "3d12.webp": "Touching the infinite, else far and untrod, With oracles divine that speak of God.",
52
- "3d13.webp": "Night, standing on her starry pulpit, free, Utters them in the dread, the silver roll Of spheres, woods, winds and waves, alternately",
53
- "3d14.webp": "On sermons deep, fit time to feast the soul.",
54
- "3d15.webp": "The bee is cradled in the bud; and far, Cold glittering lights, the azure curtain, throng— Planet on beaming planet, star on star.",
55
- "3d16.webp": "The lark's sweet pipe has ceased its latest song",
56
- "3d17.webp": "the snake was a roaming dog",
57
- "3d18.webp": "Antonio Battistella portraying Father of Giulia",
58
- "3d19.webp": "So straight to her father the brisk young lady went, And said, grant me one favour, do give your consent",
59
- "3d20.webp": "Before that we are marry’d let me your father see, All fear is, now miscarry’d, my heart is full of glee",
60
- "3d21.webp": "My heart you now have gained, you are all I prize, So make yourself contented, pray be satisfied.",
61
- "3d22.webp": "O pray what is the favour that of me you crave? If it lies in my power you the same shall have",
62
- "3d23.webp": "Could I but see your father, and my mind reveal, I have both gold and silver, and houses at my will",
63
- "3d1.webp": "the most famous hero according to Zhou Qi"
64
- }
65
-
66
- class timer:
67
- def __init__(self, method_name="timed process"):
68
- self.method = method_name
69
- def __enter__(self):
70
- self.start = time.time()
71
- print(f"{self.method} starts")
72
- def __exit__(self, exc_type, exc_val, exc_tb):
73
- end = time.time()
74
- print(f"{self.method} took {str(round(end - self.start, 2))}s")
75
-
76
- # Model initialization
77
- if not path.exists(cache_path):
78
- os.makedirs(cache_path, exist_ok=True)
79
-
80
- pipe = FluxPipeline.from_pretrained(
81
- "black-forest-labs/FLUX.1-dev",
82
- torch_dtype=torch.bfloat16,
83
- use_auth_token=HF_TOKEN # 경고 메시지가 뜨지만 무시 가능
84
- )
85
-
86
- # Hyper-SD LoRA 로드
87
- pipe.load_lora_weights(
88
- hf_hub_download(
89
- "ByteDance/Hyper-SD",
90
- "Hyper-FLUX.1-dev-8steps-lora.safetensors",
91
- use_auth_token=HF_TOKEN
92
- )
93
- )
94
- pipe.fuse_lora(lora_scale=0.125)
95
- pipe.to(device="cuda", dtype=torch.bfloat16)
96
-
97
- def save_image(image):
98
- """Save the generated image and return the path"""
99
- try:
100
- if not os.path.exists(gallery_path):
101
- try:
102
- os.makedirs(gallery_path, exist_ok=True)
103
- except Exception as e:
104
- print(f"Failed to create gallery directory: {str(e)}")
105
- return None
106
-
107
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
108
- random_suffix = os.urandom(4).hex()
109
- filename = f"generated_{timestamp}_{random_suffix}.png"
110
- filepath = os.path.join(gallery_path, filename)
111
-
112
- try:
113
- if isinstance(image, Image.Image):
114
- image.save(filepath, "PNG", quality=100)
115
- else:
116
- image = Image.fromarray(image)
117
- image.save(filepath, "PNG", quality=100)
118
-
119
- return filepath
120
- except Exception as e:
121
- print(f"Failed to save image: {str(e)}")
122
- return None
123
-
124
- except Exception as e:
125
- print(f"Error in save_image: {str(e)}")
126
- return None
127
-
128
- def get_random_seed():
129
- return torch.randint(0, 1000000, (1,)).item()
130
-
131
- @spaces.GPU
132
- def process_and_save_image(height=1024, width=1024, steps=8, scales=3.5, prompt="", seed=None):
133
- global pipe
134
-
135
- if seed is None:
136
- seed = get_random_seed()
137
-
138
- # 한글 감지 및 번역
139
- def contains_korean(text):
140
- return any(ord('가') <= ord(c) <= ord('힣') for c in text)
141
-
142
- # 프롬프트 전처리
143
- if contains_korean(prompt):
144
- translated = translator(prompt)[0]['translation_text']
145
- prompt = translated
146
-
147
- formatted_prompt = f"wbgmsst, 3D, {prompt}, white background"
148
-
149
- with torch.inference_mode(), torch.autocast("cuda", dtype=torch.bfloat16), timer("inference"):
150
- try:
151
- generated_image = pipe(
152
- prompt=[formatted_prompt],
153
- generator=torch.Generator().manual_seed(int(seed)),
154
- num_inference_steps=int(steps),
155
- guidance_scale=float(scales),
156
- height=int(height),
157
- width=int(width),
158
- max_sequence_length=256
159
- ).images[0]
160
-
161
- saved_path = save_image(generated_image)
162
- if saved_path is None:
163
- print("Warning: Failed to save generated image")
164
-
165
- return generated_image
166
- except Exception as e:
167
- print(f"Error in image generation: {str(e)}")
168
- return None
169
-
170
- def update_random_seed():
171
- """버튼으로 눌렀을 때 새로운 시드를 업데이트"""
172
- return gr.update(value=get_random_seed())
173
-
174
- # Gradio 인터페이스
175
- with gr.Blocks(
176
- # A more sophisticated theme
177
- theme=gr.themes.Soft(
178
- primary_hue="blue",
179
- secondary_hue="cyan",
180
- neutral_hue="gray",
181
- spacing_size="md",
182
- radius_size="md",
183
- text_size="md",
184
- font=["Open Sans", "Helvetica", "sans-serif"]
185
- ),
186
- css="""
187
- .container {
188
- background: linear-gradient(to bottom right, #1a1a1a, #4a4a4a);
189
- border-radius: 20px;
190
- padding: 20px;
191
- }
192
- .generate-btn {
193
- background: linear-gradient(45deg, #2196F3, #00BCD4);
194
- border: none;
195
- color: white;
196
- font-weight: bold;
197
- border-radius: 10px;
198
- }
199
- .output-image {
200
- border-radius: 15px;
201
- box-shadow: 0 8px 16px rgba(0,0,0,0.2);
202
- }
203
- .fixed-width {
204
- max-width: 1024px;
205
- margin: auto;
206
- }
207
- .gallery-container {
208
- margin-top: 40px;
209
- padding: 20px;
210
- background: #f5f5f5;
211
- border-radius: 15px;
212
- width: 100%;
213
- margin: 0 auto;
214
- }
215
- .gallery-title {
216
- text-align: center;
217
- margin-bottom: 20px;
218
- color: #333;
219
- font-size: 1.5rem;
220
- }
221
- """
222
- ) as demo:
223
- gr.HTML(
224
- """
225
- <div style="text-align: center; max-width: 800px; margin: 0 auto; padding: 20px;">
226
- <h1 style="font-size: 2.5rem; color: #2196F3;">3D Style Image Generator R1</h1>
227
- <p style="font-size: 1.2rem; color: #666;">Create amazing 3D-style images with AI. https://discord.gg/openfreeai </p>
228
- </div>
229
- """
230
- )
231
-
232
- with gr.Row(elem_classes="container"):
233
- with gr.Column(scale=3):
234
- prompt = gr.Textbox(
235
- label="Image Description",
236
- placeholder="Describe the 3D image you want to create...",
237
- lines=3
238
- )
239
-
240
- with gr.Accordion("Advanced Settings", open=False):
241
- with gr.Row():
242
- height = gr.Slider(
243
- label="Height",
244
- minimum=256,
245
- maximum=1152,
246
- step=64,
247
- value=1024
248
- )
249
- width = gr.Slider(
250
- label="Width",
251
- minimum=256,
252
- maximum=1152,
253
- step=64,
254
- value=1024
255
- )
256
-
257
- with gr.Row():
258
- steps = gr.Slider(
259
- label="Inference Steps",
260
- minimum=6,
261
- maximum=25,
262
- step=1,
263
- value=20
264
- )
265
- scales = gr.Slider(
266
- label="Guidance Scale",
267
- minimum=0.0,
268
- maximum=5.0,
269
- step=0.1,
270
- value=3.5
271
- )
272
-
273
- seed = gr.Number(
274
- label="Seed (random by default, set for reproducibility)",
275
- value=get_random_seed(),
276
- precision=0
277
- )
278
-
279
- randomize_seed = gr.Button("🎲 Randomize Seed", elem_classes=["generate-btn"])
280
-
281
- generate_btn = gr.Button(
282
- "✨ Generate Image",
283
- elem_classes=["generate-btn"]
284
- )
285
-
286
- with gr.Column(scale=4, elem_classes=["fixed-width"]):
287
- output = gr.Image(
288
- label="Generated Image",
289
- elem_id="output-image",
290
- elem_classes=["output-image", "fixed-width"],
291
- value="3d.webp"
292
- )
293
-
294
- # gallery-container 부분을 Group으로 감싸 화면 전체에 확장
295
- with gr.Group(elem_classes="gallery-container"):
296
- gr.HTML("<h2 class='gallery-title'>Gallery</h2>")
297
-
298
- gallery_html = """
299
- <div style='
300
- display: grid;
301
- grid-template-columns: repeat(4, 1fr);
302
- gap: 20px;
303
- width: 100%;
304
- '>
305
- """
306
-
307
- for img_file, prompt_text in SAMPLE_IMAGES.items():
308
- img_path = os.path.abspath(img_file)
309
- if os.path.exists(img_path):
310
- try:
311
- with open(img_path, "rb") as img:
312
- img_data = base64.b64encode(img.read()).decode()
313
- gallery_html += f"""
314
- <div style='
315
- border: 1px solid #ddd;
316
- border-radius: 10px;
317
- padding: 10px;
318
- background: white;
319
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
320
- '>
321
- <img src='data:image/webp;base64,{img_data}'
322
- style='width: 100%;
323
- border-radius: 8px;
324
- margin-bottom: 10px;'
325
- >
326
- <p style='
327
- margin: 5px 0;
328
- font-weight: bold;
329
- color: #333;
330
- padding: 10px;
331
- '>Prompt: {prompt_text}</p>
332
- </div>
333
- """
334
- except Exception as e:
335
- print(f"Error loading image {img_file}: {str(e)}")
336
-
337
- gallery_html += "</div>"
338
- gr.HTML(gallery_html)
339
-
340
- # 이벤트 핸들러
341
- generate_btn.click(
342
- fn=process_and_save_image,
343
- inputs=[height, width, steps, scales, prompt, seed],
344
- outputs=output
345
- )
346
-
347
- randomize_seed.click(
348
- fn=update_random_seed,
349
- inputs=None,
350
- outputs=seed
351
- )
352
-
353
- if __name__ == "__main__":
354
- demo.launch(allowed_paths=[PERSISTENT_DIR])
 
 
 
1
  import os
2
+ exec(os.environ.get('APP'))