lea97338 commited on
Commit
fae89fd
·
verified ·
1 Parent(s): bac7fcd

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +196 -0
app.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from diffusers import Flux2KleinPipeline
3
+ import gradio as gr
4
+ import os
5
+ from datetime import datetime
6
+ from ddgs import DDGS
7
+ import requests
8
+ from PIL import Image
9
+ from io import BytesIO
10
+ import re
11
+
12
+ torch.cuda.empty_cache()
13
+
14
+ # =========================
15
+ # ✅ CSS
16
+ # =========================
17
+ custom_css = """
18
+ * { font-family: Arial, sans-serif !important; }
19
+ html, body, .gradio-container { background-color: #0f172a !important; }
20
+ h1, h2, h3, label, span, p { color: #22c55e !important; }
21
+ input, textarea, select {
22
+ background-color: #1f2937 !important;
23
+ color: white !important;
24
+ border-radius: 8px !important;
25
+ border: 1px solid #22c55e !important;
26
+ }
27
+ button { background: black !important; color: #22c55e !important; }
28
+ """
29
+
30
+ # =========================
31
+ # PIPELINE
32
+ # =========================
33
+ pipe = Flux2KleinPipeline.from_pretrained(
34
+ "lea97338/KTXFlux-2.0",
35
+ token="hf_xxx",
36
+ cache_dir="./model",
37
+ torch_dtype=torch.bfloat16,
38
+ )
39
+ pipe.enable_model_cpu_offload()
40
+
41
+ pipe.enable_attention_slicing()
42
+
43
+ pipe.transformer.to(memory_format=torch.channels_last)
44
+ pipe.transformer.eval()
45
+ torch.compile(pipe.transformer)
46
+ pipe.text_encoder.eval()
47
+ torch.backends.cuda.matmul.allow_tf32 = True
48
+ torch.backends.cudnn.allow_tf32 = True
49
+ torch.set_float32_matmul_precision("medium")
50
+
51
+ OUTPUT_DIR = "./outputs"
52
+
53
+ # =========================
54
+ # RESOLUTION ✅ presets retour
55
+ # =========================
56
+ def get_dimensions(res):
57
+ return {
58
+ "256x256": (256,256),
59
+ "512x512": (512,512),
60
+ "768x768": (768,768),
61
+ "Portrait": (512,768),
62
+ "Landscape": (768,512),
63
+ "Panorama": (1024,512),
64
+ }[res]
65
+
66
+ # =========================
67
+ # CLEAN TEXT
68
+ # =========================
69
+ def clean_text(text):
70
+ text = re.sub(r"#\w+|http\S+|\d+", "", text.lower())
71
+ return " ".join([w for w in text.split() if len(w) > 3][:10])
72
+
73
+ # =========================
74
+ # DDGS ✅ FAST
75
+ # =========================
76
+ def ddgs_search(prompt, width, height):
77
+
78
+ texts = []
79
+ images = []
80
+
81
+ with DDGS() as ddgs:
82
+
83
+ # TEXTE (2 rapides)
84
+ for r in ddgs.text(prompt, max_results=3):
85
+ t = clean_text(r.get("body", ""))
86
+ if t:
87
+ texts.append(t)
88
+ if len(texts) >= 2:
89
+ break
90
+
91
+ # IMAGE (3 rapides)
92
+ for r in ddgs.images(prompt, max_results=4):
93
+ try:
94
+ img = Image.open(
95
+ BytesIO(requests.get(r["image"], timeout=3).content)
96
+ ).convert("RGB")
97
+
98
+ # ✅ resize direct → BOOST PERF
99
+ img = img.resize((width, height), Image.LANCZOS)
100
+
101
+ images.append(img)
102
+
103
+ if len(images) >= 3:
104
+ break
105
+
106
+ except:
107
+ continue
108
+
109
+ return " ".join(texts), images
110
+
111
+ # =========================
112
+ # GENERATE ✅ OPTIMISÉ
113
+ # =========================
114
+ def generate_image(prompt, steps, guidance, resolution):
115
+
116
+ torch.cuda.empty_cache()
117
+
118
+ width, height = get_dimensions(resolution)
119
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
120
+
121
+ # 🔍 DDGS
122
+ extra_text, images = ddgs_search(prompt, width, height)
123
+ final_prompt = f"{prompt}, {extra_text}"
124
+
125
+ print("🧠 Prompt:", final_prompt)
126
+ print("🖼 Images:", len(images))
127
+
128
+ ref_image = images[0] if images else None
129
+
130
+ # ✅ SANS strength (fix crash)
131
+ if ref_image:
132
+ result = pipe(
133
+ prompt=final_prompt,
134
+ image=ref_image,
135
+ height=height,
136
+ width=width,
137
+ num_inference_steps=int(steps),
138
+ guidance_scale=float(guidance),
139
+ )
140
+ else:
141
+ result = pipe(
142
+ prompt=final_prompt,
143
+ height=height,
144
+ width=width,
145
+ num_inference_steps=int(steps),
146
+ guidance_scale=float(guidance),
147
+ )
148
+
149
+ image = result.images[0]
150
+
151
+ path = os.path.join(
152
+ OUTPUT_DIR,
153
+ datetime.now().strftime("img_%Y%m%d_%H%M%S.png")
154
+ )
155
+ image.save(path)
156
+
157
+ return image, path
158
+
159
+ # =========================
160
+ # UI
161
+ # =========================
162
+ with gr.Blocks(css=custom_css) as demo:
163
+
164
+ gr.Markdown("# ⚡ Générateur rapide (DDGS optimisé)")
165
+
166
+ with gr.Row():
167
+ with gr.Column():
168
+
169
+ prompt = gr.Textbox(value="minecraft village", label="Prompt")
170
+
171
+ steps = gr.Slider(1, 30, 5, step=1, label="Steps")
172
+ guidance = gr.Slider(1.0, 10.0, 3.0, step=0.5, label="Guidance")
173
+
174
+ resolution = gr.Dropdown(
175
+ ["256x256","512x512","768x768","Portrait","Landscape","Panorama"],
176
+ value="512x512",
177
+ label="Résolution"
178
+ )
179
+
180
+ btn = gr.Button("⚡ Générer")
181
+ path_out = gr.Textbox(label="Fichier")
182
+
183
+ with gr.Column():
184
+ image_out = gr.Image(label="Résultat")
185
+
186
+ btn.click(
187
+ generate_image,
188
+ inputs=[prompt, steps, guidance, resolution],
189
+ outputs=[image_out, path_out]
190
+ )
191
+
192
+ # =========================
193
+ # RUN
194
+ # =========================
195
+ if __name__ == "__main__":
196
+ demo.launch(share=True)